Rev 71 | Rev 81 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
68 | daniel-mar | 1 | unit UD2_Obj; |
2 | |||
3 | interface |
||
4 | |||
5 | {$IF CompilerVersion >= 25.0} |
||
6 | {$LEGACYIFEND ON} |
||
7 | {$IFEND} |
||
8 | |||
70 | daniel-mar | 9 | {$INCLUDE 'UserDetect2.inc'} |
10 | |||
68 | daniel-mar | 11 | uses |
71 | daniel-mar | 12 | Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf, |
13 | UD2_PluginStatus; |
||
68 | daniel-mar | 14 | |
15 | const |
||
69 | daniel-mar | 16 | cchBufferSize = 32768; |
68 | daniel-mar | 17 | |
18 | type |
||
19 | TUD2Plugin = class(TObject) |
||
20 | protected |
||
21 | FDetectedIdentifications: TObjectList{<TUD2IdentificationEntry>}; |
||
22 | public |
||
23 | PluginDLL: string; |
||
24 | PluginGUID: TGUID; |
||
25 | PluginName: WideString; |
||
26 | PluginVendor: WideString; |
||
27 | PluginVersion: WideString; |
||
28 | IdentificationMethodName: WideString; |
||
70 | daniel-mar | 29 | |
30 | // ONLY contains the non-failure status code of IdentificationStringW |
||
31 | IdentificationProcedureStatusCode: UD2_STATUS; |
||
32 | IdentificationProcedureStatusCodeDescribed: WideString; |
||
33 | |||
69 | daniel-mar | 34 | Time: Cardinal; |
68 | daniel-mar | 35 | function PluginGUIDString: string; |
36 | property DetectedIdentifications: TObjectList{<TUD2IdentificationEntry>} |
||
37 | read FDetectedIdentifications; |
||
38 | destructor Destroy; override; |
||
39 | constructor Create; |
||
40 | procedure AddIdentification(IdStr: WideString); |
||
41 | end; |
||
42 | |||
43 | TUD2IdentificationEntry = class(TObject) |
||
44 | private |
||
45 | FIdentificationString: WideString; |
||
46 | FPlugin: TUD2Plugin; |
||
47 | public |
||
48 | property IdentificationString: WideString read FIdentificationString; |
||
49 | property Plugin: TUD2Plugin read FPlugin; |
||
50 | function GetPrimaryIdName: WideString; |
||
51 | procedure GetIdNames(sl: TStrings); |
||
52 | constructor Create(AIdentificationString: WideString; APlugin: TUD2Plugin); |
||
53 | end; |
||
54 | |||
55 | TUD2 = class(TObject) |
||
56 | private |
||
70 | daniel-mar | 57 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
68 | daniel-mar | 58 | FGUIDLookup: TStrings; |
70 | daniel-mar | 59 | {$ENDIF} |
68 | daniel-mar | 60 | protected |
61 | FLoadedPlugins: TObjectList{<TUD2Plugin>}; |
||
62 | FIniFile: TMemIniFile; |
||
63 | FErrors: TStrings; |
||
64 | FIniFileName: string; |
||
65 | public |
||
66 | property IniFileName: string read FIniFileName; |
||
67 | property Errors: TStrings read FErrors; |
||
68 | property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins; |
||
69 | property IniFile: TMemIniFile read FIniFile; |
||
70 | procedure GetCommandList(ShortTaskName: string; outSL: TStrings); |
||
80 | daniel-mar | 71 | procedure HandlePluginDir(APluginDir, AFileMask: string); |
68 | daniel-mar | 72 | procedure GetTaskListing(outSL: TStrings); |
73 | constructor Create(AIniFileName: string); |
||
74 | destructor Destroy; override; |
||
75 | function TaskExists(ShortTaskName: string): boolean; |
||
80 | daniel-mar | 76 | function ReadMetatagString(ShortTaskName, MetatagName: string; DefaultVal: string): string; |
77 | function ReadMetatagBool(ShortTaskName, MetatagName: string; DefaultVal: string): boolean; |
||
68 | daniel-mar | 78 | function GetTaskName(AShortTaskName: string): string; |
71 | daniel-mar | 79 | class function GenericErrorLookup(grStatus: UD2_STATUS): string; |
68 | daniel-mar | 80 | end; |
81 | |||
82 | implementation |
||
83 | |||
84 | uses |
||
70 | daniel-mar | 85 | UD2_Utils; |
68 | daniel-mar | 86 | |
69 | daniel-mar | 87 | type |
88 | TUD2PluginLoader = class(TThread) |
||
89 | protected |
||
90 | dllFile: string; |
||
91 | lngID: LANGID; |
||
92 | procedure Execute; override; |
||
70 | daniel-mar | 93 | function HandleDLL: boolean; |
69 | daniel-mar | 94 | public |
95 | pl: TUD2Plugin; |
||
96 | Errors: TStringList; |
||
97 | constructor Create(Suspended: boolean; DLL: string; alngid: LANGID); |
||
98 | destructor Destroy; override; |
||
99 | end; |
||
100 | |||
71 | daniel-mar | 101 | class function TUD2.GenericErrorLookup(grStatus: UD2_STATUS): string; |
68 | daniel-mar | 102 | resourcestring |
80 | daniel-mar | 103 | LNG_STATUS_OK_UNSPECIFIED = 'Success (Unspecified)'; |
104 | LNG_STATUS_OK_SINGLELINE = 'Success (One identifier returned)'; |
||
105 | LNG_STATUS_OK_MULTILINE = 'Success (Multiple identifiers returned)'; |
||
106 | LNG_UNKNOWN_SUCCESS = 'Success (Unknown status code %s)'; |
||
69 | daniel-mar | 107 | |
80 | daniel-mar | 108 | LNG_STATUS_NOTAVAIL_UNSPECIFIED = 'Not available (Unspecified)'; |
109 | LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED = 'Not available (Operating system not supported)'; |
||
110 | LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED = 'Not available (Hardware not supported)'; |
||
111 | LNG_STATUS_NOTAVAIL_NO_ENTITIES = 'Not available (No entities to identify)'; |
||
112 | LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE = 'Not available (A Windows API call failed. Message: %s)'; |
||
113 | LNG_UNKNOWN_NOTAVAIL = 'Not available (Unknown status code %s)'; |
||
69 | daniel-mar | 114 | |
80 | daniel-mar | 115 | LNG_STATUS_ERROR_UNSPECIFIED = 'Error (Unspecified)'; |
116 | LNG_STATUS_ERROR_BUFFER_TOO_SMALL = 'Error (The provided buffer is too small!)'; |
||
117 | LNG_STATUS_ERROR_INVALID_ARGS = 'Error (The function received invalid arguments!)'; |
||
118 | LNG_STATUS_ERROR_PLUGIN_NOT_LICENSED = 'Error (The plugin is not licensed)'; |
||
119 | LNG_UNKNOWN_FAILED = 'Error (Unknown status code %s)'; |
||
69 | daniel-mar | 120 | |
71 | daniel-mar | 121 | LNG_UNKNOWN_STATUS = 'Unknown status code with unexpected category: %s'; |
68 | daniel-mar | 122 | begin |
71 | daniel-mar | 123 | if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_UNSPECIFIED, false) then result := LNG_STATUS_OK_UNSPECIFIED |
124 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_SINGLELINE, false) then result := LNG_STATUS_OK_SINGLELINE |
||
125 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_MULTILINE, false) then result := LNG_STATUS_OK_MULTILINE |
||
69 | daniel-mar | 126 | |
71 | daniel-mar | 127 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_UNSPECIFIED, false) then result := LNG_STATUS_NOTAVAIL_UNSPECIFIED |
128 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED, false) then result := LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED |
||
129 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_HW_NOT_SUPPORTED, false) then result := LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED |
||
130 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_NO_ENTITIES, false) then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES |
||
131 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE, false) then result := Format(LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE, [FormatOSError(grStatus.dwExtraInfo)]) |
||
69 | daniel-mar | 132 | |
71 | daniel-mar | 133 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_UNSPECIFIED, false) then result := LNG_STATUS_ERROR_UNSPECIFIED |
134 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_BUFFER_TOO_SMALL, false) then result := LNG_STATUS_ERROR_BUFFER_TOO_SMALL |
||
135 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_INVALID_ARGS, false) then result := LNG_STATUS_ERROR_INVALID_ARGS |
||
136 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_PLUGIN_NOT_LICENSED, false) then result := LNG_STATUS_ERROR_PLUGIN_NOT_LICENSED |
||
69 | daniel-mar | 137 | |
71 | daniel-mar | 138 | else if grStatus.wCategory = UD2_STATUSCAT_SUCCESS then result := Format(LNG_UNKNOWN_SUCCESS, [UD2_STATUS_FormatStatusCode(grStatus)]) |
139 | else if grStatus.wCategory = UD2_STATUSCAT_NOT_AVAIL then result := Format(LNG_UNKNOWN_NOTAVAIL, [UD2_STATUS_FormatStatusCode(grStatus)]) |
||
140 | else if grStatus.wCategory = UD2_STATUSCAT_FAILED then result := Format(LNG_UNKNOWN_FAILED, [UD2_STATUS_FormatStatusCode(grStatus)]) |
||
141 | else result := Format(LNG_UNKNOWN_STATUS, [UD2_STATUS_FormatStatusCode(grStatus)]); |
||
68 | daniel-mar | 142 | end; |
143 | |||
144 | { TUD2Plugin } |
||
145 | |||
146 | function TUD2Plugin.PluginGUIDString: string; |
||
147 | begin |
||
148 | result := UpperCase(GUIDToString(PluginGUID)); |
||
149 | end; |
||
150 | |||
151 | procedure TUD2Plugin.AddIdentification(IdStr: WideString); |
||
152 | begin |
||
153 | DetectedIdentifications.Add(TUD2IdentificationEntry.Create(IdStr, Self)) |
||
154 | end; |
||
155 | |||
156 | destructor TUD2Plugin.Destroy; |
||
157 | begin |
||
158 | DetectedIdentifications.Free; |
||
159 | inherited; |
||
160 | end; |
||
161 | |||
162 | constructor TUD2Plugin.Create; |
||
163 | begin |
||
164 | inherited Create; |
||
165 | FDetectedIdentifications := TObjectList{<TUD2IdentificationEntry>}.Create(true); |
||
166 | end; |
||
167 | |||
168 | { TUD2IdentificationEntry } |
||
169 | |||
170 | function TUD2IdentificationEntry.GetPrimaryIdName: WideString; |
||
171 | begin |
||
172 | result := Plugin.IdentificationMethodName+':'+IdentificationString; |
||
173 | end; |
||
174 | |||
175 | procedure TUD2IdentificationEntry.GetIdNames(sl: TStrings); |
||
176 | begin |
||
177 | sl.Add(GetPrimaryIdName); |
||
178 | sl.Add(UpperCase(Plugin.IdentificationMethodName)+':'+IdentificationString); |
||
179 | sl.Add(LowerCase(Plugin.IdentificationMethodName)+':'+IdentificationString); |
||
180 | sl.Add(UpperCase(Plugin.PluginGUIDString)+':'+IdentificationString); |
||
181 | sl.Add(LowerCase(Plugin.PluginGUIDString)+':'+IdentificationString); |
||
182 | end; |
||
183 | |||
184 | constructor TUD2IdentificationEntry.Create(AIdentificationString: WideString; |
||
185 | APlugin: TUD2Plugin); |
||
186 | begin |
||
187 | inherited Create; |
||
188 | FIdentificationString := AIdentificationString; |
||
189 | FPlugin := APlugin; |
||
190 | end; |
||
191 | |||
192 | { TUD2 } |
||
193 | |||
80 | daniel-mar | 194 | procedure TUD2.HandlePluginDir(APluginDir, AFileMask: string); |
69 | daniel-mar | 195 | Var |
196 | SR: TSearchRec; |
||
197 | path: string; |
||
70 | daniel-mar | 198 | pluginLoader: TUD2PluginLoader; |
69 | daniel-mar | 199 | tob: TObjectList; |
68 | daniel-mar | 200 | i: integer; |
70 | daniel-mar | 201 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
202 | sPluginID, prevDLL: string; |
||
203 | {$ENDIF} |
||
69 | daniel-mar | 204 | lngid: LANGID; |
80 | daniel-mar | 205 | maskpath: string; |
68 | daniel-mar | 206 | resourcestring |
207 | LNG_PLUGINS_SAME_GUID = 'Attention: The plugin "%s" and the plugin "%s" have the same identification GUID. The latter will not be loaded.'; |
||
208 | begin |
||
69 | daniel-mar | 209 | tob := TObjectList.Create; |
68 | daniel-mar | 210 | try |
69 | daniel-mar | 211 | tob.OwnsObjects := false; |
68 | daniel-mar | 212 | |
69 | daniel-mar | 213 | lngID := GetSystemDefaultLangID; |
68 | daniel-mar | 214 | |
80 | daniel-mar | 215 | path := APluginDir; |
216 | if path <> '' then path := IncludeTrailingPathDelimiter(path); |
||
217 | |||
218 | if FindFirst(path + AFileMask, 0, SR) = 0 then |
||
68 | daniel-mar | 219 | begin |
220 | try |
||
69 | daniel-mar | 221 | repeat |
222 | try |
||
80 | daniel-mar | 223 | tob.Add(TUD2PluginLoader.Create(false, path + sr.Name, lngid)); |
69 | daniel-mar | 224 | except |
225 | on E: Exception do |
||
226 | begin |
||
227 | MessageDlg(E.Message, mtError, [mbOK], 0); |
||
228 | end; |
||
229 | end; |
||
230 | until FindNext(SR) <> 0; |
||
68 | daniel-mar | 231 | finally |
69 | daniel-mar | 232 | FindClose(SR); |
68 | daniel-mar | 233 | end; |
234 | end; |
||
235 | |||
69 | daniel-mar | 236 | for i := 0 to tob.count-1 do |
68 | daniel-mar | 237 | begin |
70 | daniel-mar | 238 | pluginLoader := tob.items[i] as TUD2PluginLoader; |
239 | pluginLoader.WaitFor; |
||
240 | Errors.AddStrings(pluginLoader.Errors); |
||
241 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
||
242 | if Assigned(pluginLoader.pl) then |
||
68 | daniel-mar | 243 | begin |
70 | daniel-mar | 244 | sPluginID := GUIDToString(pluginLoader.pl.PluginGUID); |
245 | prevDLL := FGUIDLookup.Values[sPluginID]; |
||
246 | if (prevDLL <> '') and (prevDLL <> pluginLoader.pl.PluginDLL) then |
||
69 | daniel-mar | 247 | begin |
70 | daniel-mar | 248 | Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.pl.PluginDLL])); |
249 | pluginLoader.pl.Free; |
||
69 | daniel-mar | 250 | end |
251 | else |
||
252 | begin |
||
70 | daniel-mar | 253 | FGUIDLookup.Values[sPluginID] := pluginLoader.pl.PluginDLL; |
254 | LoadedPlugins.Add(pluginLoader.pl); |
||
69 | daniel-mar | 255 | end; |
68 | daniel-mar | 256 | end; |
70 | daniel-mar | 257 | {$ENDIF} |
258 | pluginLoader.Free; |
||
68 | daniel-mar | 259 | end; |
260 | finally |
||
69 | daniel-mar | 261 | tob.free; |
68 | daniel-mar | 262 | end; |
263 | end; |
||
264 | |||
265 | destructor TUD2.Destroy; |
||
266 | begin |
||
267 | FIniFile.Free; |
||
268 | FLoadedPlugins.Free; |
||
70 | daniel-mar | 269 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
68 | daniel-mar | 270 | FGUIDLookup.Free; |
70 | daniel-mar | 271 | {$ENDIF} |
68 | daniel-mar | 272 | FErrors.Free; |
273 | end; |
||
274 | |||
275 | constructor TUD2.Create(AIniFileName: string); |
||
276 | begin |
||
277 | FIniFileName := AIniFileName; |
||
278 | FLoadedPlugins := TObjectList{<TUD2Plugin>}.Create(true); |
||
279 | FIniFile := TMemIniFile.Create(IniFileName); |
||
70 | daniel-mar | 280 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
68 | daniel-mar | 281 | FGUIDLookup := TStringList.Create; |
70 | daniel-mar | 282 | {$ENDIF} |
68 | daniel-mar | 283 | FErrors := TStringList.Create; |
284 | end; |
||
285 | |||
286 | function TUD2.GetTaskName(AShortTaskName: string): string; |
||
69 | daniel-mar | 287 | resourcestring |
288 | LNG_NO_DESCRIPTION = '(%s)'; |
||
68 | daniel-mar | 289 | begin |
69 | daniel-mar | 290 | result := FIniFile.ReadString(AShortTaskName, 'Description', Format(LNG_NO_DESCRIPTION, [AShortTaskName])); |
68 | daniel-mar | 291 | end; |
292 | |||
293 | procedure TUD2.GetTaskListing(outSL: TStrings); |
||
294 | var |
||
295 | sl: TStringList; |
||
296 | i: integer; |
||
297 | desc: string; |
||
298 | begin |
||
299 | sl := TStringList.Create; |
||
300 | try |
||
301 | FIniFile.ReadSections(sl); |
||
302 | for i := 0 to sl.Count-1 do |
||
303 | begin |
||
304 | desc := GetTaskName(sl.Strings[i]); |
||
305 | outSL.Values[sl.Strings[i]] := desc; |
||
306 | end; |
||
307 | finally |
||
308 | sl.Free; |
||
309 | end; |
||
310 | end; |
||
311 | |||
312 | function TUD2.TaskExists(ShortTaskName: string): boolean; |
||
313 | begin |
||
314 | result := FIniFile.SectionExists(ShortTaskName); |
||
315 | end; |
||
316 | |||
317 | function TUD2.ReadMetatagString(ShortTaskName, MetatagName: string; |
||
318 | DefaultVal: string): string; |
||
319 | begin |
||
320 | result := IniFile.ReadString(ShortTaskName, MetatagName, DefaultVal); |
||
321 | end; |
||
322 | |||
323 | function TUD2.ReadMetatagBool(ShortTaskName, MetatagName: string; |
||
324 | DefaultVal: string): boolean; |
||
325 | begin |
||
326 | // DefaultVal is a string, because we want to allow an empty string, in case the |
||
327 | // user wishes an Exception in case the string is not a valid boolean string |
||
328 | result := BetterInterpreteBool(IniFile.ReadString(ShortTaskName, MetatagName, DefaultVal)); |
||
329 | end; |
||
330 | |||
331 | (* |
||
332 | |||
333 | NAMING EXAMPLE: ComputerName:ABC&&User:John=calc.exe |
||
334 | |||
335 | idTerm: ComputerName:ABC&&User:John |
||
336 | idName: ComputerName:ABC |
||
337 | IdMethodName: ComputerName |
||
338 | IdStr ABC |
||
339 | cmd: calc.exe |
||
340 | |||
341 | *) |
||
342 | |||
343 | procedure TUD2.GetCommandList(ShortTaskName: string; outSL: TStrings); |
||
344 | var |
||
345 | i, j: integer; |
||
346 | cmd: string; |
||
347 | idTerm, idName: WideString; |
||
348 | slSV, slIdNames: TStrings; |
||
349 | x: TArrayOfString; |
||
350 | nameVal: TArrayOfString; |
||
351 | FulfilsEverySubterm: boolean; |
||
352 | pl: TUD2Plugin; |
||
353 | ude: TUD2IdentificationEntry; |
||
354 | begin |
||
355 | SetLength(x, 0); |
||
356 | SetLength(nameVal, 0); |
||
357 | |||
358 | slIdNames := TStringList.Create; |
||
359 | try |
||
360 | for i := 0 to LoadedPlugins.Count-1 do |
||
361 | begin |
||
362 | pl := LoadedPlugins.Items[i] as TUD2Plugin; |
||
363 | for j := 0 to pl.DetectedIdentifications.Count-1 do |
||
364 | begin |
||
365 | ude := pl.DetectedIdentifications.Items[j] as TUD2IdentificationEntry; |
||
366 | ude.GetIdNames(slIdNames); |
||
367 | end; |
||
368 | end; |
||
369 | |||
370 | slSV := TStringList.Create; |
||
371 | try |
||
372 | FIniFile.ReadSectionValues(ShortTaskName, slSV); |
||
373 | for j := 0 to slSV.Count-1 do |
||
374 | begin |
||
375 | // We are doing the interpretation of the line ourselves, because |
||
376 | // TStringList.Values[] would not allow multiple command lines with the |
||
377 | // same key (idTerm) |
||
378 | nameVal := SplitString('=', slSV.Strings[j]); |
||
379 | idTerm := nameVal[0]; |
||
380 | cmd := nameVal[1]; |
||
381 | |||
382 | if Pos(':', idTerm) = 0 then Continue; |
||
383 | x := SplitString('&&', idTerm); |
||
384 | FulfilsEverySubterm := true; |
||
385 | for i := Low(x) to High(x) do |
||
386 | begin |
||
387 | idName := x[i]; |
||
388 | |||
389 | if slIdNames.IndexOf(idName) = -1 then |
||
390 | begin |
||
391 | FulfilsEverySubterm := false; |
||
392 | break; |
||
393 | end; |
||
394 | end; |
||
395 | |||
396 | if FulfilsEverySubterm then outSL.Add(cmd); |
||
397 | end; |
||
398 | finally |
||
399 | slSV.Free; |
||
400 | end; |
||
401 | finally |
||
402 | slIdNames.Free; |
||
403 | end; |
||
404 | end; |
||
405 | |||
69 | daniel-mar | 406 | { TUD2PluginLoader } |
407 | |||
408 | procedure TUD2PluginLoader.Execute; |
||
409 | begin |
||
410 | inherited; |
||
411 | |||
412 | HandleDLL; |
||
413 | end; |
||
414 | |||
415 | constructor TUD2PluginLoader.Create(Suspended: boolean; DLL: string; alngid: LANGID); |
||
416 | begin |
||
417 | inherited Create(Suspended); |
||
418 | dllfile := dll; |
||
419 | pl := nil; |
||
420 | Errors := TStringList.Create; |
||
421 | lngid := alngid; |
||
422 | end; |
||
423 | |||
424 | destructor TUD2PluginLoader.Destroy; |
||
425 | begin |
||
426 | Errors.Free; |
||
427 | inherited; |
||
428 | end; |
||
429 | |||
70 | daniel-mar | 430 | function TUD2PluginLoader.HandleDLL: boolean; |
69 | daniel-mar | 431 | var |
432 | sIdentifier: WideString; |
||
433 | sIdentifiers: TArrayOfString; |
||
434 | buf: array[0..cchBufferSize-1] of WideChar; |
||
435 | sPluginConfigFile: string; |
||
436 | iniConfig: TINIFile; |
||
437 | sOverrideGUID: string; |
||
438 | pluginIDfound: boolean; |
||
439 | pluginInterfaceID: TGUID; |
||
70 | daniel-mar | 440 | dllHandle: Cardinal; |
69 | daniel-mar | 441 | fPluginInterfaceID: TFuncPluginInterfaceID; |
442 | fPluginIdentifier: TFuncPluginIdentifier; |
||
443 | fPluginNameW: TFuncPluginNameW; |
||
444 | fPluginVendorW: TFuncPluginVendorW; |
||
445 | fPluginVersionW: TFuncPluginVersionW; |
||
446 | fIdentificationMethodNameW: TFuncIdentificationMethodNameW; |
||
447 | fIdentificationStringW: TFuncIdentificationStringW; |
||
448 | fCheckLicense: TFuncCheckLicense; |
||
70 | daniel-mar | 449 | fDescribeOwnStatusCodeW: TFuncDescribeOwnStatusCodeW; |
69 | daniel-mar | 450 | statusCode: UD2_STATUS; |
451 | i: integer; |
||
452 | starttime, endtime, time: cardinal; |
||
70 | daniel-mar | 453 | |
454 | function _ErrorLookup(statusCode: UD2_STATUS): WideString; |
||
455 | var |
||
456 | ret: BOOL; |
||
457 | begin |
||
458 | ret := fDescribeOwnStatusCodeW(@buf, cchBufferSize, statusCode, lngID); |
||
459 | if ret then |
||
460 | begin |
||
461 | result := PWideChar(@buf); |
||
462 | Exit; |
||
463 | end; |
||
464 | result := TUD2.GenericErrorLookup(statusCode); |
||
465 | end; |
||
466 | |||
69 | daniel-mar | 467 | resourcestring |
468 | LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded.'; |
||
469 | LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.'; |
||
80 | daniel-mar | 470 | LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this application.'; |
69 | daniel-mar | 471 | LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".'; |
472 | begin |
||
70 | daniel-mar | 473 | result := false; |
69 | daniel-mar | 474 | startTime := GetTickCount; |
475 | |||
476 | dllHandle := LoadLibrary(PChar(dllFile)); |
||
477 | if dllHandle = 0 then |
||
478 | begin |
||
479 | Errors.Add(Format(LNG_DLL_NOT_LOADED, [dllFile])); |
||
480 | end; |
||
481 | try |
||
482 | @fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID); |
||
483 | if not Assigned(fPluginInterfaceID) then |
||
484 | begin |
||
485 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile])); |
||
486 | Exit; |
||
487 | end; |
||
488 | pluginInterfaceID := fPluginInterfaceID(); |
||
489 | if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then |
||
490 | begin |
||
491 | Errors.Add(Format(LNG_INVALID_PLUGIN, [dllFile])); |
||
492 | Exit; |
||
493 | end; |
||
494 | |||
495 | @fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW); |
||
496 | if not Assigned(fIdentificationStringW) then |
||
497 | begin |
||
498 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile])); |
||
499 | Exit; |
||
500 | end; |
||
501 | |||
502 | @fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW); |
||
503 | if not Assigned(fPluginNameW) then |
||
504 | begin |
||
505 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile])); |
||
506 | Exit; |
||
507 | end; |
||
508 | |||
509 | @fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW); |
||
510 | if not Assigned(fPluginVendorW) then |
||
511 | begin |
||
512 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile])); |
||
513 | Exit; |
||
514 | end; |
||
515 | |||
516 | @fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW); |
||
517 | if not Assigned(fPluginVersionW) then |
||
518 | begin |
||
519 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile])); |
||
520 | Exit; |
||
521 | end; |
||
522 | |||
523 | @fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense); |
||
524 | if not Assigned(fCheckLicense) then |
||
525 | begin |
||
526 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile])); |
||
527 | Exit; |
||
528 | end; |
||
529 | |||
530 | @fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW); |
||
531 | if not Assigned(fIdentificationMethodNameW) then |
||
532 | begin |
||
533 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile])); |
||
534 | Exit; |
||
535 | end; |
||
536 | |||
70 | daniel-mar | 537 | @fDescribeOwnStatusCodeW := GetProcAddress(dllHandle, mnDescribeOwnStatusCodeW); |
538 | if not Assigned(fDescribeOwnStatusCodeW) then |
||
539 | begin |
||
540 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDescribeOwnStatusCodeW, dllFile])); |
||
541 | Exit; |
||
542 | end; |
||
543 | |||
69 | daniel-mar | 544 | pl := TUD2Plugin.Create; |
545 | pl.PluginDLL := dllFile; |
||
546 | |||
547 | pluginIDfound := false; |
||
548 | sPluginConfigFile := ChangeFileExt(dllFile, '.ini'); |
||
549 | if FileExists(sPluginConfigFile) then |
||
550 | begin |
||
551 | iniConfig := TIniFile.Create(sPluginConfigFile); |
||
552 | try |
||
553 | sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', ''); |
||
554 | if sOverrideGUID <> '' then |
||
555 | begin |
||
556 | pl.PluginGUID := StringToGUID(sOverrideGUID); |
||
557 | pluginIDfound := true; |
||
558 | end; |
||
559 | finally |
||
560 | iniConfig.Free; |
||
561 | end; |
||
562 | end; |
||
563 | |||
564 | if not pluginIDfound then |
||
565 | begin |
||
566 | @fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier); |
||
567 | if not Assigned(fPluginIdentifier) then |
||
568 | begin |
||
569 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile])); |
||
570 | Exit; |
||
571 | end; |
||
572 | pl.PluginGUID := fPluginIdentifier(); |
||
573 | end; |
||
574 | |||
575 | statusCode := fCheckLicense(nil); |
||
71 | daniel-mar | 576 | if statusCode.wCategory = UD2_STATUSCAT_FAILED then |
69 | daniel-mar | 577 | begin |
70 | daniel-mar | 578 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnCheckLicense, dllFile])); |
69 | daniel-mar | 579 | Exit; |
580 | end; |
||
581 | |||
582 | statusCode := fPluginNameW(@buf, cchBufferSize, lngID); |
||
71 | daniel-mar | 583 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginName := PWideChar(@buf) |
584 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginName := '' |
||
69 | daniel-mar | 585 | else |
586 | begin |
||
70 | daniel-mar | 587 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginNameW, dllFile])); |
69 | daniel-mar | 588 | Exit; |
589 | end; |
||
590 | |||
591 | statusCode := fPluginVendorW(@buf, cchBufferSize, lngID); |
||
71 | daniel-mar | 592 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginVendor := PWideChar(@buf) |
593 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginVendor := '' |
||
69 | daniel-mar | 594 | else |
595 | begin |
||
70 | daniel-mar | 596 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVendorW, dllFile])); |
69 | daniel-mar | 597 | Exit; |
598 | end; |
||
599 | |||
600 | statusCode := fPluginVersionW(@buf, cchBufferSize, lngID); |
||
71 | daniel-mar | 601 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginVersion := PWideChar(@buf) |
602 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginVersion := '' |
||
69 | daniel-mar | 603 | else |
604 | begin |
||
70 | daniel-mar | 605 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVersionW, dllFile])); |
69 | daniel-mar | 606 | Exit; |
607 | end; |
||
608 | |||
609 | statusCode := fIdentificationMethodNameW(@buf, cchBufferSize); |
||
71 | daniel-mar | 610 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.IdentificationMethodName := PWideChar(@buf) |
611 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.IdentificationMethodName := '' |
||
69 | daniel-mar | 612 | else |
613 | begin |
||
70 | daniel-mar | 614 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile])); |
69 | daniel-mar | 615 | Exit; |
616 | end; |
||
617 | |||
618 | statusCode := fIdentificationStringW(@buf, cchBufferSize); |
||
70 | daniel-mar | 619 | pl.IdentificationProcedureStatusCode := statusCode; |
620 | pl.IdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
||
71 | daniel-mar | 621 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then |
69 | daniel-mar | 622 | begin |
623 | sIdentifier := PWideChar(@buf); |
||
71 | daniel-mar | 624 | if UD2_STATUS_Equal(statusCode, UD2_STATUS_OK_MULTILINE, false) then |
69 | daniel-mar | 625 | begin |
70 | daniel-mar | 626 | // Multiple identifiers (e.g. multiple MAC addresses are delimited via UD2_MULTIPLE_ITEMS_DELIMITER) |
69 | daniel-mar | 627 | SetLength(sIdentifiers, 0); |
628 | sIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier); |
||
629 | for i := Low(sIdentifiers) to High(sIdentifiers) do |
||
630 | begin |
||
631 | pl.AddIdentification(sIdentifiers[i]); |
||
632 | end; |
||
633 | end |
||
634 | else |
||
635 | begin |
||
636 | pl.AddIdentification(sIdentifier); |
||
637 | end; |
||
638 | end |
||
71 | daniel-mar | 639 | else if statusCode.wCategory <> UD2_STATUSCAT_NOT_AVAIL then |
69 | daniel-mar | 640 | begin |
70 | daniel-mar | 641 | // Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationStringW, dllFile])); |
642 | Errors.Add(Format(LNG_METHOD_FAILURE, [pl.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile])); |
||
69 | daniel-mar | 643 | Exit; |
644 | end; |
||
645 | |||
646 | endtime := GetTickCount; |
||
647 | time := endtime - starttime; |
||
648 | if endtime < starttime then time := High(Cardinal) - time; |
||
649 | pl.time := time; |
||
650 | |||
70 | daniel-mar | 651 | result := true; |
69 | daniel-mar | 652 | finally |
70 | daniel-mar | 653 | if not result and Assigned(pl) then FreeAndNil(pl); |
69 | daniel-mar | 654 | FreeLibrary(dllHandle); |
655 | end; |
||
656 | end; |
||
657 | |||
68 | daniel-mar | 658 | end. |