Subversion Repositories userdetect2

Rev

Rev 90 | Rev 92 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 90 Rev 91
1
unit UD2_Obj;
1
unit UD2_Obj;
2
 
2
 
3
interface
3
interface
4
 
4
 
5
{$IF CompilerVersion >= 25.0}
5
{$IF CompilerVersion >= 25.0}
6
{$LEGACYIFEND ON}
6
{$LEGACYIFEND ON}
7
{$IFEND}
7
{$IFEND}
8
 
8
 
9
{$INCLUDE 'UserDetect2.inc'}
9
{$INCLUDE 'UserDetect2.inc'}
10
 
10
 
11
uses
11
uses
12
  Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf,
12
  Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf,
13
  UD2_PluginStatus, UD2_Utils, UD2_Parsing;
13
  UD2_PluginStatus, UD2_Utils, UD2_Parsing;
14
 
14
 
15
const
15
const
16
  UD2_TagDescription = 'Description';
16
  UD2_TagDescription = 'Description';
17
 
17
 
18
type
18
type
19
  TUD2IdentificationEntry = class;
19
  TUD2IdentificationEntry = class;
20
 
20
 
21
  TUD2Plugin = class(TObject)
21
  TUD2Plugin = class(TObject)
22
  protected
22
  protected
23
    FDetectedIdentifications: TObjectList{<TUD2IdentificationEntry>};
23
    FDetectedIdentifications: TObjectList{<TUD2IdentificationEntry>};
24
    FOSNotSupportedEnforced: boolean;
24
    FOSNotSupportedEnforced: boolean;
25
    FPluginDLL: string;
25
    FPluginDLL: string;
26
    FPluginGUIDSet: boolean;
26
    FPluginGUIDSet: boolean;
27
    FPluginGUID: TGUID;
27
    FPluginGUID: TGUID;
28
    FPluginName: WideString;
28
    FPluginName: WideString;
29
    FPluginVendor: WideString;
29
    FPluginVendor: WideString;
30
    FPluginVersion: WideString;
30
    FPluginVersion: WideString;
31
    FIdentificationMethodName: WideString;
31
    FIdentificationMethodName: WideString;
32
    FAcceptsDynamicRequests: boolean;
32
    FAcceptsDynamicRequests: boolean;
33
    FIdentificationProcedureStatusCode: UD2_STATUS;
33
    FIdentificationProcedureStatusCode: UD2_STATUS;
34
    FIdentificationProcedureStatusCodeDescribed: WideString;
34
    FIdentificationProcedureStatusCodeDescribed: WideString;
35
    FLoadingTime: Cardinal;
35
    FLoadingTime: Cardinal;
36
  public
36
  public
37
    // This flag will be set if "AutoOSNotSupportedCompatibility" of the INI manifest had to be enforced/used
37
    // This flag will be set if "AutoOSNotSupportedCompatibility" of the INI manifest had to be enforced/used
38
    property OSNotSupportedEnforced: boolean read FOSNotSupportedEnforced;
38
    property OSNotSupportedEnforced: boolean read FOSNotSupportedEnforced;
39
 
39
 
40
    // Data read from the DLL
40
    // Data read from the DLL
41
    property PluginDLL: string read FPluginDLL;
41
    property PluginDLL: string read FPluginDLL;
42
    property PluginGUIDSet: boolean read FPluginGUIDSet;
42
    property PluginGUIDSet: boolean read FPluginGUIDSet;
43
    property PluginGUID: TGUID read FPluginGUID;
43
    property PluginGUID: TGUID read FPluginGUID;
44
    property PluginName: WideString read FPluginName;
44
    property PluginName: WideString read FPluginName;
45
    property PluginVendor: WideString read FPluginVendor;
45
    property PluginVendor: WideString read FPluginVendor;
46
    property PluginVersion: WideString read FPluginVersion;
46
    property PluginVersion: WideString read FPluginVersion;
47
    property IdentificationMethodName: WideString read FIdentificationMethodName;
47
    property IdentificationMethodName: WideString read FIdentificationMethodName;
48
    property AcceptsDynamicRequests: boolean read FAcceptsDynamicRequests;
48
    property AcceptsDynamicRequests: boolean read FAcceptsDynamicRequests;
49
 
49
 
50
    // ONLY contains the non-failure status code of IdentificationStringW
50
    // ONLY contains the non-failure status code of IdentificationStringW
51
    property IdentificationProcedureStatusCode: UD2_STATUS read FIdentificationProcedureStatusCode;
51
    property IdentificationProcedureStatusCode: UD2_STATUS read FIdentificationProcedureStatusCode;
52
    property IdentificationProcedureStatusCodeDescribed: WideString read FIdentificationProcedureStatusCodeDescribed;
52
    property IdentificationProcedureStatusCodeDescribed: WideString read FIdentificationProcedureStatusCodeDescribed;
53
 
53
 
54
    // How long did the plugin to load?
54
    // How long did the plugin to load?
55
    property LoadingTime: Cardinal read FLoadingTime;
55
    property LoadingTime: Cardinal read FLoadingTime;
56
 
56
 
57
    function PluginGUIDString: string;
57
    function PluginGUIDString: string;
58
    property DetectedIdentifications: TObjectList{<TUD2IdentificationEntry>} read FDetectedIdentifications;
58
    property DetectedIdentifications: TObjectList{<TUD2IdentificationEntry>} read FDetectedIdentifications;
59
    destructor Destroy; override;
59
    destructor Destroy; override;
60
    constructor Create;
60
    constructor Create;
61
    function AddIdentification(IdStr: WideString): TUD2IdentificationEntry;
61
    function AddIdentification(IdStr: WideString): TUD2IdentificationEntry;
62
 
62
 
63
    function InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings; var outIDs: TArrayOfString): boolean; overload;
63
    function InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings; var outIDs: TArrayOfString): boolean; overload;
64
    function InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings): boolean; overload;
64
    function InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings): boolean; overload;
65
    function GetDynamicRequestResult(dynamicData: WideString; AErrorOut: TStrings=nil): TArrayOfString;
65
    function GetDynamicRequestResult(dynamicData: WideString; AErrorOut: TStrings=nil): TArrayOfString;
66
 
66
 
67
    function EqualsMethodNameOrGuid(idMethodNameOrGUID: string): boolean;
67
    function EqualsMethodNameOrGuid(idMethodNameOrGUID: string): boolean;
68
  end;
68
  end;
69
 
69
 
70
  TUD2IdentificationEntry = class(TObject)
70
  TUD2IdentificationEntry = class(TObject)
71
  private
71
  private
72
    FIdentificationString: WideString;
72
    FIdentificationString: WideString;
73
    FPlugin: TUD2Plugin;
73
    FPlugin: TUD2Plugin;
74
    FDynamicDataUsed: boolean;
74
    FDynamicDataUsed: boolean;
75
    FDynamicData: WideString;
75
    FDynamicData: WideString;
76
  public
76
  public
77
    property DynamicDataUsed: boolean read FDynamicDataUsed write FDynamicDataUsed;
77
    property DynamicDataUsed: boolean read FDynamicDataUsed write FDynamicDataUsed;
78
    property DynamicData: WideString read FDynamicData write FDynamicData;
78
    property DynamicData: WideString read FDynamicData write FDynamicData;
79
    property IdentificationString: WideString read FIdentificationString;
79
    property IdentificationString: WideString read FIdentificationString;
80
    property Plugin: TUD2Plugin read FPlugin;
80
    property Plugin: TUD2Plugin read FPlugin;
81
    procedure GetIdNames(sl: TStrings);
81
    procedure GetIdNames(sl: TStrings);
82
    constructor Create(AIdentificationString: WideString; APlugin: TUD2Plugin);
82
    constructor Create(AIdentificationString: WideString; APlugin: TUD2Plugin);
83
  end;
83
  end;
84
 
84
 
85
  TUD2 = class(TObject)
85
  TUD2 = class(TObject)
86
  private
86
  private
87
    {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
87
    {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
88
    FGUIDLookup: TStrings;
88
    FGUIDLookup: TStrings;
89
    {$ENDIF}
89
    {$ENDIF}
90
  protected
90
  protected
91
    FLoadedPlugins: TObjectList{<TUD2Plugin>};
91
    FLoadedPlugins: TObjectList{<TUD2Plugin>};
92
    FIniFile: TMemIniFile;
92
    FIniFile: TMemIniFile;
93
    FErrors: TStrings;
93
    FErrors: TStrings;
94
    FIniFileName: string;
94
    FIniFileName: string;
95
  public
95
  public
96
    property IniFileName: string read FIniFileName;
96
    property IniFileName: string read FIniFileName;
97
    property Errors: TStrings read FErrors;
97
    property Errors: TStrings read FErrors;
98
    property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins;
98
    property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins;
99
    property IniFile: TMemIniFile read FIniFile;
99
    property IniFile: TMemIniFile read FIniFile;
100
    procedure GetAllDetectedIDs(outSL: TStrings);
100
    procedure GetAllDetectedIDs(outSL: TStrings);
101
    function FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; overload;
101
    function FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; overload;
102
    function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; overload;
102
    function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; overload;
103
    function CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): TUD2CommandArray;
103
    function CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): TUD2CommandArray;
104
    function FindPluginByMethodNameOrGuid(idMethodName: string): TUD2Plugin;
104
    function FindPluginByMethodNameOrGuid(idMethodName: string): TUD2Plugin;
105
    function GetCommandList(ShortTaskName: string; AErrorOut: TStrings=nil): TUD2CommandArray;
105
    function GetCommandList(ShortTaskName: string; AErrorOut: TStrings=nil): TUD2CommandArray;
106
    procedure HandlePluginDir(APluginDir, AFileMask: string);
106
    procedure HandlePluginDir(APluginDir, AFileMask: string);
107
    procedure GetTaskListing(outSL: TStrings);
107
    procedure GetTaskListing(outSL: TStrings);
108
    constructor Create(AIniFileName: string);
108
    constructor Create(AIniFileName: string);
109
    destructor Destroy; override;
109
    destructor Destroy; override;
110
    function TaskExists(ShortTaskName: string): boolean;
