Rev 81 | Rev 83 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 81 | Rev 82 | ||
---|---|---|---|
Line 6... | Line 6... | ||
6 | {$LEGACYIFEND ON} |
6 | {$LEGACYIFEND ON} |
7 | {$IFEND} |
7 | {$IFEND} |
8 | 8 | ||
9 | {$INCLUDE 'UserDetect2.inc'} |
9 | {$INCLUDE 'UserDetect2.inc'} |
10 | 10 | ||
11 | {$WARN UNSAFE_CODE OFF} |
- | |
12 | {$WARN UNSAFE_TYPE OFF} |
- | |
13 | - | ||
14 | uses |
11 | uses |
15 | Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf, |
12 | Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf, |
16 | UD2_PluginStatus; |
13 | UD2_PluginStatus; |
17 | 14 | ||
18 | const |
15 | const |
Line 21... | Line 18... | ||
21 | type |
18 | type |
22 | TUD2Plugin = class(TObject) |
19 | TUD2Plugin = class(TObject) |
23 | protected |
20 | protected |
24 | FDetectedIdentifications: TObjectList{<TUD2IdentificationEntry>}; |
21 | FDetectedIdentifications: TObjectList{<TUD2IdentificationEntry>}; |
25 | public |
22 | public |
- | 23 | // This flag will be set if "AutoOSNotSupportedCompatibility" of the INI manifest had to be enforced/used |
|
- | 24 | OSNotSupportedEnforced: boolean; |
|
- | 25 | ||
26 | PluginDLL: string; |
26 | PluginDLL: string; |
27 | PluginGUID: TGUID; |
27 | PluginGUID: TGUID; |
28 | PluginName: WideString; |
28 | PluginName: WideString; |
29 | PluginVendor: WideString; |
29 | PluginVendor: WideString; |
30 | PluginVersion: WideString; |
30 | PluginVersion: WideString; |
Line 68... | Line 68... | ||
68 | public |
68 | public |
69 | property IniFileName: string read FIniFileName; |
69 | property IniFileName: string read FIniFileName; |
70 | property Errors: TStrings read FErrors; |
70 | property Errors: TStrings read FErrors; |
71 | property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins; |
71 | property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins; |
72 | property IniFile: TMemIniFile read FIniFile; |
72 | property IniFile: TMemIniFile read FIniFile; |
73 | - | ||
74 | procedure GetAllIdNames(outSL: TStrings); |
73 | procedure GetAllIdNames(outSL: TStrings); |
75 | function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; |
74 | function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; |
76 | - | ||
77 | - | ||
78 | procedure GetCommandList(ShortTaskName: string; outSL: TStrings); |
75 | procedure GetCommandList(ShortTaskName: string; outSL: TStrings); |
79 | procedure HandlePluginDir(APluginDir, AFileMask: string); |
76 | procedure HandlePluginDir(APluginDir, AFileMask: string); |
80 | procedure GetTaskListing(outSL: TStrings); |
77 | procedure GetTaskListing(outSL: TStrings); |
81 | constructor Create(AIniFileName: string); |
78 | constructor Create(AIniFileName: string); |
82 | destructor Destroy; override; |
79 | destructor Destroy; override; |
Line 118... | Line 115... | ||
118 | LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED = 'Not available (Hardware not supported)'; |
115 | LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED = 'Not available (Hardware not supported)'; |
119 | LNG_STATUS_NOTAVAIL_NO_ENTITIES = 'Not available (No entities to identify)'; |
116 | LNG_STATUS_NOTAVAIL_NO_ENTITIES = 'Not available (No entities to identify)'; |
120 | LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE = 'Not available (A Windows API call failed. Message: %s)'; |
117 | LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE = 'Not available (A Windows API call failed. Message: %s)'; |
121 | LNG_UNKNOWN_NOTAVAIL = 'Not available (Unknown status code %s)'; |
118 | LNG_UNKNOWN_NOTAVAIL = 'Not available (Unknown status code %s)'; |
122 | 119 | ||
123 | LNG_STATUS_ERROR_UNSPECIFIED = 'Error (Unspecified)'; |
120 | LNG_STATUS_FAILURE_UNSPECIFIED = 'Error (Unspecified)'; |
124 | LNG_STATUS_ERROR_BUFFER_TOO_SMALL = 'Error (The provided buffer is too small!)'; |
121 | LNG_STATUS_FAILURE_BUFFER_TOO_SMALL = 'Error (The provided buffer is too small!)'; |
125 | LNG_STATUS_ERROR_INVALID_ARGS = 'Error (The function received invalid arguments!)'; |
122 | LNG_STATUS_FAILURE_INVALID_ARGS = 'Error (The function received invalid arguments!)'; |
126 | LNG_STATUS_ERROR_PLUGIN_NOT_LICENSED = 'Error (The plugin is not licensed)'; |
123 | LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED = 'Error (The plugin is not licensed)'; |
- | 124 | LNG_STATUS_FAILURE_NO_RETURNED_VALUE = 'Error (Plugin did not return a status)'; |
|
- | 125 | LNG_STATUS_FAILURE_CATCHED_EXCEPTION = 'Error (Catched unexpected Exception)'; |
|
127 | LNG_UNKNOWN_FAILED = 'Error (Unknown status code %s)'; |
126 | LNG_UNKNOWN_FAILED = 'Error (Unknown status code %s)'; |
128 | 127 | ||
129 | LNG_UNKNOWN_STATUS = 'Unknown status code with unexpected category: %s'; |
128 | LNG_UNKNOWN_STATUS = 'Unknown status code with unexpected category: %s'; |
130 | begin |
129 | begin |
131 | if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_UNSPECIFIED, false) then result := LNG_STATUS_OK_UNSPECIFIED |
130 | if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_UNSPECIFIED, false) then result := LNG_STATUS_OK_UNSPECIFIED |
Line 136... | Line 135... | ||
136 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED, false) then result := LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED |
135 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED, false) then result := LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED |
137 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_HW_NOT_SUPPORTED, false) then result := LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED |
136 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_HW_NOT_SUPPORTED, false) then result := LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED |
138 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_NO_ENTITIES, false) then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES |
137 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_NO_ENTITIES, false) then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES |
139 | 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)]) |
138 | 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)]) |
140 | 139 | ||
141 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_UNSPECIFIED, false) then result := LNG_STATUS_ERROR_UNSPECIFIED |
140 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_UNSPECIFIED, false) then result := LNG_STATUS_FAILURE_UNSPECIFIED |
142 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_BUFFER_TOO_SMALL, false) then result := LNG_STATUS_ERROR_BUFFER_TOO_SMALL |
141 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_BUFFER_TOO_SMALL, false) then result := LNG_STATUS_FAILURE_BUFFER_TOO_SMALL |
143 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_INVALID_ARGS, false) then result := LNG_STATUS_ERROR_INVALID_ARGS |
142 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_INVALID_ARGS, false) then result := LNG_STATUS_FAILURE_INVALID_ARGS |
144 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_PLUGIN_NOT_LICENSED, false) then result := LNG_STATUS_ERROR_PLUGIN_NOT_LICENSED |
143 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_PLUGIN_NOT_LICENSED, false) then result := LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED |
- | 144 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_NO_RETURNED_VALUE, false) then result := LNG_STATUS_FAILURE_NO_RETURNED_VALUE |
|
- | 145 | else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_CATCHED_EXCEPTION, false) then result := LNG_STATUS_FAILURE_CATCHED_EXCEPTION |
|
145 | 146 | ||
146 | else if grStatus.wCategory = UD2_STATUSCAT_SUCCESS then result := Format(LNG_UNKNOWN_SUCCESS, [UD2_STATUS_FormatStatusCode(grStatus)]) |
147 | else if grStatus.wCategory = UD2_STATUSCAT_SUCCESS then result := Format(LNG_UNKNOWN_SUCCESS, [UD2_STATUS_FormatStatusCode(grStatus)]) |
147 | else if grStatus.wCategory = UD2_STATUSCAT_NOT_AVAIL then result := Format(LNG_UNKNOWN_NOTAVAIL, [UD2_STATUS_FormatStatusCode(grStatus)]) |
148 | else if grStatus.wCategory = UD2_STATUSCAT_NOT_AVAIL then result := Format(LNG_UNKNOWN_NOTAVAIL, [UD2_STATUS_FormatStatusCode(grStatus)]) |
148 | else if grStatus.wCategory = UD2_STATUSCAT_FAILED then result := Format(LNG_UNKNOWN_FAILED, [UD2_STATUS_FormatStatusCode(grStatus)]) |
149 | else if grStatus.wCategory = UD2_STATUSCAT_FAILED then result := Format(LNG_UNKNOWN_FAILED, [UD2_STATUS_FormatStatusCode(grStatus)]) |
149 | else result := Format(LNG_UNKNOWN_STATUS, [UD2_STATUS_FormatStatusCode(grStatus)]); |
150 | else result := Format(LNG_UNKNOWN_STATUS, [UD2_STATUS_FormatStatusCode(grStatus)]); |
Line 181... | Line 182... | ||
181 | end; |
182 | end; |
182 | 183 | ||
183 | procedure TUD2IdentificationEntry.GetIdNames(sl: TStrings); |
184 | procedure TUD2IdentificationEntry.GetIdNames(sl: TStrings); |
184 | begin |
185 | begin |
185 | sl.Add(GetPrimaryIdName); |
186 | sl.Add(GetPrimaryIdName); |
186 | sl.Add(UpperCase(Plugin.IdentificationMethodName)+':'+IdentificationString); |
- | |
187 | sl.Add(LowerCase(Plugin.IdentificationMethodName)+':'+IdentificationString); |
187 | sl.Add(Plugin.IdentificationMethodName+':'+IdentificationString); |
188 | sl.Add(UpperCase(Plugin.PluginGUIDString)+':'+IdentificationString); |
- | |
189 | sl.Add(LowerCase(Plugin.PluginGUIDString)+':'+IdentificationString); |
188 | sl.Add(Plugin.PluginGUIDString+':'+IdentificationString); |
190 | end; |
189 | end; |
191 | 190 | ||
192 | constructor TUD2IdentificationEntry.Create(AIdentificationString: WideString; |
191 | constructor TUD2IdentificationEntry.Create(AIdentificationString: WideString; |
193 | APlugin: TUD2Plugin); |
192 | APlugin: TUD2Plugin); |
194 | begin |
193 | begin |
Line 246... | Line 245... | ||
246 | pluginLoader.WaitFor; |
245 | pluginLoader.WaitFor; |
247 | Errors.AddStrings(pluginLoader.Errors); |
246 | Errors.AddStrings(pluginLoader.Errors); |
248 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
247 | {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
249 | if Assigned(pluginLoader.pl) then |
248 | if Assigned(pluginLoader.pl) then |
250 | begin |
249 | begin |
251 | sPluginID := GUIDToString(pluginLoader.pl.PluginGUID); |
- | |
252 | prevDLL := FGUIDLookup.Values[sPluginID]; |
- | |
253 | if (prevDLL <> '') and (prevDLL <> pluginLoader.pl.PluginDLL) then |
- | |
254 | begin |
- | |
255 | Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.pl.PluginDLL])); |
- | |
256 | pluginLoader.pl.Free; |
250 | if not pluginLoader.pl.OSNotSupportedEnforced then |
257 | end |
- | |
258 | else |
- | |
259 | begin |
251 | begin |
- | 252 | sPluginID := GUIDToString(pluginLoader.pl.PluginGUID); |
|
- | 253 | prevDLL := FGUIDLookup.Values[sPluginID]; |
|
- | 254 | if (prevDLL <> '') and (prevDLL <> pluginLoader.pl.PluginDLL) then |
|
- | 255 | begin |
|
- | 256 | Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.pl.PluginDLL])); |
|
- | 257 | pluginLoader.pl.Free; |
|
- | 258 | end |
|
- | 259 | else |
|
- | 260 | begin |
|
260 | FGUIDLookup.Values[sPluginID] := pluginLoader.pl.PluginDLL; |
261 | FGUIDLookup.Values[sPluginID] := pluginLoader.pl.PluginDLL; |
261 | LoadedPlugins.Add(pluginLoader.pl); |
262 | LoadedPlugins.Add(pluginLoader.pl); |
- | 263 | end; |
|
262 | end; |
264 | end; |
263 | end; |
265 | end; |
264 | {$ENDIF} |
266 | {$ENDIF} |
265 | pluginLoader.Free; |
267 | pluginLoader.Free; |
266 | end; |
268 | end; |
Line 363... | Line 365... | ||
363 | end; |
365 | end; |
364 | end; |
366 | end; |
365 | end; |
367 | end; |
366 | 368 | ||
367 | function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; |
369 | function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; |
- | 370 | const |
|
- | 371 | CASE_SENSITIVE_FLAG = '$CASESENSITIVE$'; |
|
368 | var |
372 | var |
369 | x: TArrayOfString; |
373 | x: TArrayOfString; |
370 | i: integer; |
374 | i: integer; |
371 | idName: WideString; |
375 | idName: WideString; |
372 | cleanUpStringList: boolean; |
376 | cleanUpStringList: boolean; |
- | 377 | caseSensitive: boolean; |
|
373 | begin |
378 | begin |
374 | cleanUpStringList := slIdNames = nil; |
379 | cleanUpStringList := slIdNames = nil; |
375 | try |
380 | try |
376 | if cleanUpStringList then |
381 | if cleanUpStringList then |
377 | begin |
382 | begin |
Line 389... | Line 394... | ||
389 | result := true; |
394 | result := true; |
390 | for i := Low(x) to High(x) do |
395 | for i := Low(x) to High(x) do |
391 | begin |
396 | begin |
392 | idName := x[i]; |
397 | idName := x[i]; |
393 | 398 | ||
- | 399 | if Pos(CASE_SENSITIVE_FLAG, idName) >= 1 then |
|
- | 400 | begin |
|
- | 401 | idName := StringReplace(idName, CASE_SENSITIVE_FLAG, '', [rfReplaceAll]); |
|
- | 402 | caseSensitive := true; |
|
- | 403 | end |
|
- | 404 | else |
|
- | 405 | begin |
|
- | 406 | caseSensitive := false; |
|
- | 407 | end; |
|
- | 408 | ||
394 | if slIdNames.IndexOf(idName) = -1 then |
409 | if (not caseSensitive and (slIdNames.IndexOf(idName) = -1)) or |
- | 410 | (caseSensitive and (IndexOf_CS(slIdNames, idName) = -1)) then |
|
395 | begin |
411 | begin |
396 | result := false; |
412 | result := false; |
397 | break; |
413 | break; |
398 | end; |
414 | end; |
399 | end; |
415 | end; |
Line 466... | Line 482... | ||
466 | function TUD2PluginLoader.HandleDLL: boolean; |
482 | function TUD2PluginLoader.HandleDLL: boolean; |
467 | var |
483 | var |
468 | sIdentifier: WideString; |
484 | sIdentifier: WideString; |
469 | sIdentifiers: TArrayOfString; |
485 | sIdentifiers: TArrayOfString; |
470 | buf: array[0..cchBufferSize-1] of WideChar; |
486 | buf: array[0..cchBufferSize-1] of WideChar; |
471 | sPluginConfigFile: string; |
- | |
472 | iniConfig: TINIFile; |
- | |
473 | sOverrideGUID: string; |
- | |
474 | pluginIDfound: boolean; |
- | |
475 | pluginInterfaceID: TGUID; |
487 | pluginInterfaceID: TGUID; |
476 | dllHandle: Cardinal; |
488 | dllHandle: Cardinal; |
477 | fPluginInterfaceID: TFuncPluginInterfaceID; |
489 | fPluginInterfaceID: TFuncPluginInterfaceID; |
478 | fPluginIdentifier: TFuncPluginIdentifier; |
490 | fPluginIdentifier: TFuncPluginIdentifier; |
479 | fPluginNameW: TFuncPluginNameW; |
491 | fPluginNameW: TFuncPluginNameW; |
Line 484... | Line 496... | ||
484 | fCheckLicense: TFuncCheckLicense; |
496 | fCheckLicense: TFuncCheckLicense; |
485 | fDescribeOwnStatusCodeW: TFuncDescribeOwnStatusCodeW; |
497 | fDescribeOwnStatusCodeW: TFuncDescribeOwnStatusCodeW; |
486 | statusCode: UD2_STATUS; |
498 | statusCode: UD2_STATUS; |
487 | i: integer; |
499 | i: integer; |
488 | starttime, endtime, time: cardinal; |
500 | starttime, endtime, time: cardinal; |
- | 501 | bakErrorMode: DWORD; |
|
- | 502 | err: DWORD; |
|
489 | 503 | ||
490 | function _ErrorLookup(statusCode: UD2_STATUS): WideString; |
504 | function _ErrorLookup(statusCode: UD2_STATUS): WideString; |
491 | var |
505 | var |
492 | ret: BOOL; |
506 | ret: BOOL; |
493 | begin |
507 | begin |
494 | ret := fDescribeOwnStatusCodeW(@buf, cchBufferSize, statusCode, lngID); |
508 | if Assigned(fDescribeOwnStatusCodeW) then |
495 | if ret then |
- | |
496 | begin |
509 | begin |
- | 510 | ZeroMemory(@buf, cchBufferSize); |
|
- | 511 | ret := fDescribeOwnStatusCodeW(@buf, cchBufferSize, statusCode, lngID); |
|
- | 512 | if ret then |
|
- | 513 | begin |
|
497 | result := PWideChar(@buf); |
514 | result := PWideChar(@buf); |
498 | Exit; |
515 | Exit; |
- | 516 | end; |
|
499 | end; |
517 | end; |
500 | result := TUD2.GenericErrorLookup(statusCode); |
518 | result := TUD2.GenericErrorLookup(statusCode); |
501 | end; |
519 | end; |
502 | 520 | ||
503 | resourcestring |
- | |
504 | LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded.'; |
521 | function _ApplyCompatibilityGUID: boolean; |
505 | LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.'; |
- | |
506 | LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this application.'; |
- | |
507 | LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".'; |
- | |
508 | begin |
522 | var |
509 | result := false; |
523 | iniConfig: TIniFile; |
510 | startTime := GetTickCount; |
524 | sOverrideGUID: string; |
511 | - | ||
512 | dllHandle := LoadLibrary(PChar(dllFile)); |
- | |
513 | if dllHandle = 0 then |
525 | sPluginConfigFile: string; |
514 | begin |
526 | begin |
515 | Errors.Add(Format(LNG_DLL_NOT_LOADED, [dllFile])); |
- | |
516 | end; |
- | |
517 | try |
- | |
518 | @fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID); |
- | |
519 | if not Assigned(fPluginInterfaceID) then |
- | |
520 | begin |
- | |
521 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile])); |
- | |
522 | Exit; |
- | |
523 | end; |
- | |
524 | pluginInterfaceID := fPluginInterfaceID(); |
- | |
525 | if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then |
- | |
526 | begin |
- | |
527 | Errors.Add(Format(LNG_INVALID_PLUGIN, [dllFile])); |
- | |
528 | Exit; |
- | |
529 | end; |
- | |
530 | - | ||
531 | @fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW); |
- | |
532 | if not Assigned(fIdentificationStringW) then |
- | |
533 | begin |
- | |
534 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile])); |
- | |
535 | Exit; |
- | |
536 | end; |
- | |
537 | - | ||
538 | @fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW); |
- | |
539 | if not Assigned(fPluginNameW) then |
- | |
540 | begin |
- | |
541 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile])); |
- | |
542 | Exit; |
- | |
543 | end; |
- | |
544 | - | ||
545 | @fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW); |
- | |
546 | if not Assigned(fPluginVendorW) then |
- | |
547 | begin |
- | |
548 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile])); |
- | |
549 | Exit; |
- | |
550 | end; |
- | |
551 | - | ||
552 | @fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW); |
- | |
553 | if not Assigned(fPluginVersionW) then |
- | |
554 | begin |
- | |
555 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile])); |
- | |
556 | Exit; |
- | |
557 | end; |
- | |
558 | - | ||
559 | @fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense); |
- | |
560 | if not Assigned(fCheckLicense) then |
- | |
561 | begin |
- | |
562 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile])); |
- | |
563 | Exit; |
- | |
564 | end; |
- | |
565 | - | ||
566 | @fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW); |
- | |
567 | if not Assigned(fIdentificationMethodNameW) then |
- | |
568 | begin |
- | |
569 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile])); |
- | |
570 | Exit; |
- | |
571 | end; |
- | |
572 | - | ||
573 | @fDescribeOwnStatusCodeW := GetProcAddress(dllHandle, mnDescribeOwnStatusCodeW); |
- | |
574 | if not Assigned(fDescribeOwnStatusCodeW) then |
- | |
575 | begin |
- | |
576 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDescribeOwnStatusCodeW, dllFile])); |
- | |
577 | Exit; |
- | |
578 | end; |
- | |
579 | - | ||
580 | pl := TUD2Plugin.Create; |
- | |
581 | pl.PluginDLL := dllFile; |
- | |
582 | - | ||
583 | pluginIDfound := false; |
527 | result := false; |
584 | sPluginConfigFile := ChangeFileExt(dllFile, '.ini'); |
528 | sPluginConfigFile := ChangeFileExt(dllFile, '.ini'); |
585 | if FileExists(sPluginConfigFile) then |
529 | if FileExists(sPluginConfigFile) then |
586 | begin |
530 | begin |
587 | iniConfig := TIniFile.Create(sPluginConfigFile); |
531 | iniConfig := TIniFile.Create(sPluginConfigFile); |
588 | try |
532 | try |
589 | sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', ''); |
533 | sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', ''); |
590 | if sOverrideGUID <> '' then |
534 | if sOverrideGUID <> '' then |
591 | begin |
535 | begin |
592 | pl.PluginGUID := StringToGUID(sOverrideGUID); |
536 | pl.PluginGUID := StringToGUID(sOverrideGUID); |
593 | pluginIDfound := true; |
537 | result := true; |
594 | end; |
538 | end; |
595 | finally |
539 | finally |
596 | iniConfig.Free; |
540 | iniConfig.Free; |
597 | end; |
541 | end; |
598 | end; |
542 | end; |
- | 543 | end; |
|
599 | 544 | ||
- | 545 | function _AutoOSNotSupportedMode: integer; |
|
- | 546 | var |
|
- | 547 | iniConfig: TIniFile; |
|
- | 548 | sPluginConfigFile: string; |
|
- | 549 | begin |
|
- | 550 | result := 0; |
|
- | 551 | sPluginConfigFile := ChangeFileExt(dllFile, '.ini'); |
|
600 | if not pluginIDfound then |
552 | if FileExists(sPluginConfigFile) then |
601 | begin |
553 | begin |
602 | @fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier); |
554 | iniConfig := TIniFile.Create(sPluginConfigFile); |
603 | if not Assigned(fPluginIdentifier) then |
- | |
604 | begin |
555 | try |
605 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile])); |
556 | result := iniConfig.ReadInteger('Compatibility', 'AutoOSNotSupported', 0); |
606 | Exit; |
557 | finally |
- | 558 | iniConfig.Free; |
|
607 | end; |
559 | end; |
608 | pl.PluginGUID := fPluginIdentifier(); |
- | |
609 | end; |
560 | end; |
- | 561 | end; |
|
610 | 562 | ||
- | 563 | procedure _OverwriteStatusToOSNotSupported; |
|
- | 564 | begin |
|
- | 565 | pl := TUD2Plugin.Create; |
|
611 | statusCode := fCheckLicense(nil); |
566 | pl.PluginDLL := dllFile; |
612 | if statusCode.wCategory = UD2_STATUSCAT_FAILED then |
567 | statusCode := UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED; |
- | 568 | pl.IdentificationProcedureStatusCode := statusCode; |
|
- | 569 | pl.IdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
|
- | 570 | (* |
|
- | 571 | if not _ApplyCompatibilityGUID then |
|
613 | begin |
572 | begin |
614 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnCheckLicense, dllFile])); |
573 | CreateGUID(pl.PluginGUID); // to avoid the "double GUID" error |
615 | Exit; |
- | |
616 | end; |
574 | end; |
- | 575 | *) |
|
- | 576 | pl.OSNotSupportedEnforced := true; // to avoid the "double GUID" error |
|
- | 577 | result := true; |
|
- | 578 | end; |
|
617 | 579 | ||
- | 580 | resourcestring |
|
618 | statusCode := fPluginNameW(@buf, cchBufferSize, lngID); |
581 | LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded: %s'; |
- | 582 | LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.'; |
|
619 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginName := PWideChar(@buf) |
583 | LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this application.'; |
620 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginName := '' |
584 | LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".'; |
621 | else |
585 | LNG_EXCEPTION = 'Fatal error while loading "%s" (%s: %s)'; |
622 | begin |
586 | begin |
623 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginNameW, dllFile])); |
- | |
624 | Exit; |
587 | result := false; |
625 | end; |
588 | startTime := GetTickCount; |
626 | 589 | ||
- | 590 | try |
|
627 | statusCode := fPluginVendorW(@buf, cchBufferSize, lngID); |
591 | bakErrorMode := 0; |
628 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginVendor := PWideChar(@buf) |
- | |
629 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginVendor := '' |
592 | UD2_SetThreadErrorMode(SEM_FAILCRITICALERRORS, Pointer(bakErrorMode)); |
630 | else |
593 | try |
631 | begin |
- | |
632 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVendorW, dllFile])); |
594 | dllHandle := LoadLibrary(PChar(dllFile)); |
633 | Exit; |
595 | if dllHandle = 0 then |
634 | end; |
596 | begin |
- | 597 | err := GetLastError; |
|
635 | 598 | ||
636 | statusCode := fPluginVersionW(@buf, cchBufferSize, lngID); |
- | |
637 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginVersion := PWideChar(@buf) |
599 | if ((_AutoOSNotSupportedMode = 1) and ((err = ERROR_DLL_NOT_FOUND) or (err = ERROR_PROC_NOT_FOUND))) or |
638 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginVersion := '' |
600 | (_AutoOSNotSupportedMode >= 2) then |
639 | else |
- | |
640 | begin |
601 | begin |
641 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVersionW, dllFile])); |
602 | _OverwriteStatusToOSNotSupported; |
642 | Exit; |
603 | Exit; |
643 | end; |
604 | end; |
644 | 605 | ||
645 | statusCode := fIdentificationMethodNameW(@buf, cchBufferSize); |
606 | Errors.Add(Format(LNG_DLL_NOT_LOADED, [dllFile, SysErrorMessage(err)])); |
- | 607 | Exit; |
|
- | 608 | end; |
|
- | 609 | try |
|
646 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.IdentificationMethodName := PWideChar(@buf) |
610 | @fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID); |
- | 611 | if not Assigned(fPluginInterfaceID) then |
|
- | 612 | begin |
|
647 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.IdentificationMethodName := '' |
613 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile])); |
- | 614 | Exit; |
|
648 | else |
615 | end; |
- | 616 | pluginInterfaceID := fPluginInterfaceID(); |
|
- | 617 | if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then |
|
649 | begin |
618 | begin |
650 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile])); |
619 | Errors.Add(Format(LNG_INVALID_PLUGIN, [dllFile])); |
651 | Exit; |
620 | Exit; |
652 | end; |
621 | end; |
653 | 622 | ||
654 | statusCode := fIdentificationStringW(@buf, cchBufferSize); |
- | |
655 | pl.IdentificationProcedureStatusCode := statusCode; |
- | |
656 | pl.IdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
- | |
657 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then |
- | |
658 | begin |
- | |
659 | sIdentifier := PWideChar(@buf); |
- | |
660 | if UD2_STATUS_Equal(statusCode, UD2_STATUS_OK_MULTILINE, false) then |
- | |
661 | begin |
- | |
662 | // Multiple identifiers (e.g. multiple MAC addresses are delimited via UD2_MULTIPLE_ITEMS_DELIMITER) |
- | |
663 | SetLength(sIdentifiers, 0); |
- | |
664 | sIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier); |
623 | @fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW); |
665 | for i := Low(sIdentifiers) to High(sIdentifiers) do |
624 | if not Assigned(fIdentificationStringW) then |
666 | begin |
625 | begin |
667 | pl.AddIdentification(sIdentifiers[i]); |
626 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile])); |
- | 627 | Exit; |
|
668 | end; |
628 | end; |
- | 629 | ||
- | 630 | @fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW); |
|
- | 631 | if not Assigned(fPluginNameW) then |
|
- | 632 | begin |
|
- | 633 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile])); |
|
- | 634 | Exit; |
|
- | 635 | end; |
|
- | 636 | ||
- | 637 | @fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW); |
|
- | 638 | if not Assigned(fPluginVendorW) then |
|
- | 639 | begin |
|
- | 640 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile])); |
|
- | 641 | Exit; |
|
- | 642 | end; |
|
- | 643 | ||
- | 644 | @fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW); |
|
- | 645 | if not Assigned(fPluginVersionW) then |
|
- | 646 | begin |
|
- | 647 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile])); |
|
- | 648 | Exit; |
|
- | 649 | end; |
|
- | 650 | ||
- | 651 | @fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense); |
|
- | 652 | if not Assigned(fCheckLicense) then |
|
- | 653 | begin |
|
- | 654 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile])); |
|
- | 655 | Exit; |
|
- | 656 | end; |
|
- | 657 | ||
- | 658 | @fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW); |
|
- | 659 | if not Assigned(fIdentificationMethodNameW) then |
|
- | 660 | begin |
|
- | 661 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile])); |
|
- | 662 | Exit; |
|
- | 663 | end; |
|
- | 664 | ||
- | 665 | @fDescribeOwnStatusCodeW := GetProcAddress(dllHandle, mnDescribeOwnStatusCodeW); |
|
- | 666 | if not Assigned(fDescribeOwnStatusCodeW) then |
|
- | 667 | begin |
|
- | 668 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDescribeOwnStatusCodeW, dllFile])); |
|
- | 669 | Exit; |
|
- | 670 | end; |
|
- | 671 | ||
- | 672 | pl := TUD2Plugin.Create; |
|
- | 673 | pl.PluginDLL := dllFile; |
|
- | 674 | ||
- | 675 | if not _ApplyCompatibilityGUID then |
|
- | 676 | begin |
|
- | 677 | @fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier); |
|
- | 678 | if not Assigned(fPluginIdentifier) then |
|
- | 679 | begin |
|
- | 680 | Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile])); |
|
- | 681 | Exit; |
|
- | 682 | end; |
|
- | 683 | pl.PluginGUID := fPluginIdentifier(); |
|
- | 684 | end; |
|
- | 685 | ||
- | 686 | statusCode := fCheckLicense(nil); |
|
- | 687 | if statusCode.wCategory = UD2_STATUSCAT_FAILED then |
|
- | 688 | begin |
|
- | 689 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnCheckLicense, dllFile])); |
|
- | 690 | Exit; |
|
- | 691 | end; |
|
- | 692 | ||
- | 693 | ZeroMemory(@buf, cchBufferSize); |
|
- | 694 | statusCode := fPluginNameW(@buf, cchBufferSize, lngID); |
|
- | 695 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginName := PWideChar(@buf) |
|
- | 696 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginName := '' |
|
- | 697 | else |
|
- | 698 | begin |
|
- | 699 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginNameW, dllFile])); |
|
- | 700 | Exit; |
|
- | 701 | end; |
|
- | 702 | ||
- | 703 | ZeroMemory(@buf, cchBufferSize); |
|
- | 704 | statusCode := fPluginVendorW(@buf, cchBufferSize, lngID); |
|
- | 705 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginVendor := PWideChar(@buf) |
|
- | 706 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginVendor := '' |
|
- | 707 | else |
|
- | 708 | begin |
|
- | 709 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVendorW, dllFile])); |
|
- | 710 | Exit; |
|
- | 711 | end; |
|
- | 712 | ||
- | 713 | ZeroMemory(@buf, cchBufferSize); |
|
- | 714 | statusCode := fPluginVersionW(@buf, cchBufferSize, lngID); |
|
- | 715 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.PluginVersion := PWideChar(@buf) |
|
- | 716 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.PluginVersion := '' |
|
- | 717 | else |
|
- | 718 | begin |
|
- | 719 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVersionW, dllFile])); |
|
- | 720 | Exit; |
|
669 | end |
721 | end; |
- | 722 | ||
- | 723 | ZeroMemory(@buf, cchBufferSize); |
|
- | 724 | statusCode := fIdentificationMethodNameW(@buf, cchBufferSize); |
|
- | 725 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.IdentificationMethodName := PWideChar(@buf) |
|
- | 726 | else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.IdentificationMethodName := '' |
|
670 | else |
727 | else |
- | 728 | begin |
|
- | 729 | Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile])); |
|
- | 730 | Exit; |
|
- | 731 | end; |
|
- | 732 | ||
- | 733 | ZeroMemory(@buf, cchBufferSize); |
|
- | 734 | statusCode := UD2_STATUS_FAILURE_NO_RETURNED_VALUE; // This status will be used when the DLL does not return anything (which is an error by the developer) |
|
- | 735 | statusCode := fIdentificationStringW(@buf, cchBufferSize); |
|
- | 736 | pl.IdentificationProcedureStatusCode := statusCode; |
|
- | 737 | pl.IdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
|
- | 738 | if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then |
|
- | 739 | begin |
|
- | 740 | sIdentifier := PWideChar(@buf); |
|
- | 741 | if UD2_STATUS_Equal(statusCode, UD2_STATUS_OK_MULTILINE, false) then |
|
- | 742 | begin |
|
- | 743 | // Multiple identifiers (e.g. multiple MAC addresses are delimited via UD2_MULTIPLE_ITEMS_DELIMITER) |
|
- | 744 | SetLength(sIdentifiers, 0); |
|
- | 745 | sIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier); |
|
- | 746 | for i := Low(sIdentifiers) to High(sIdentifiers) do |
|
- | 747 | begin |
|
- | 748 | pl.AddIdentification(sIdentifiers[i]); |
|
- | 749 | end; |
|
- | 750 | end |
|
- | 751 | else |
|
- | 752 | begin |
|
- | 753 | pl.AddIdentification(sIdentifier); |
|
- | 754 | end; |
|
- | 755 | end |
|
- | 756 | else if statusCode.wCategory <> UD2_STATUSCAT_NOT_AVAIL then |
|
- | 757 | begin |
|
- | 758 | if _AutoOSNotSupportedMode >= 3 then |
|
- | 759 | begin |
|
- | 760 | _OverwriteStatusToOSNotSupported; |
|
- | 761 | Exit; |
|
- | 762 | end; |
|
- | 763 | ||
- | 764 | // Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationStringW, dllFile])); |
|
- | 765 | Errors.Add(Format(LNG_METHOD_FAILURE, [pl.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile])); |
|
- | 766 | Exit; |
|
- | 767 | end; |
|
- | 768 | ||
- | 769 | result := true; |
|
- | 770 | finally |
|
- | 771 | if not result and Assigned(pl) then FreeAndNil(pl); |
|
- | 772 | FreeLibrary(dllHandle); |
|
- | 773 | end; |
|
- | 774 | finally |
|
- | 775 | UD2_SetThreadErrorMode(bakErrorMode, nil); |
|
- | 776 | ||
- | 777 | if result then |
|
671 | begin |
778 | begin |
- | 779 | endtime := GetTickCount; |
|
672 | pl.AddIdentification(sIdentifier); |
780 | time := endtime - starttime; |
- | 781 | if endtime < starttime then time := High(Cardinal) - time; |
|
- | 782 | pl.time := time; |
|
673 | end; |
783 | end; |
674 | end |
784 | end; |
- | 785 | except |
|
- | 786 | // TODO: when an exception happens in a cdecl DLL, then this code is somehow not |
|
675 | else if statusCode.wCategory <> UD2_STATUSCAT_NOT_AVAIL then |
787 | // executed. Probably the memory is corrupted. Anyway, a cdecl DLL shall NEVER |
- | 788 | // raise an Exception. |
|
- | 789 | on E: Exception do |
|
676 | begin |
790 | begin |
677 | // Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationStringW, dllFile])); |
791 | Errors.Add(Format(LNG_EXCEPTION, [dllFile, E.ClassName, E.Message])); |
678 | Errors.Add(Format(LNG_METHOD_FAILURE, [pl.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile])); |
- | |
679 | Exit; |
792 | Exit; |
680 | end; |
793 | end; |
681 | - | ||
682 | endtime := GetTickCount; |
- | |
683 | time := endtime - starttime; |
- | |
684 | if endtime < starttime then time := High(Cardinal) - time; |
- | |
685 | pl.time := time; |
- | |
686 | - | ||
687 | result := true; |
- | |
688 | finally |
- | |
689 | if not result and Assigned(pl) then FreeAndNil(pl); |
- | |
690 | FreeLibrary(dllHandle); |
- | |
691 | end; |
794 | end; |
692 | end; |
795 | end; |
693 | 796 | ||
694 | end. |
797 | end. |