Subversion Repositories userdetect2

Rev

Rev 68 | Rev 70 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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