110
    function TaskExists(ShortTaskName: string): boolean;
111
    function ReadMetatagString(ShortTaskName, MetatagName: string; DefaultVal: string): string;
111
    function ReadMetatagString(ShortTaskName, MetatagName: string; DefaultVal: string): string;
112
    function ReadMetatagBool(ShortTaskName, MetatagName: string; DefaultVal: string): boolean;
112
    function ReadMetatagBool(ShortTaskName, MetatagName: string; DefaultVal: string): boolean;
113
    function GetTaskName(AShortTaskName: string): string;
113
    function GetTaskName(AShortTaskName: string): string;
114
    class function GenericErrorLookup(grStatus: UD2_STATUS): string;
114
    class function GenericErrorLookup(grStatus: UD2_STATUS): string;
115
  end;
115
  end;
116
 
116
 
117
implementation
117
implementation
118
 
118
 
119
uses
119
uses
120
  Math;
120
  Math;
121
 
121
 
122
const
122
const
123
  cchBufferSize = 32768;
123
  cchBufferSize = 32768;
124
 
124
 
125
type
125
type
126
  TUD2PluginLoader = class(TThread)
126
  TUD2PluginLoader = class(TThread)
127
  protected
127
  protected
128
    dllFile: string;
128
    dllFile: string;
129
    lngID: LANGID;
129
    lngID: LANGID;
130
    useDynamicData: boolean;
130
    useDynamicData: boolean;
131
    dynamicData: WideString;
131
    dynamicData: WideString;
132
    procedure Execute; override;
132
    procedure Execute; override;
133
    function HandleDLL: boolean;
133
    function HandleDLL: boolean;
134
  public
134
  public
135
    Plugin: TUD2Plugin;
135
    Plugin: TUD2Plugin;
136
    Errors: TStringList;
136
    Errors: TStringList;
137
    ResultIdentifiers: TArrayOfString;
137
    ResultIdentifiers: TArrayOfString;
138
    constructor Create(Suspended: boolean; DLL: string; alngid: LANGID; useDynamicData: boolean; dynamicData: WideString);
138
    constructor Create(Suspended: boolean; DLL: string; alngid: LANGID; useDynamicData: boolean; dynamicData: WideString);
139
    destructor Destroy; override;
139
    destructor Destroy; override;
140
  end;
140
  end;
141
 
141
 
142
class function TUD2.GenericErrorLookup(grStatus: UD2_STATUS): string;
142
class function TUD2.GenericErrorLookup(grStatus: UD2_STATUS): string;
143
resourcestring
143
resourcestring
144
  LNG_STATUS_OK_UNSPECIFIED               = 'Success (Unspecified)';
144
  LNG_STATUS_OK_UNSPECIFIED               = 'Success (Unspecified)';
145
  LNG_STATUS_OK_SINGLELINE                = 'Success (One identifier returned)';
145
  LNG_STATUS_OK_SINGLELINE                = 'Success (One identifier returned)';
146
  LNG_STATUS_OK_MULTILINE                 = 'Success (Multiple identifiers returned)';
146
  LNG_STATUS_OK_MULTILINE                 = 'Success (Multiple identifiers returned)';
147
  LNG_UNKNOWN_SUCCESS                     = 'Success (Unknown status code %s)';
147
  LNG_UNKNOWN_SUCCESS                     = 'Success (Unknown status code %s)';
148
 
148
 
149
  LNG_STATUS_NOTAVAIL_UNSPECIFIED         = 'Not available (Unspecified)';
149
  LNG_STATUS_NOTAVAIL_UNSPECIFIED         = 'Not available (Unspecified)';
150
  LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED    = 'Not available (Operating system not supported)';
150
  LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED    = 'Not available (Operating system not supported)';
151
  LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED    = 'Not available (Hardware not supported)';
151
  LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED    = 'Not available (Hardware not supported)';
152
  LNG_STATUS_NOTAVAIL_NO_ENTITIES         = 'Not available (No entities to identify)';
152
  LNG_STATUS_NOTAVAIL_NO_ENTITIES         = 'Not available (No entities to identify)';
153
  LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE = 'Not available (A Windows API call failed. Message: %s)';
153
  LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE = 'Not available (A Windows API call failed. Message: %s)';
154
  LNG_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC = 'Not available (Arguments required)';
154
  LNG_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC = 'Not available (Arguments required)';
155
  LNG_STATUS_NOTAVAIL_INVALID_INPUT       = 'Not available (Plugin received invalid input)';
155
  LNG_STATUS_NOTAVAIL_INVALID_INPUT       = 'Not available (Plugin received invalid input)';
-
 
156
  LNG_STATUS_NOTAVAIL_DOES_NOT_ACCEPT_DYNAMIC_REQUESTS = 'Not available (Plugin does not allow dynamic requests)';
156
  LNG_UNKNOWN_NOTAVAIL                    = 'Not available (Unknown status code %s)';
157
  LNG_UNKNOWN_NOTAVAIL                    = 'Not available (Unknown status code %s)';
157
 
158
 
158
  LNG_STATUS_FAILURE_UNSPECIFIED          = 'Error (Unspecified)';
159
  LNG_STATUS_FAILURE_UNSPECIFIED          = 'Error (Unspecified)';
159
  LNG_STATUS_FAILURE_BUFFER_TOO_SMALL     = 'Error (The provided buffer is too small!)';
160
  LNG_STATUS_FAILURE_BUFFER_TOO_SMALL     = 'Error (The provided buffer is too small!)';
160
  LNG_STATUS_FAILURE_INVALID_ARGS         = 'Error (An internal function received invalid arguments!)';
161
  LNG_STATUS_FAILURE_INVALID_ARGS         = 'Error (An internal function received invalid arguments!)';
161
  LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED  = 'Error (The plugin is not licensed)';
162
  LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED  = 'Error (The plugin is not licensed)';
162
  LNG_STATUS_FAILURE_NO_RETURNED_VALUE    = 'Error (Plugin did not return a status)';
163
  LNG_STATUS_FAILURE_NO_RETURNED_VALUE    = 'Error (Plugin did not return a status)';
163
  LNG_STATUS_FAILURE_CATCHED_EXCEPTION    = 'Error (Catched unexpected Exception)';
164
  LNG_STATUS_FAILURE_CATCHED_EXCEPTION    = 'Error (Catched unexpected Exception)';
164
  LNG_UNKNOWN_FAILED                      = 'Error (Unknown status code %s)';
165
  LNG_UNKNOWN_FAILED                      = 'Error (Unknown status code %s)';
165
 
166
 
166
  LNG_UNKNOWN_STATUS                      = 'Unknown status code with unexpected category: %s';
167
  LNG_UNKNOWN_STATUS                      = 'Unknown status code with unexpected category: %s';
167
begin
168
begin
168
       if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_UNSPECIFIED, false)               then result := LNG_STATUS_OK_UNSPECIFIED
169
       if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_UNSPECIFIED, false)               then result := LNG_STATUS_OK_UNSPECIFIED
169
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_SINGLELINE, false)                then result := LNG_STATUS_OK_SINGLELINE
170
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_SINGLELINE, false)                then result := LNG_STATUS_OK_SINGLELINE
170
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_MULTILINE, false)                 then result := LNG_STATUS_OK_MULTILINE
171
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_OK_MULTILINE, false)                 then result := LNG_STATUS_OK_MULTILINE
171
 
172
 
172
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_UNSPECIFIED, false)         then result := LNG_STATUS_NOTAVAIL_UNSPECIFIED
173
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_UNSPECIFIED, false)         then result := LNG_STATUS_NOTAVAIL_UNSPECIFIED
173
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED, false)    then result := LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED
174
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED, false)    then result := LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED
174
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_HW_NOT_SUPPORTED, false)    then result := LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED
175
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_HW_NOT_SUPPORTED, false)    then result := LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED
175
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_NO_ENTITIES, false)         then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES
176
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_NO_ENTITIES, false)         then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES
176
  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)])
177
  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)])
177
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC, false) then result := LNG_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC
178
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC, false) then result := LNG_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC
178
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_INVALID_INPUT, false)       then result := LNG_STATUS_NOTAVAIL_INVALID_INPUT
179
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_INVALID_INPUT, false)       then result := LNG_STATUS_NOTAVAIL_INVALID_INPUT
-
 
180
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_DOES_NOT_ACCEPT_DYNAMIC_REQUESTS, false) then result := LNG_UD2_STATUS_NOTAVAIL_DOES_NOT_ACCEPT_DYNAMIC_REQUESTS
179
 
181
 
180
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_UNSPECIFIED, false)          then result := LNG_STATUS_FAILURE_UNSPECIFIED
182
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_UNSPECIFIED, false)          then result := LNG_STATUS_FAILURE_UNSPECIFIED
181
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_BUFFER_TOO_SMALL, false)     then result := LNG_STATUS_FAILURE_BUFFER_TOO_SMALL
183
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_BUFFER_TOO_SMALL, false)     then result := LNG_STATUS_FAILURE_BUFFER_TOO_SMALL
182
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_INVALID_ARGS, false)         then result := LNG_STATUS_FAILURE_INVALID_ARGS
184
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_INVALID_ARGS, false)         then result := LNG_STATUS_FAILURE_INVALID_ARGS
183
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_PLUGIN_NOT_LICENSED, false)  then result := LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED
185
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_PLUGIN_NOT_LICENSED, false)  then result := LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED
184
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_NO_RETURNED_VALUE, false)    then result := LNG_STATUS_FAILURE_NO_RETURNED_VALUE
186
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_NO_RETURNED_VALUE, false)    then result := LNG_STATUS_FAILURE_NO_RETURNED_VALUE
185
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_CATCHED_EXCEPTION, false)    then result := LNG_STATUS_FAILURE_CATCHED_EXCEPTION
187
  else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_CATCHED_EXCEPTION, false)    then result := LNG_STATUS_FAILURE_CATCHED_EXCEPTION
186
 
188
 
187
  else if grStatus.wCategory = UD2_STATUSCAT_SUCCESS   then result := Format(LNG_UNKNOWN_SUCCESS,  [UD2_STATUS_FormatStatusCode(grStatus)])
