Subversion Repositories userdetect2

Rev

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

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