Subversion Repositories userdetect2

Rev

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

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