189
  else if grStatus.wCategory = UD2_STATUSCAT_SUCCESS   then result := Format(LNG_UNKNOWN_SUCCESS,  [UD2_STATUS_FormatStatusCode(grStatus)])
188
  else if grStatus.wCategory = UD2_STATUSCAT_NOT_AVAIL then result := Format(LNG_UNKNOWN_NOTAVAIL, [UD2_STATUS_FormatStatusCode(grStatus)])
190
  else if grStatus.wCategory = UD2_STATUSCAT_NOT_AVAIL then result := Format(LNG_UNKNOWN_NOTAVAIL, [UD2_STATUS_FormatStatusCode(grStatus)])
189
  else if grStatus.wCategory = UD2_STATUSCAT_FAILED    then result := Format(LNG_UNKNOWN_FAILED,   [UD2_STATUS_FormatStatusCode(grStatus)])
191
  else if grStatus.wCategory = UD2_STATUSCAT_FAILED    then result := Format(LNG_UNKNOWN_FAILED,   [UD2_STATUS_FormatStatusCode(grStatus)])
190
  else                                                      result := Format(LNG_UNKNOWN_STATUS,   [UD2_STATUS_FormatStatusCode(grStatus)]);
192
  else                                                      result := Format(LNG_UNKNOWN_STATUS,   [UD2_STATUS_FormatStatusCode(grStatus)]);
191
end;
193
end;
192
 
194
 
193
{ TUD2Plugin }
195
{ TUD2Plugin }
194
 
196
 
195
function TUD2Plugin.PluginGUIDString: string;
197
function TUD2Plugin.PluginGUIDString: string;
196
begin
198
begin
197
  if PluginGUIDSet then
199
  if PluginGUIDSet then
198
    result := UpperCase(GUIDToString(PluginGUID))
200
    result := UpperCase(GUIDToString(PluginGUID))
199
  else
201
  else
200
    result := '';
202
    result := '';
201
end;
203
end;
202
 
204
 
203
function TUD2Plugin.AddIdentification(IdStr: WideString): TUD2IdentificationEntry;
205
function TUD2Plugin.AddIdentification(IdStr: WideString): TUD2IdentificationEntry;
204
begin
206
begin
205
  result := TUD2IdentificationEntry.Create(IdStr, Self);
207
  result := TUD2IdentificationEntry.Create(IdStr, Self);
206
  DetectedIdentifications.Add(result);
208
  DetectedIdentifications.Add(result);
207
end;
209
end;
208
 
210
 
209
destructor TUD2Plugin.Destroy;
211
destructor TUD2Plugin.Destroy;
210
begin
212
begin
211
  DetectedIdentifications.Free;
213
  DetectedIdentifications.Free;
212
  inherited;
214
  inherited;
213
end;
215
end;
214
 
216
 
215
constructor TUD2Plugin.Create;
217
constructor TUD2Plugin.Create;
216
begin
218
begin
217
  inherited Create;
219
  inherited Create;
218
  FDetectedIdentifications := TObjectList{<TUD2IdentificationEntry>}.Create(true);
220
  FDetectedIdentifications := TObjectList{<TUD2IdentificationEntry>}.Create(true);
219
end;
221
end;
220
 
222
 
221
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings; var outIDs: TArrayOfString): boolean;
223
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings; var outIDs: TArrayOfString): boolean;
222
var
224
var
223
  ude: TUD2IdentificationEntry;
225
  ude: TUD2IdentificationEntry;
224
  i: integer;
226
  i: integer;
225
  id: string;
227
  id: string;
226
  l: integer;
228
  l: integer;
227
begin
229
begin
228
  result := false;
230
  result := false;
229
 
231
 
230
  SetLength(outIDs, 0);
232
  SetLength(outIDs, 0);
231
 
233
 
232
  for i := 0 to FDetectedIdentifications.Count-1 do
234
  for i := 0 to FDetectedIdentifications.Count-1 do
233
  begin
235
  begin
234
    ude := FDetectedIdentifications.Items[i] as TUD2IdentificationEntry;
236
    ude := FDetectedIdentifications.Items[i] as TUD2IdentificationEntry;
235
    if ude.dynamicDataUsed and (ude.dynamicData = dynamicData) then
237
    if ude.dynamicDataUsed and (ude.dynamicData = dynamicData) then
236
    begin
238
    begin
237
      l := Length(outIDs);
239
      l := Length(outIDs);
238
      SetLength(outIDs, l+1);
240
      SetLength(outIDs, l+1);
239
      outIDs[l] := ude.FIdentificationString;
241
      outIDs[l] := ude.FIdentificationString;
240
    end;
242
    end;
241
  end;
243
  end;
242
 
244
 
243
  // The dynamic content was already evaluated (and therefore is already added in FDetectedIdentifications).
245
  // The dynamic content was already evaluated (and therefore is already added in FDetectedIdentifications).
244
  if Length(outIDs) > 0 then exit;
246
  if Length(outIDs) > 0 then exit;
245
 
247
 
246
  outIDs := GetDynamicRequestResult(dynamicData, AErrorOut);
248
  outIDs := GetDynamicRequestResult(dynamicData, AErrorOut);
247
 
249
 
248
  for i := 0 to Length(outIDs)-1 do
250
  for i := 0 to Length(outIDs)-1 do
249
  begin
251
  begin
250
    id := outIDs[i];
252
    id := outIDs[i];
251
 
253
 
252
    ude := AddIdentification(id);
254
    ude := AddIdentification(id);
253
    ude.dynamicDataUsed := true;
255
    ude.dynamicDataUsed := true;
254
    ude.dynamicData := dynamicData;
256
    ude.dynamicData := dynamicData;
255
 
257
 
256
    result := true;
258
    result := true;
257
  end;
259
  end;
258
end;
260
end;
259
 
261
 
260
function TUD2Plugin.GetDynamicRequestResult(dynamicData: WideString; AErrorOut: TStrings=nil): TArrayOfString;
262
function TUD2Plugin.GetDynamicRequestResult(dynamicData: WideString; AErrorOut: TStrings=nil): TArrayOfString;
261
var
263
var
262
  lngID: LANGID;
264
  lngID: LANGID;
263
  loader: TUD2PluginLoader;
265
  loader: TUD2PluginLoader;
264
begin
266
begin
265
  lngID := GetSystemDefaultLangID;
267
  lngID := GetSystemDefaultLangID;
266
 
268
 
267
  loader := TUD2PluginLoader.Create(false, PluginDLL, lngid, true, dynamicData);
269
  loader := TUD2PluginLoader.Create(false, PluginDLL, lngid, true, dynamicData);
268
  try
270
  try
269
    loader.WaitFor;
271
    loader.WaitFor;
270
    result := loader.ResultIdentifiers;
272
    result := loader.ResultIdentifiers;
271
    if Assigned(AErrorOut) then
273
    if Assigned(AErrorOut) then
272
    begin
274
    begin
273
      AErrorOut.AddStrings(loader.Errors);
275
      AErrorOut.AddStrings(loader.Errors);
274
    end;
276
    end;
275
 
277
 
276
    // TODO: Use assign() instead? or allow TUD2PluginLoader to write the TPlugin object directly?
278
    // TODO: Use assign() instead? or allow TUD2PluginLoader to write the TPlugin object directly?
277
    //       Should we even overwrite the current plugin data, or return the new plugin?
279
    //       Should we even overwrite the current plugin data, or return the new plugin?
278
    FIdentificationProcedureStatusCode := loader.plugin.IdentificationProcedureStatusCode;
280
    FIdentificationProcedureStatusCode := loader.plugin.IdentificationProcedureStatusCode;
279
    FIdentificationProcedureStatusCodeDescribed := loader.plugin.IdentificationProcedureStatusCodeDescribed;
281
    FIdentificationProcedureStatusCodeDescribed := loader.plugin.IdentificationProcedureStatusCodeDescribed;
280
    FOSNotSupportedEnforced := loader.plugin.OSNotSupportedEnforced;
282
    FOSNotSupportedEnforced := loader.plugin.OSNotSupportedEnforced;
281
    FLoadingTime := loader.Plugin.LoadingTime;
283
    FLoadingTime := loader.Plugin.LoadingTime;
282
 
284
 
283
  finally
285
  finally
284
    if Assigned(loader.Plugin) then FreeAndNil(loader.Plugin);
286
    if Assigned(loader.Plugin) then FreeAndNil(loader.Plugin);
285
    loader.Free;
287
    loader.Free;
286
  end;
288
  end;
287
end;
289
end;
288
 
290
 
289
function TUD2Plugin.EqualsMethodNameOrGuid(idMethodNameOrGUID: string): boolean;
291
function TUD2Plugin.EqualsMethodNameOrGuid(idMethodNameOrGUID: string): boolean;
290
begin
292
begin
291
  result := SameText(IdentificationMethodName, idMethodNameOrGUID) or
293
  result := SameText(IdentificationMethodName, idMethodNameOrGUID) or
292
            SameText(GUIDToString(PluginGUID), idMethodNameOrGUID)
294
            SameText(GUIDToString(PluginGUID), idMethodNameOrGUID)
293
end;
295
end;
294
 
296
 
295
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings): boolean;
297
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings): boolean;
296
var
298
var
297
  dummy: TArrayOfString;
299
  dummy: TArrayOfString;
298
begin
300
begin
299
  result := InvokeDynamicCheck(dynamicData, AErrorOut, dummy)
301
  result := InvokeDynamicCheck(dynamicData, AErrorOut, dummy)
300
end;
302
end;
301
 
303
 
302
{ TUD2IdentificationEntry }
304
{ TUD2IdentificationEntry }
303
 
305
 
304
procedure TUD2IdentificationEntry.GetIdNames(sl: TStrings);
306
procedure TUD2IdentificationEntry.GetIdNames(sl: TStrings);
305
var
307
var
306
  cond: TUD2TDFCondition;
308
  cond: TUD2TDFCondition;
307
begin
309
begin
308
  cond.idMethodName := Plugin.IdentificationMethodName;
310
  cond.idMethodName := Plugin.IdentificationMethodName;
309
  cond.idStr := IdentificationString;
311
  cond.idStr := IdentificationString;
310
  cond.dynamicDataUsed := DynamicDataUsed;
312
  cond.dynamicDataUsed := DynamicDataUsed;
311
  cond.dynamicData := DynamicData;
313
  cond.dynamicData := DynamicData;
312
  sl.Add(UD2_CondToStr(cond));
314
  sl.Add(UD2_CondToStr(cond));
313
 
315
 
314
  cond.idMethodName := Plugin.PluginGUIDString;
316
  cond.idMethodName := Plugin.PluginGUIDString;
315
  sl.Add(UD2_CondToStr(cond));
317
  sl.Add(UD2_CondToStr(cond));
316
end;
318
end;
317
 
319
 
318
constructor TUD2IdentificationEntry.Create(AIdentificationString: WideString;
320
constructor TUD2IdentificationEntry.Create(AIdentificationString: WideString;
319
  APlugin: TUD2Plugin);
321
  APlugin: TUD2Plugin);
320
begin
322
begin
321
  inherited Create;
323
  inherited Create;
322
 
324
 
323
  // TODO: We need to do this, because ReadSectionValues strips the names of the name-value pairs...
325
  // TODO: We need to do this, because ReadSectionValues strips the names of the name-value pairs...
324
  //       We should correct ReadSectionValues...
326
  //       We should correct ReadSectionValues...
325
  // Example: DriveSerial(c:):2SHSWNHA010807 X    =calc.exe
327
  // Example: DriveSerial(c:):2SHSWNHA010807 X    =calc.exe
326
  // ReadSectionValues will return "DriveSerial(c:):2SHSWNHA010807 X=calc.exe"
328
  // ReadSectionValues will return "DriveSerial(c:):2SHSWNHA010807 X=calc.exe"
327
  AIdentificationString := Trim(AIdentificationString);
329
  AIdentificationString := Trim(AIdentificationString);
328
 
330
 
329
  FIdentificationString := AIdentificationString;
331
  FIdentificationString := AIdentificationString;
330
  FPlugin := APlugin;
332
  FPlugin := APlugin;
331
end;
333
end;
332
 
334
 
333
{ TUD2 }
335
{ TUD2 }
334
 
336
 
335
procedure TUD2.HandlePluginDir(APluginDir, AFileMask: string);
337
procedure TUD2.HandlePluginDir(APluginDir, AFileMask: string);
336
Var
338
Var
337
  SR: TSearchRec;
339
  SR: TSearchRec;
338
  path: string;
340
  path: string;
339
  pluginLoader: TUD2PluginLoader;
341
  pluginLoader: TUD2PluginLoader;
340
  tob: TObjectList{<TUD2PluginLoader>};
342
  tob: TObjectList{<TUD2PluginLoader>};
341
  i: integer;
343
  i: integer;
342
  {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
344
  {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
343
  sPluginID, prevDLL: string;
345
  sPluginID, prevDLL: string;
344
  {$ENDIF}
346
  {$ENDIF}
345
  lngid: LANGID;
347
  lngid: LANGID;
346
resourcestring
348
resourcestring
347
  LNG_PLUGINS_SAME_GUID = 'Attention: The plugin "%s" and the plugin "%s" have the same identification GUID. The latter will not be loaded.';
349
  LNG_PLUGINS_SAME_GUID = 'Attention: The plugin "%s" and the plugin "%s" have the same identification GUID. The latter will not be loaded.';
348
begin
350
begin
349
  tob := TObjectList{<TUD2PluginLoader>}.Create;
351
  tob := TObjectList{<TUD2PluginLoader>}.Create;
350
  try
352
  try
351
    tob.OwnsObjects := false;
353
    tob.OwnsObjects := false;
352
 
354
 
353
    lngID := GetSystemDefaultLangID;
355
    lngID := GetSystemDefaultLangID;
354
 
356
 
355
    path := APluginDir;
357
    path := APluginDir;
356
    if path <> '' then path := IncludeTrailingPathDelimiter(path);
358
    if path <> '' then path := IncludeTrailingPathDelimiter(path);
357
 
359
 
358
    if FindFirst(path + AFileMask, 0, SR) = 0 then
360
    if FindFirst(path + AFileMask, 0, SR) = 0 then
359
    begin
361
    begin
360
      try
362
      try
361
        repeat
363
        repeat
362
          try
364
          try
363
            tob.Add(TUD2PluginLoader.Create(false, path + sr.Name, lngid, false, ''));
365
            tob.Add(TUD2PluginLoader.Create(false, path + sr.Name, lngid, false, ''));
364
          except
366
          except
365
            on E: Exception do
367
            on E: Exception do
366
            begin
368
            begin
367
              MessageDlg(E.Message, mtError, [mbOK], 0);
369
              MessageDlg(E.Message, mtError, [mbOK], 0);
368
            end;
370
            end;
369
          end;
371
          end;
370
        until FindNext(SR) <> 0;
372
        until FindNext(SR) <> 0;
371
      finally
373
      finally
372
        FindClose(SR);
374
        FindClose(SR);
373
      end;
375
      end;
374
    end;
376
    end;
375
 
377
 
376
    for i := 0 to tob.count-1 do
378
    for i := 0 to tob.count-1 do
377
    begin
379
    begin
378
      pluginLoader := tob.items[i] as TUD2PluginLoader;
380
      pluginLoader := tob.items[i] as TUD2PluginLoader;
379
      pluginLoader.WaitFor;
381
      pluginLoader.WaitFor;
380
      Errors.AddStrings(pluginLoader.Errors);
382
      Errors.AddStrings(pluginLoader.Errors);
381
      if Assigned(pluginLoader.Plugin) then
383
      if Assigned(pluginLoader.Plugin) then
382
      begin
384
      begin
383
        {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
385
        {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
384
        if pluginLoader.Plugin.PluginGUIDSet then
386
        if pluginLoader.Plugin.PluginGUIDSet then
385
        begin
387
        begin
386
          sPluginID := GUIDToString(pluginLoader.Plugin.PluginGUID);
388
          sPluginID := GUIDToString(pluginLoader.Plugin.PluginGUID);
387
          prevDLL := FGUIDLookup.Values[sPluginID];
389
          prevDLL := FGUIDLookup.Values[sPluginID];
388
          if (prevDLL <> '') and (prevDLL <> pluginLoader.Plugin.PluginDLL) then
390
          if (prevDLL <> '') and (prevDLL <> pluginLoader.Plugin.PluginDLL) then
389
          begin
391
          begin
390
            Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.Plugin.PluginDLL]));
392
            Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.Plugin.PluginDLL]));
391
            pluginLoader.Plugin.Free;
393
            pluginLoader.Plugin.Free;
392
          end
394
          end
393
          else
395
          else
394
          begin
396
          begin
395
            FGUIDLookup.Values[sPluginID] := pluginLoader.Plugin.PluginDLL;
397
            FGUIDLookup.Values[sPluginID] := pluginLoader.Plugin.PluginDLL;
396
            LoadedPlugins.Add(pluginLoader.Plugin);
398
            LoadedPlugins.Add(pluginLoader.Plugin);
397
          end;
399
          end;
398
        end
400
        end
399
        else
401
        else
400
        begin
402
        begin
401
          LoadedPlugins.Add(pluginLoader.Plugin);
403
          LoadedPlugins.Add(pluginLoader.Plugin);
402
        end;
404
        end;
403
        {$ELSE}
405
        {$ELSE}
404
        LoadedPlugins.Add(pluginLoader.Plugin);
406
        LoadedPlugins.Add(pluginLoader.Plugin);
405
        {$ENDIF}
407
        {$ENDIF}
406
      end;
408
      end;
407
      pluginLoader.Free;
409
      pluginLoader.Free;
408
    end;
410
    end;
409
  finally
411
  finally
410
    tob.free;
412
    tob.free;
411
  end;
413
  end;
412
end;
414
end;
413
 
415
 
414
destructor TUD2.Destroy;
416
destructor TUD2.Destroy;
415
begin
417
begin
416
  FIniFile.Free;
418
  FIniFile.Free;
417
  FLoadedPlugins.Free;
419
  FLoadedPlugins.Free;
418
  {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
420
  {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
419
  FGUIDLookup.Free;
421
  FGUIDLookup.Free;
420
  {$ENDIF}
422
  {$ENDIF}
421
  FErrors.Free;
423
  FErrors.Free;
422
end;
424
end;
423
 
425
 
424
constructor TUD2.Create(AIniFileName: string);
426
constructor TUD2.Create(AIniFileName: string);
425
begin
427
begin
426
  FIniFileName := AIniFileName;
428
  FIniFileName := AIniFileName;
427
  FLoadedPlugins := TObjectList{<TUD2Plugin>}.Create(true);
429
  FLoadedPlugins := TObjectList{<TUD2Plugin>}.Create(true);
428
  FIniFile := TMemIniFile.Create(IniFileName);
430
  FIniFile := TMemIniFile.Create(IniFileName);
429
  {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
431
  {$IFDEF CHECK_FOR_SAME_PLUGIN_GUID}
430
  FGUIDLookup := TStringList.Create;
432
  FGUIDLookup := TStringList.Create;
431
  {$ENDIF}
433
  {$ENDIF}
432
  FErrors := TStringList.Create;
434
  FErrors := TStringList.Create;
433
end;
435
end;
434
 
436
 
435
function TUD2.GetTaskName(AShortTaskName: string): string;
437
function TUD2.GetTaskName(AShortTaskName: string): string;
436
resourcestring
438
resourcestring
437
  LNG_NO_DESCRIPTION = '(%s)';
439
  LNG_NO_DESCRIPTION = '(%s)';
438
begin
440
begin
439
  result := FIniFile.ReadString(AShortTaskName, UD2_TagDescription, Format(LNG_NO_DESCRIPTION, [AShortTaskName]));
441
  result := FIniFile.ReadString(AShortTaskName, UD2_TagDescription, Format(LNG_NO_DESCRIPTION, [AShortTaskName]));
440
end;
442
end;
441
 
443
 
442
procedure TUD2.GetTaskListing(outSL: TStrings);
444
procedure TUD2.GetTaskListing(outSL: TStrings);
443
var
445
var
444
  sl: TStringList;
446
  sl: TStringList;
445
  i: integer;
447
  i: integer;
446
  desc: string;
448
  desc: string;
447
begin
449
begin
448
  sl := TStringList.Create;
450
  sl := TStringList.Create;
449
  try
451
  try
450
    FIniFile.ReadSections(sl);
452
    FIniFile.ReadSections(sl);
451
    for i := 0 to sl.Count-1 do
453
    for i := 0 to sl.Count-1 do
452
    begin
454
    begin
453
      desc := GetTaskName(sl.Strings[i]);
455
      desc := GetTaskName(sl.Strings[i]);
454
      outSL.Values[sl.Strings[i]] := desc;
456
      outSL.Values[sl.Strings[i]] := desc;
455
    end;
457
    end;
456
  finally
458
  finally
457
    sl.Free;
459
    sl.Free;
458
  end;
460
  end;
459
end;
461
end;
460
 
462
 
461
function TUD2.TaskExists(ShortTaskName: string): boolean;
463
function TUD2.TaskExists(ShortTaskName: string): boolean;
462
begin
464
begin
463
  result := FIniFile.SectionExists(ShortTaskName);
465
  result := FIniFile.SectionExists(ShortTaskName);
464
end;
466
end;
465
 
467
 
466
function TUD2.ReadMetatagString(ShortTaskName, MetatagName: string; DefaultVal: string): string;
468
function TUD2.ReadMetatagString(ShortTaskName, MetatagName: string; DefaultVal: string): string;
467
begin
469
begin
468
  result := IniFile.ReadString(ShortTaskName, MetatagName, DefaultVal);
470
  result := IniFile.ReadString(ShortTaskName, MetatagName, DefaultVal);
469
end;
471
end;
470
 
472
 
471
function TUD2.ReadMetatagBool(ShortTaskName, MetatagName: string; DefaultVal: string): boolean;
473
function TUD2.ReadMetatagBool(ShortTaskName, MetatagName: string; DefaultVal: string): boolean;
472
begin
474
begin
473
  // DefaultVal is a string, because we want to allow an empty string, in case the
475
  // DefaultVal is a string, because we want to allow an empty string, in case the
474
  // user wishes an Exception in case the string is not a valid boolean string
476
  // user wishes an Exception in case the string is not a valid boolean string
475
  result := BetterInterpreteBool(IniFile.ReadString(ShortTaskName, MetatagName, DefaultVal));
477
  result := BetterInterpreteBool(IniFile.ReadString(ShortTaskName, MetatagName, DefaultVal));
476
end;
478
end;
477
 
479
 
478
(*
480
(*
479
 
481
 
480
NAMING EXAMPLE: $CASESENSITIVE$ComputerName(dynXYZ):ABC&&User:John=calc.exe$RIOD$
482
NAMING EXAMPLE: $CASESENSITIVE$ComputerName(dynXYZ):ABC&&User:John=calc.exe$RIOD$
481
 
483
 
482
        idTerm:       ComputerName(dynXYZ):ABC&&User:John
484
        idTerm:       ComputerName(dynXYZ):ABC&&User:John
483
        idName:       ComputerName:ABC
485
        idName:       ComputerName:ABC
484
        IdMethodName: ComputerName
486
        IdMethodName: ComputerName
485
        IdStr         ABC
487
        IdStr         ABC
486
        cmd:          calc.exe
488
        cmd:          calc.exe
487
        dynamicData:  dynXYZ
489
        dynamicData:  dynXYZ
488
 
490
 
489
*)
491
*)
490
 
492
 
491
procedure TUD2.GetAllDetectedIDs(outSL: TStrings);
493
procedure TUD2.GetAllDetectedIDs(outSL: TStrings);
492
var
494
var
493
  i, j: integer;
495
  i, j: integer;
494
  pl: TUD2Plugin;
496
  pl: TUD2Plugin;
495
  ude: TUD2IdentificationEntry;
497
  ude: TUD2IdentificationEntry;
496
begin
498
begin
497
  for i := 0 to LoadedPlugins.Count-1 do
499
  for i := 0 to LoadedPlugins.Count-1 do
498
  begin
500
  begin
499
    pl := LoadedPlugins.Items[i] as TUD2Plugin;
501
    pl := LoadedPlugins.Items[i] as TUD2Plugin;
500
    for j := 0 to pl.DetectedIdentifications.Count-1 do
502
    for j := 0 to pl.DetectedIdentifications.Count-1 do
501
    begin
503
    begin
502
      ude := pl.DetectedIdentifications.Items[j] as TUD2IdentificationEntry;
504
      ude := pl.DetectedIdentifications.Items[j] as TUD2IdentificationEntry;
503
      ude.GetIdNames(outSL);
505
      ude.GetIdNames(outSL);
504
    end;
506
    end;
505
  end;
507
  end;
506
end;
508
end;
507
 
509
 
508
function TUD2.FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean;
510
function TUD2.FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean;
509
begin
511
begin
510
  result := FulfilsEverySubterm(UD2_CondsToStr(conds), slIdNames, AErrorOut);
512
  result := FulfilsEverySubterm(UD2_CondsToStr(conds), slIdNames, AErrorOut);
511
end;
513
end;
512
 
514
 
513
function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean;
515
function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean;
514
var
516
var
515
  i: integer;
517
  i: integer;
516
  p: TUD2Plugin;
518
  p: TUD2Plugin;
517
  cleanUpStringList: boolean;
519
  cleanUpStringList: boolean;
518
  conds: TUD2TDFConditionArray;
520
  conds: TUD2TDFConditionArray;
519
  cond: TUD2TDFCondition;
521
  cond: TUD2TDFCondition;
520
  idName: string;
522
  idName: string;
521
begin
523
begin
522
  {$IFDEF NO_CONDITIONS_IS_FAILURE}
524
  {$IFDEF NO_CONDITIONS_IS_FAILURE}
523
  if idTerm = '' then
525
  if idTerm = '' then
524
  begin
526
  begin
525
    SetLength(conds, 0);
527
    SetLength(conds, 0);
526
    result := false;
528
    result := false;
527
    Exit;
529
    Exit;
528
  end;
530
  end;
529
  {$ENDIF}
531
  {$ENDIF}
530
 
532
 
531
  cleanUpStringList := slIdNames = nil;
533
  cleanUpStringList := slIdNames = nil;
532
  try
534
  try
533
    if cleanUpStringList then
535
    if cleanUpStringList then
534
    begin
536
    begin
535
      slIdNames := TStringList.Create;
537
      slIdNames := TStringList.Create;
536
      GetAllDetectedIDs(slIdNames);
538
      GetAllDetectedIDs(slIdNames);
537
    end;
539
    end;
538
 
540
 
539
    conds := UD2P_ParseConditions(idTerm);
541
    conds := UD2P_ParseConditions(idTerm);
540
 
542
 
541
    result := true;
543
    result := true;
542
    for i := Low(conds) to High(conds) do
544
    for i := Low(conds) to High(conds) do
543
    begin
545
    begin
544
      cond := conds[i];
546
      cond := conds[i];
545
 
547
 
546
      if cond.dynamicDataUsed then
548
      if cond.dynamicDataUsed then
547
      begin
549
      begin
548
        p := FindPluginByMethodNameOrGuid(cond.idMethodName);
550
        p := FindPluginByMethodNameOrGuid(cond.idMethodName);
549
        if Assigned(p) then
551
        if Assigned(p) then
550
        begin
552
        begin
551
          if p.InvokeDynamicCheck(cond.dynamicData, AErrorOut) then
553
          if p.InvokeDynamicCheck(cond.dynamicData, AErrorOut) then
552
          begin
554
          begin
553
            // Reload the identifications
555
            // Reload the identifications
554
            slIdNames.Clear;
556
            slIdNames.Clear;
555
            GetAllDetectedIDs(slIdNames);
557
            GetAllDetectedIDs(slIdNames);
556
          end;
558
          end;
557
        end;
559
        end;
558
      end;
560
      end;
559
 
561
 
560
      idName := UD2_CondToStr(cond);
562
      idName := UD2_CondToStr(cond);
561
 
563
 
562
      if (not cond.caseSensitive and (slIdNames.IndexOf(idName) = -1)) or
564
      if (not cond.caseSensitive and (slIdNames.IndexOf(idName) = -1)) or
563
         (cond.caseSensitive and (IndexOf_CS(slIdNames, idName) = -1)) then
565
         (cond.caseSensitive and (IndexOf_CS(slIdNames, idName) = -1)) then
564
      begin
566
      begin
565
        result := false;
567
        result := false;
566
        break;
568
        break;
567
      end;
569
      end;
568
    end;
570
    end;
569
  finally
571
  finally
570
    if cleanUpStringList and Assigned(slIdNames) then
572
    if cleanUpStringList and Assigned(slIdNames) then
571
      slIdNames.Free;
573
      slIdNames.Free;
572
  end;
574
  end;
573
end;
575
end;
574
 
576
 
575
function TUD2.FindPluginByMethodNameOrGuid(idMethodName: string): TUD2Plugin;
577
function TUD2.FindPluginByMethodNameOrGuid(idMethodName: string): TUD2Plugin;
576
var
578
var
577
  i: integer;
579
  i: integer;
578
  p: TUD2Plugin;
580
  p: TUD2Plugin;
579
begin
581
begin
580
  result := nil;
582
  result := nil;
581
  for i := 0 to LoadedPlugins.Count-1 do
583
  for i := 0 to LoadedPlugins.Count-1 do
582
  begin
584
  begin
583
    p := LoadedPlugins.Items[i] as TUD2Plugin;
585
    p := LoadedPlugins.Items[i] as TUD2Plugin;
584
 
586
 
585
    if p.EqualsMethodNameOrGuid(idMethodName) then
587
    if p.EqualsMethodNameOrGuid(idMethodName) then
586
    begin
588
    begin
587
      result := p;
589
      result := p;
588
      Exit;
590
      Exit;
589
    end;
591
    end;
590
  end;
592
  end;
591
end;
593
end;
592
 
594
 
593
function TUD2.GetCommandList(ShortTaskName: string; AErrorOut: TStrings=nil): TUD2CommandArray;
595
function TUD2.GetCommandList(ShortTaskName: string; AErrorOut: TStrings=nil): TUD2CommandArray;
594
var
596
var
595
  i, j, l: integer;
597
  i, j, l: integer;
596
  slSV, slIdNames: TStrings;
598
  slSV, slIdNames: TStrings;
597
  tmpCmds: TUD2CommandArray;
599
  tmpCmds: TUD2CommandArray;
598
begin
600
begin
599
  SetLength(result, 0);
601
  SetLength(result, 0);
600
  SetLength(tmpCmds, 0);
602
  SetLength(tmpCmds, 0);
601
 
603
 
602
  slIdNames := TStringList.Create;
604
  slIdNames := TStringList.Create;
603
  try
605
  try
604
    GetAllDetectedIDs(slIdNames);
606
    GetAllDetectedIDs(slIdNames);
605
 
607
 
606
    slSV := TStringList.Create;
608
    slSV := TStringList.Create;
607
    try
609
    try
608
      FIniFile.ReadSectionValues(ShortTaskName, slSV);
610
      FIniFile.ReadSectionValues(ShortTaskName, slSV);
609
      for i := 0 to slSV.Count-1 do
611
      for i := 0 to slSV.Count-1 do
610
      begin
612
      begin
611
        tmpCmds := CheckTerm(slSV.Strings[i], slIdNames, AErrorOut);
613
        tmpCmds := CheckTerm(slSV.Strings[i], slIdNames, AErrorOut);
612
        for j := Low(tmpCmds) to High(tmpCmds) do
614
        for j := Low(tmpCmds) to High(tmpCmds) do
613
        begin
615
        begin
614
          l := Length(result);
616
          l := Length(result);
615
          SetLength(result, l+1);
617
          SetLength(result, l+1);
616
          result[l] := tmpCmds[j];
618
          result[l] := tmpCmds[j];
617
        end;
619
        end;
618
      end;
620
      end;
619
    finally
621
    finally
620
      slSV.Free;
622
      slSV.Free;
621
    end;
623
    end;
622
  finally
624
  finally
623
    slIdNames.Free;
625
    slIdNames.Free;
624
  end;
626
  end;
625
end;
627
end;
626
 
628
 
627
function TUD2.CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): TUD2CommandArray;
629
function TUD2.CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): TUD2CommandArray;
628
var
630
var
629
  slIdNamesCreated: boolean;
631
  slIdNamesCreated: boolean;
630
  ent: TUD2TDFEntry;
632
  ent: TUD2TDFEntry;
631
begin
633
begin
632
  SetLength(result, 0);
634
  SetLength(result, 0);
633
 
635
 
634
  slIdNamesCreated := false;
636
  slIdNamesCreated := false;
635
  try
637
  try
636
    if not Assigned(slIdNames) then
638
    if not Assigned(slIdNames) then
637
    begin
639
    begin
638
      slIdNamesCreated := true;
640
      slIdNamesCreated := true;
639
      slIdNames := TStringList.Create;
641
      slIdNames := TStringList.Create;
640
      GetAllDetectedIDs(slIdNames);
642
      GetAllDetectedIDs(slIdNames);
641
    end;
643
    end;
642
 
644
 
643
    if not UD2P_ParseTdfLine(idTermAndCmd, ent) then Exit;
645
    if not UD2P_ParseTdfLine(idTermAndCmd, ent) then Exit;
644
    if FulfilsEverySubterm(ent.ids, slIdNames, AErrorOut) then
646
    if FulfilsEverySubterm(ent.ids, slIdNames, AErrorOut) then
645
    begin
647
    begin
646
      result := ent.commands;
648
      result := ent.commands;
647
    end;
649
    end;
648
  finally
650
  finally
649
    if slIdNamesCreated then slIdNames.Free;
651
    if slIdNamesCreated then slIdNames.Free;
650
  end;
652
  end;
651
end;
653
end;
652
 
654
 
653
{ TUD2PluginLoader }
655
{ TUD2PluginLoader }
654
 
656
 
655
procedure TUD2PluginLoader.Execute;
657
procedure TUD2PluginLoader.Execute;
656
begin
658
begin
657
  inherited;
659
  inherited;
658
 
660
 
659
  HandleDLL;
661
  HandleDLL;
660
end;
662
end;
661
 
663
 
662
constructor TUD2PluginLoader.Create(Suspended: boolean; DLL: string; alngid: LANGID; useDynamicData: boolean; dynamicData: WideString);
664
constructor TUD2PluginLoader.Create(Suspended: boolean; DLL: string; alngid: LANGID; useDynamicData: boolean; dynamicData: WideString);
663
begin
665
begin
664
  inherited Create(Suspended);
666
  inherited Create(Suspended);
665
  dllfile := dll;
667
  dllfile := dll;
666
  Plugin := nil;
668
  Plugin := nil;
667
  Errors := TStringList.Create;
669
  Errors := TStringList.Create;
668
  lngid := alngid;
670
  lngid := alngid;
669
  self.useDynamicData := useDynamicData;
671
  self.useDynamicData := useDynamicData;
670
  Self.dynamicData := dynamicData;
672
  Self.dynamicData := dynamicData;
671
end;
673
end;
672
 
674
 
673
destructor TUD2PluginLoader.Destroy;
675
destructor TUD2PluginLoader.Destroy;
674
begin
676
begin
675
  Errors.Free;
677
  Errors.Free;
676
  inherited;
678
  inherited;
677
end;
679
end;
678
 
680
 
679
function TUD2PluginLoader.HandleDLL: boolean;
681
function TUD2PluginLoader.HandleDLL: boolean;
680
var
682
var
681
  sIdentifier: WideString;
683
  sIdentifier: WideString;
682
  buf: array[0..cchBufferSize-1] of WideChar;
684
  buf: array[0..cchBufferSize-1] of WideChar;
683
  pluginInterfaceID: TGUID;
685
  pluginInterfaceID: TGUID;
684
  dllHandle: Cardinal;
686
  dllHandle: Cardinal;
685
  fPluginInterfaceID: TFuncPluginInterfaceID;
687
  fPluginInterfaceID: TFuncPluginInterfaceID;
686
  fPluginIdentifier: TFuncPluginIdentifier;
688
  fPluginIdentifier: TFuncPluginIdentifier;
687
  fPluginNameW: TFuncPluginNameW;
689
  fPluginNameW: TFuncPluginNameW;
688
  fPluginVendorW: TFuncPluginVendorW;
690
  fPluginVendorW: TFuncPluginVendorW;
689
  fPluginVersionW: TFuncPluginVersionW;
691
  fPluginVersionW: TFuncPluginVersionW;
690
  fIdentificationMethodNameW: TFuncIdentificationMethodNameW;
692
  fIdentificationMethodNameW: TFuncIdentificationMethodNameW;
691
  fIdentificationStringW: TFuncIdentificationStringW;
693
  fIdentificationStringW: TFuncIdentificationStringW;
692
  fDynamicIdentificationStringW: TFuncDynamicIdentificationStringW;
694
  fDynamicIdentificationStringW: TFuncDynamicIdentificationStringW;
693
  fCheckLicense: TFuncCheckLicense;
695
  fCheckLicense: TFuncCheckLicense;
694
  fDescribeOwnStatusCodeW: TFuncDescribeOwnStatusCodeW;
696
  fDescribeOwnStatusCodeW: TFuncDescribeOwnStatusCodeW;
695
  statusCode: UD2_STATUS;
697
  statusCode: UD2_STATUS;
696
  i: integer;
698
  i: integer;
697
  starttime, endtime, time: cardinal;
699
  starttime, endtime, time: cardinal;
698
  bakErrorMode: DWORD;
700
  bakErrorMode: DWORD;
699
  err: DWORD;
701
  err: DWORD;
700
 
702
 
701
  function _ErrorLookup(statusCode: UD2_STATUS): WideString;
703
  function _ErrorLookup(statusCode: UD2_STATUS): WideString;
702
  var
704
  var
703
    ret: BOOL;
705
    ret: BOOL;
704
    buf: array[0..cchBufferSize-1] of WideChar;
706
    buf: array[0..cchBufferSize-1] of WideChar;
705
  begin
707
  begin
706
    if Assigned(fDescribeOwnStatusCodeW) then
708
    if Assigned(fDescribeOwnStatusCodeW) then
707
    begin
709
    begin
708
      ZeroMemory(@buf, cchBufferSize);
710
      ZeroMemory(@buf, cchBufferSize);
709
      ret := fDescribeOwnStatusCodeW(@buf, cchBufferSize, statusCode, lngID);
711
      ret := fDescribeOwnStatusCodeW(@buf, cchBufferSize, statusCode, lngID);
710
      if ret then
712
      if ret then
711
      begin
713
      begin
712
        result := PWideChar(@buf);
714
        result := PWideChar(@buf);
713
        Exit;
715
        Exit;
714
      end;
716
      end;
715
    end;
717
    end;
716
    result := TUD2.GenericErrorLookup(statusCode);
718
    result := TUD2.GenericErrorLookup(statusCode);
717
  end;
719
  end;
718
 
720
 
719
  function _ApplyCompatibilityGUID: boolean;
721
  function _ApplyCompatibilityGUID: boolean;
720
  var
722
  var
721
    iniConfig: TIniFile;
723
    iniConfig: TIniFile;
722
    sOverrideGUID: string;
724
    sOverrideGUID: string;
723
    sPluginConfigFile: string;
725
    sPluginConfigFile: string;
724
  begin
726
  begin
725
    result := false;
727
    result := false;
726
    sPluginConfigFile := ChangeFileExt(dllFile, '.ini');
728
    sPluginConfigFile := ChangeFileExt(dllFile, '.ini');
727
    if FileExists(sPluginConfigFile) then
729
    if FileExists(sPluginConfigFile) then
728
    begin
730
    begin
729
      iniConfig := TIniFile.Create(sPluginConfigFile);
731
      iniConfig := TIniFile.Create(sPluginConfigFile);
730
      try
732
      try
731
        sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', '');
733
        sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', '');
732
        if sOverrideGUID <> '' then
734
        if sOverrideGUID <> '' then
733
        begin
735
        begin
734
          Plugin.FPluginGUIDSet := true;
736
          Plugin.FPluginGUIDSet := true;
735
          Plugin.FPluginGUID := StringToGUID(sOverrideGUID);
737
          Plugin.FPluginGUID := StringToGUID(sOverrideGUID);
736
          result := true;
738
          result := true;
737
        end;
739
        end;
738
      finally
740
      finally
739
        iniConfig.Free;
741
        iniConfig.Free;
740
      end;
742
      end;
741
    end;
743
    end;
742
  end;
744
  end;
743
 
745
 
744
  function _AutoOSNotSupportedMode: integer;
746
  function _AutoOSNotSupportedMode: integer;
745
  var
747
  var
746
    iniConfig: TIniFile;
748
    iniConfig: TIniFile;
747
    sPluginConfigFile: string;
749
    sPluginConfigFile: string;
748
  begin
750
  begin
749
    result := 0;
751
    result := 0;
750
    sPluginConfigFile := ChangeFileExt(dllFile, '.ini');
752
    sPluginConfigFile := ChangeFileExt(dllFile, '.ini');
751
    if FileExists(sPluginConfigFile) then
753
    if FileExists(sPluginConfigFile) then
752
    begin
754
    begin
753
      iniConfig := TIniFile.Create(sPluginConfigFile);
755
      iniConfig := TIniFile.Create(sPluginConfigFile);
754
      try
756
      try
755
        result := iniConfig.ReadInteger('Compatibility', 'AutoOSNotSupported', 0);
757
        result := iniConfig.ReadInteger('Compatibility', 'AutoOSNotSupported', 0);
756
      finally
758
      finally
757
        iniConfig.Free;
759
        iniConfig.Free;
758
      end;
760
      end;
759
    end;
761
    end;
760
  end;
762
  end;
761
 
763
 
762
  procedure _OverwriteStatusToOSNotSupported;
764
  procedure _OverwriteStatusToOSNotSupported;
763
  begin
765
  begin
764
    Plugin := TUD2Plugin.Create;
766
    Plugin := TUD2Plugin.Create;
765
    Plugin.FPluginDLL := dllFile;
767
    Plugin.FPluginDLL := dllFile;
766
    statusCode := UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED;
768
    statusCode := UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED;
767
    Plugin.FIdentificationProcedureStatusCode := statusCode;
769
    Plugin.FIdentificationProcedureStatusCode := statusCode;
768
    Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode);
770
    Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode);
769
    Plugin.FOSNotSupportedEnforced := true;
771
    Plugin.FOSNotSupportedEnforced := true;
770
    result := true;
772
    result := true;
771
  end;
773
  end;
772
 
774
 
773
resourcestring
775
resourcestring
774
  LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded: %s';
776
  LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded: %s';
775
  LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.';
777
  LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.';
776
  LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this application.';
778
  LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this application.';
777
  LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".';
779
  LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".';
778
  LNG_EXCEPTION = 'Fatal error while loading "%s" (%s: %s)';
780
  LNG_EXCEPTION = 'Fatal error while loading "%s" (%s: %s)';
779
begin
781
begin
780
  result := false;
782
  result := false;
781
  startTime := GetTickCount;
783
  startTime := GetTickCount;
782
 
784
 
783
  try
785
  try
784
    bakErrorMode := 0;
786
    bakErrorMode := 0;
785
    UD2_SetThreadErrorMode(SEM_FAILCRITICALERRORS, Pointer(bakErrorMode));
787
    UD2_SetThreadErrorMode(SEM_FAILCRITICALERRORS, Pointer(bakErrorMode));
786
    try
788
    try
787
      dllHandle := LoadLibrary(PChar(dllFile));
789
      dllHandle := LoadLibrary(PChar(dllFile));
788
      if dllHandle = 0 then
790
      if dllHandle = 0 then
789
      begin
791
      begin
790
        err := GetLastError;
792
        err := GetLastError;
791
 
793
 
792
        if ((_AutoOSNotSupportedMode = 1) and ((err = ERROR_DLL_NOT_FOUND) or (err = ERROR_PROC_NOT_FOUND))) or
794
        if ((_AutoOSNotSupportedMode = 1) and ((err = ERROR_DLL_NOT_FOUND) or (err = ERROR_PROC_NOT_FOUND))) or
793
           (_AutoOSNotSupportedMode >= 2) then
795
           (_AutoOSNotSupportedMode >= 2) then
794
        begin
796
        begin
795
          _OverwriteStatusToOSNotSupported;
797
          _OverwriteStatusToOSNotSupported;
796
          Exit;
798
          Exit;
797
        end;
799
        end;
798
 
800
 
799
        Errors.Add(Format(LNG_DLL_NOT_LOADED, [dllFile, SysErrorMessage(err)]));
801
        Errors.Add(Format(LNG_DLL_NOT_LOADED, [dllFile, SysErrorMessage(err)]));
800
        Exit;
802
        Exit;
801
      end;
803
      end;
802
      try
804
      try
803
        @fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID);
805
        @fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID);
804
        if not Assigned(fPluginInterfaceID) then
806
        if not Assigned(fPluginInterfaceID) then
805
        begin
807
        begin
806
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile]));
808
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile]));
807
          Exit;
809
          Exit;
808
        end;
810
        end;
809
        pluginInterfaceID := fPluginInterfaceID();
811
        pluginInterfaceID := fPluginInterfaceID();
810
        if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then
812
        if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then
811
        begin
813
        begin
812
          Errors.Add(Format(LNG_INVALID_PLUGIN, [dllFile]));
814
          Errors.Add(Format(LNG_INVALID_PLUGIN, [dllFile]));
813
          Exit;
815
          Exit;
814
        end;
816
        end;
815
 
817
 
816
        Plugin := TUD2Plugin.Create;
818
        Plugin := TUD2Plugin.Create;
817
        Plugin.FPluginDLL := dllFile;
819
        Plugin.FPluginDLL := dllFile;
818
 
820
 
819
        @fDynamicIdentificationStringW := GetProcAddress(dllHandle, mnDynamicIdentificationStringW);
821
        @fDynamicIdentificationStringW := GetProcAddress(dllHandle, mnDynamicIdentificationStringW);
820
        Plugin.FAcceptsDynamicRequests := Assigned(fDynamicIdentificationStringW);
822
        Plugin.FAcceptsDynamicRequests := Assigned(fDynamicIdentificationStringW);
821
 
823
 
822
        fIdentificationStringW := nil;
824
        fIdentificationStringW := nil;
823
        if useDynamicData then
825
        if useDynamicData then
824
        begin
826
        begin
825
          if not Plugin.AcceptsDynamicRequests then
827
          if not Plugin.AcceptsDynamicRequests then
826
          begin
828
          begin
827
            // TODO xxx: Darf hier ein fataler Fehler entstehen, obwohl dieses Szenario nur durch die INI file auftreten kann?
829
            // We should not output a fatal error here, because it is likely that the error is caused by the user writing a buggy INI file (specifying a parameter for a non-dynamic plugin)
-
 
830
            (*
-
 
831
            Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDynamicIdentificationStringW, dllFile]));
-
 
832
            Exit;
-
 
833
            *)
-
 
834
 
-
 
835
            // But we just try to find out if the plugin seems to be "OK"
-
 
836
            if not Assigned(fIdentificationStringW) then
828
            // TODO (allgemein): doku
837
            begin
829
            Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDynamicIdentificationStringW, dllFile]));
838
              Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDynamicIdentificationStringW, dllFile]));
830
            Exit;
839
              Exit;
-
 
840
            end;
-
 
841
 
-
 
842
            Plugin.FIdentificationProcedureStatusCode := UD2_STATUS_NOTAVAIL_DOES_NOT_ACCEPT_DYNAMIC_REQUESTS;
-
 
843
            Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode);
-
 
844
 
-
 
845
            Exit;
831
          end;
846
          end;
832
        end
847
        end
833
        else
848
        else
834
        begin
849
        begin
835
          @fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW);
850
          @fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW);
836
          if not Assigned(fIdentificationStringW) then
851
          if not Assigned(fIdentificationStringW) then
837
          begin
852
          begin
838
            Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile]));
853
            Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile]));
839
            Exit;
854
            Exit;
840
          end;
855
          end;
841
        end;
856
        end;
842
 
857
 
843
        @fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW);
858
        @fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW);
844
        if not Assigned(fPluginNameW) then
859
        if not Assigned(fPluginNameW) then
845
        begin
860
        begin
846
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile]));
861
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile]));
847
          Exit;
862
          Exit;
848
        end;
863
        end;
849
 
864
 
850
        @fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW);
865
        @fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW);
851
        if not Assigned(fPluginVendorW) then
866
        if not Assigned(fPluginVendorW) then
852
        begin
867
        begin
853
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile]));
868
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile]));
854
          Exit;
869
          Exit;
855
        end;
870
        end;
856
 
871
 
857
        @fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW);
872
        @fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW);
858
        if not Assigned(fPluginVersionW) then
873
        if not Assigned(fPluginVersionW) then
859
        begin
874
        begin
860
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile]));
875
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile]));
861
          Exit;
876
          Exit;
862
        end;
877
        end;
863
 
878
 
864
        @fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense);
879
        @fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense);
865
        if not Assigned(fCheckLicense) then
880
        if not Assigned(fCheckLicense) then
866
        begin
881
        begin
867
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile]));
882
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile]));
868
          Exit;
883
          Exit;
869
        end;
884
        end;
870
 
885
 
871
        @fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW);
886
        @fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW);
872
        if not Assigned(fIdentificationMethodNameW) then
887
        if not Assigned(fIdentificationMethodNameW) then
873
        begin
888
        begin
874
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile]));
889
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile]));
875
          Exit;
890
          Exit;
876
        end;
891
        end;
877
 
892
 
878
        @fDescribeOwnStatusCodeW := GetProcAddress(dllHandle, mnDescribeOwnStatusCodeW);
893
        @fDescribeOwnStatusCodeW := GetProcAddress(dllHandle, mnDescribeOwnStatusCodeW);
879
        if not Assigned(fDescribeOwnStatusCodeW) then
894
        if not Assigned(fDescribeOwnStatusCodeW) then
880
        begin
895
        begin
881
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDescribeOwnStatusCodeW, dllFile]));
896
          Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnDescribeOwnStatusCodeW, dllFile]));
882
          Exit;
897
          Exit;
883
        end;
898
        end;
884
 
899
 
885
        if not _ApplyCompatibilityGUID then
900
        if not _ApplyCompatibilityGUID then
886
        begin
901
        begin
887
          @fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier);
902
          @fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier);
888
          if not Assigned(fPluginIdentifier) then
903
          if not Assigned(fPluginIdentifier) then
889
          begin
904
          begin
890
            Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile]));
905
            Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile]));
891
            Exit;
906
            Exit;
892
          end;
907
          end;
893
          Plugin.FPluginGUIDSet := true;
908
          Plugin.FPluginGUIDSet := true;
894
          Plugin.FPluginGUID := fPluginIdentifier();
909
          Plugin.FPluginGUID := fPluginIdentifier();
895
        end;
910
        end;
896
 
911
 
897
        statusCode := fCheckLicense(nil);
912
        statusCode := fCheckLicense(nil);
898
        if statusCode.wCategory = UD2_STATUSCAT_FAILED then
913
        if statusCode.wCategory = UD2_STATUSCAT_FAILED then
899
        begin
914
        begin
900
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnCheckLicense, dllFile]));
915
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnCheckLicense, dllFile]));
901
          Exit;
916
          Exit;
902
        end;
917
        end;
903
 
918
 
904
        ZeroMemory(@buf, cchBufferSize);
919
        ZeroMemory(@buf, cchBufferSize);
905
        statusCode := fPluginNameW(@buf, cchBufferSize, lngID);
920
        statusCode := fPluginNameW(@buf, cchBufferSize, lngID);
906
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FPluginName := PWideChar(@buf)
921
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FPluginName := PWideChar(@buf)
907
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginName := ''
922
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginName := ''
908
        else
923
        else
909
        begin
924
        begin
910
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginNameW, dllFile]));
925
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginNameW, dllFile]));
911
          Exit;
926
          Exit;
912
        end;
927
        end;
913
 
928
 
914
        ZeroMemory(@buf, cchBufferSize);
929
        ZeroMemory(@buf, cchBufferSize);
915
        statusCode := fPluginVendorW(@buf, cchBufferSize, lngID);
930
        statusCode := fPluginVendorW(@buf, cchBufferSize, lngID);
916
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FPluginVendor := PWideChar(@buf)
931
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FPluginVendor := PWideChar(@buf)
917
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginVendor := ''
932
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginVendor := ''
918
        else
933
        else
919
        begin
934
        begin
920
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVendorW, dllFile]));
935
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVendorW, dllFile]));
921
          Exit;
936
          Exit;
922
        end;
937
        end;
923
 
938
 
924
        ZeroMemory(@buf, cchBufferSize);
939
        ZeroMemory(@buf, cchBufferSize);
925
        statusCode := fPluginVersionW(@buf, cchBufferSize, lngID);
940
        statusCode := fPluginVersionW(@buf, cchBufferSize, lngID);
926
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FPluginVersion := PWideChar(@buf)
941
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FPluginVersion := PWideChar(@buf)
927
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginVersion := ''
942
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginVersion := ''
928
        else
943
        else
929
        begin
944
        begin
930
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVersionW, dllFile]));
945
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVersionW, dllFile]));
931
          Exit;
946
          Exit;
932
        end;
947
        end;
933
 
948
 
934
        ZeroMemory(@buf, cchBufferSize);
949
        ZeroMemory(@buf, cchBufferSize);
935
        statusCode := fIdentificationMethodNameW(@buf, cchBufferSize);
950
        statusCode := fIdentificationMethodNameW(@buf, cchBufferSize);
936
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FIdentificationMethodName := PWideChar(@buf)
951
             if statusCode.wCategory = UD2_STATUSCAT_SUCCESS   then Plugin.FIdentificationMethodName := PWideChar(@buf)
937
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FIdentificationMethodName := ''
952
        else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FIdentificationMethodName := ''
938
        else
953
        else
939
        begin
954
        begin
940
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile]));
955
          Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile]));
941
          Exit;
956
          Exit;
942
        end;
957
        end;
943
 
958
 
944
        ZeroMemory(@buf, cchBufferSize);
959
        ZeroMemory(@buf, cchBufferSize);
945
        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)
960
        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)
946
        if useDynamicData then
961
        if useDynamicData then
947
        begin
962
        begin
948
          statusCode := fDynamicIdentificationStringW(@buf, cchBufferSize, PWideChar(dynamicData));
963
          statusCode := fDynamicIdentificationStringW(@buf, cchBufferSize, PWideChar(dynamicData));
949
        end
964
        end
950
        else
965
        else
951
        begin
966
        begin
952
          statusCode := fIdentificationStringW(@buf, cchBufferSize);
967
          statusCode := fIdentificationStringW(@buf, cchBufferSize);
953
        end;
968
        end;
954
        Plugin.FIdentificationProcedureStatusCode := statusCode;
969
        Plugin.FIdentificationProcedureStatusCode := statusCode;
955
        Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode);
970
        Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode);
956
        if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then
971
        if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then
957
        begin
972
        begin
958
          sIdentifier := PWideChar(@buf);
973
          sIdentifier := PWideChar(@buf);
959
          if UD2_STATUS_Equal(statusCode, UD2_STATUS_OK_MULTILINE, false) then
974
          if UD2_STATUS_Equal(statusCode, UD2_STATUS_OK_MULTILINE, false) then
960
          begin
975
          begin
961
            // Multiple identifiers (e.g. multiple MAC addresses are delimited via UD2_MULTIPLE_ITEMS_DELIMITER)
976
            // Multiple identifiers (e.g. multiple MAC addresses are delimited via UD2_MULTIPLE_ITEMS_DELIMITER)
962
            SetLength(ResultIdentifiers, 0);
977
            SetLength(ResultIdentifiers, 0);
963
            ResultIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier);
978
            ResultIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier);
964
            for i := Low(ResultIdentifiers) to High(ResultIdentifiers) do
979
            for i := Low(ResultIdentifiers) to High(ResultIdentifiers) do
965
            begin
980
            begin
966
              Plugin.AddIdentification(ResultIdentifiers[i]);
981
              Plugin.AddIdentification(ResultIdentifiers[i]);
967
            end;
982
            end;
968
          end
983
          end
969
          else
984
          else
970
          begin
985
          begin
971
            Plugin.AddIdentification(sIdentifier);
986
            Plugin.AddIdentification(sIdentifier);
972
 
987
 
973
            SetLength(ResultIdentifiers, 1);
988
            SetLength(ResultIdentifiers, 1);
974
            ResultIdentifiers[0] := sIdentifier;
989
            ResultIdentifiers[0] := sIdentifier;
975
          end;
990
          end;
976
        end
991
        end
977
        else if statusCode.wCategory <> UD2_STATUSCAT_NOT_AVAIL then
992
        else if statusCode.wCategory <> UD2_STATUSCAT_NOT_AVAIL then
978
        begin
993
        begin
979
          if _AutoOSNotSupportedMode >= 3 then
994
          if _AutoOSNotSupportedMode >= 3 then
980
          begin
995
          begin
981
            _OverwriteStatusToOSNotSupported;
996
            _OverwriteStatusToOSNotSupported;
982
            Exit;
997
            Exit;
983
          end;
998
          end;
984
 
999
 
985
          // Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationStringW, dllFile]));
1000
          // Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationStringW, dllFile]));
986
          Errors.Add(Format(LNG_METHOD_FAILURE, [Plugin.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile]));
1001
          Errors.Add(Format(LNG_METHOD_FAILURE, [Plugin.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile]));
987
          Exit;
1002
          Exit;
988
        end;
1003
        end;
989
 
1004
 
990
        result := true;
1005
        result := true;
991
      finally
1006
      finally
992
        if not result and Assigned(Plugin) then FreeAndNil(Plugin);
1007
        if not result and Assigned(Plugin) then FreeAndNil(Plugin);
993
        FreeLibrary(dllHandle);
1008
        FreeLibrary(dllHandle);
994
      end;
1009
      end;
995
    finally
1010
    finally
996
      UD2_SetThreadErrorMode(bakErrorMode, nil);
1011
      UD2_SetThreadErrorMode(bakErrorMode, nil);
997
 
1012
 
998
      if result then
1013
      if result then
999
      begin
1014
      begin
1000
        endtime := GetTickCount;
1015
        endtime := GetTickCount;
1001
        time := endtime - starttime;
1016
        time := endtime - starttime;
1002
        if endtime < starttime then time := High(Cardinal) - time;
1017
        if endtime < starttime then time := High(Cardinal) - time;
1003
        Plugin.FLoadingTime := time;
1018
        Plugin.FLoadingTime := time;
1004
      end;
1019
      end;
1005
    end;
1020
    end;
1006
  except
1021
  except
1007
    // TODO: when an exception happens in a cdecl DLL, then this code is somehow not
1022
    // TODO: when an exception happens in a cdecl DLL, then this code is somehow not
1008
    // executed. Probably the memory is corrupted. Anyway, a cdecl DLL shall NEVER
1023
    // executed. Probably the memory is corrupted. Anyway, a cdecl DLL shall NEVER
1009
    // raise an Exception.
1024
    // raise an Exception.
1010
    on E: Exception do
1025
    on E: Exception do
1011
    begin
1026
    begin
1012
      Errors.Add(Format(LNG_EXCEPTION, [dllFile, E.ClassName, E.Message]));
1027
      Errors.Add(Format(LNG_EXCEPTION, [dllFile, E.ClassName, E.Message]));
1013
      Exit;
1028
      Exit;
1014
    end;
1029
    end;
1015
  end;
1030
  end;
1016
end;
1031
end;
1017
 
1032
 
1018
end.
1033
end.
1019
 
1034