Subversion Repositories userdetect2

Compare Revisions

Regard whitespace Rev 68 → Rev 69

/trunk/UserDetect2/UD2_Obj.pas
10,7 → 10,7
Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs;
 
const
cchBufferSize = 2048;
cchBufferSize = 32768;
 
type
TUD2Plugin = class(TObject)
23,6 → 23,7
PluginVendor: WideString;
PluginVersion: WideString;
IdentificationMethodName: WideString;
Time: Cardinal;
function PluginGUIDString: string;
property DetectedIdentifications: TObjectList{<TUD2IdentificationEntry>}
read FDetectedIdentifications;
51,7 → 52,6
FIniFile: TMemIniFile;
FErrors: TStrings;
FIniFileName: string;
procedure HandleDLL(dllFile: string);
public
property IniFileName: string read FIniFileName;
property Errors: TStrings read FErrors;
75,19 → 75,61
uses
UD2_PluginIntf, UD2_Utils;
 
function UD2_ErrorLookup(ec: UD2_STATUSCODE): string;
type
TUD2PluginLoader = class(TThread)
protected
dllFile: string;
lngID: LANGID;
procedure Execute; override;
procedure HandleDLL;
public
pl: TUD2Plugin;
Errors: TStringList;
constructor Create(Suspended: boolean; DLL: string; alngid: LANGID);
destructor Destroy; override;
end;
 
function UD2_ErrorLookup(dwStatus: UD2_STATUS): string;
resourcestring
LNG_STATUS_OK = 'Operation completed sucessfully';
LNG_STATUS_BUFFER_TOO_SMALL = 'The provided buffer is too small!';
LNG_STATUS_INVALID_ARGS = 'The function received invalid arguments!';
LNG_STATUS_INVALID = 'Unexpected status code %s';
LNG_STATUS_NOT_LICENSED = 'The plugin is not licensed';
LNG_STATUS_OK_UNSPECIFIED = 'Unspecified generic success';
LNG_STATUS_OK_SINGLELINE = 'Operation successful; one identifier returned';
LNG_STATUS_OK_MULTILINE = 'Operation successful; multiple identifiers returned';
 
LNG_STATUS_NOTAVAIL_UNSPECIFIED = 'Unspecified generic "not available" status';
LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED = 'Operating system not supported';
LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED = 'Hardware not supported';
LNG_STATUS_NOTAVAIL_NO_ENTITIES = 'No entities to identify';
LNG_STATUS_NOTAVAIL_API_CALL_FAILURE = 'An API call failed';
 
LNG_STATUS_ERROR_UNSPECIFIED = 'Unspecified generic error';
LNG_STATUS_ERROR_BUFFER_TOO_SMALL = 'The provided buffer is too small!';
LNG_STATUS_ERROR_INVALID_ARGS = 'The function received invalid arguments!';
LNG_STATUS_ERROR_PLUGIN_NOT_LICENSED = 'The plugin is not licensed';
 
LNG_UNKNOWN_SUCCESS = 'Unknown "success" status code %s';
LNG_UNKNOWN_NOTAVAIL = 'Unknown "not available" status code %s';
LNG_UNKNOWN_FAILED = 'Unknown "failed" status code %s';
LNG_UNKNOWN_STATUS = 'Unknown status code with unexpected category: %s';
begin
if ec = UD2_STATUS_OK then result := LNG_STATUS_OK
else if ec = UD2_STATUS_BUFFER_TOO_SMALL then result := LNG_STATUS_BUFFER_TOO_SMALL
else if ec = UD2_STATUS_INVALID_ARGS then result := LNG_STATUS_INVALID_ARGS
else if ec = UD2_STATUS_NOT_LICENSED then result := LNG_STATUS_NOT_LICENSED
else result := Format(LNG_STATUS_INVALID, ['0x'+IntToHex(ec, 8)]);
if dwStatus = UD2_STATUS_OK_UNSPECIFIED then result := LNG_STATUS_OK_UNSPECIFIED
else if dwStatus = UD2_STATUS_OK_SINGLELINE then result := LNG_STATUS_OK_SINGLELINE
else if dwStatus = UD2_STATUS_OK_MULTILINE then result := LNG_STATUS_OK_MULTILINE
 
else if dwStatus = UD2_STATUS_NOTAVAIL_UNSPECIFIED then result := LNG_STATUS_NOTAVAIL_UNSPECIFIED
else if dwStatus = UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED then result := LNG_STATUS_NOTAVAIL_OS_NOT_SUPPORTED
else if dwStatus = UD2_STATUS_NOTAVAIL_HW_NOT_SUPPORTED then result := LNG_STATUS_NOTAVAIL_HW_NOT_SUPPORTED
else if dwStatus = UD2_STATUS_NOTAVAIL_NO_ENTITIES then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES
else if dwStatus = UD2_STATUS_NOTAVAIL_API_CALL_FAILURE then result := LNG_STATUS_NOTAVAIL_API_CALL_FAILURE
 
else if dwStatus = UD2_STATUS_ERROR_UNSPECIFIED then result := LNG_STATUS_ERROR_UNSPECIFIED
else if dwStatus = UD2_STATUS_ERROR_BUFFER_TOO_SMALL then result := LNG_STATUS_ERROR_BUFFER_TOO_SMALL
else if dwStatus = UD2_STATUS_ERROR_INVALID_ARGS then result := LNG_STATUS_ERROR_INVALID_ARGS
else if dwStatus = UD2_STATUS_ERROR_PLUGIN_NOT_LICENSED then result := LNG_STATUS_ERROR_PLUGIN_NOT_LICENSED
 
else if UD2_STATUS_Successful(dwStatus) then result := Format(LNG_UNKNOWN_SUCCESS, [UD2_STATUS_FormatStatusCode(dwStatus)])
else if UD2_STATUS_NotAvail(dwStatus) then result := Format(LNG_UNKNOWN_NOTAVAIL, [UD2_STATUS_FormatStatusCode(dwStatus)])
else if UD2_STATUS_Failed(dwStatus) then result := Format(LNG_UNKNOWN_FAILED, [UD2_STATUS_FormatStatusCode(dwStatus)])
else result := Format(LNG_UNKNOWN_STATUS, [UD2_STATUS_FormatStatusCode(dwStatus)]);
end;
 
{ TUD2Plugin }
140,237 → 182,70
 
{ TUD2 }
 
procedure TUD2.HandleDLL(dllFile: string);
 
procedure ReportError(AMsg: string);
begin
// MessageDlg(AMsg, mtError, [mbOk], 0);
Errors.Add(AMsg)
end;
 
var
sIdentifier: array[0..cchBufferSize-1] of WideChar;
sIdentifiers: TArrayOfString;
sPluginName: array[0..cchBufferSize-1] of WideChar;
sPluginVendor: array[0..cchBufferSize-1] of WideChar;
sPluginVersion: array[0..cchBufferSize-1] of WideChar;
sIdentificationMethodName: array[0..cchBufferSize-1] of WideChar;
sPluginConfigFile: string;
iniConfig: TINIFile;
sOverrideGUID: string;
pluginID: TGUID;
sPluginID: string;
pluginInterfaceID: TGUID;
dllHandle: cardinal;
fPluginInterfaceID: TFuncPluginInterfaceID;
fPluginIdentifier: TFuncPluginIdentifier;
fPluginNameW: TFuncPluginNameW;
fPluginVendorW: TFuncPluginVendorW;
fPluginVersionW: TFuncPluginVersionW;
fIdentificationMethodNameW: TFuncIdentificationMethodNameW;
fIdentificationStringW: TFuncIdentificationStringW;
fCheckLicense: TFuncCheckLicense;
statusCode: UD2_STATUSCODE;
pl: TUD2Plugin;
procedure TUD2.HandlePluginDir(APluginDir: string);
Var
SR: TSearchRec;
path: string;
x: TUD2PluginLoader;
tob: TObjectList;
i: integer;
lngID: LANGID;
sPluginID, v: string;
lngid: LANGID;
resourcestring
LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded.';
LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.';
LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this program version.';
LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".';
LNG_PLUGINS_SAME_GUID = 'Attention: The plugin "%s" and the plugin "%s" have the same identification GUID. The latter will not be loaded.';
begin
tob := TObjectList.Create;
try
tob.OwnsObjects := false;
 
lngID := GetSystemDefaultLangID;
 
dllHandle := LoadLibrary(PChar(dllFile));
if dllHandle = 0 then
path := IncludeTrailingPathDelimiter(APluginDir);
if FindFirst(path + '*.dll', 0, SR) = 0 then
begin
ReportError(Format(LNG_DLL_NOT_LOADED, [dllFile]));
end;
try
@fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID);
if not Assigned(fPluginInterfaceID) then
repeat
try
tob.Add(TUD2PluginLoader.Create(false, path+sr.Name, lngid));
except
on E: Exception do
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile]));
Exit;
MessageDlg(E.Message, mtError, [mbOK], 0);
end;
pluginInterfaceID := fPluginInterfaceID();
if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then
begin
ReportError(Format(LNG_INVALID_PLUGIN, [dllFile]));
Exit;
end;
 
@fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW);
if not Assigned(fIdentificationStringW) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile]));
Exit;
end;
 
@fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW);
if not Assigned(fPluginNameW) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile]));
Exit;
end;
 
@fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW);
if not Assigned(fPluginVendorW) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile]));
Exit;
end;
 
@fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW);
if not Assigned(fPluginVersionW) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile]));
Exit;
end;
 
@fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense);
if not Assigned(fCheckLicense) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile]));
Exit;
end;
 
@fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW);
if not Assigned(fIdentificationMethodNameW) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile]));
Exit;
end;
 
sPluginID := '';
 
sPluginConfigFile := ChangeFileExt(dllFile, '.ini');
if FileExists(sPluginConfigFile) then
begin
iniConfig := TIniFile.Create(sPluginConfigFile);
try
sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', '');
if sOverrideGUID <> '' then
begin
sPluginID := sOverrideGUID;
pluginID := StringToGUID(sPluginID);
end;
until FindNext(SR) <> 0;
finally
iniConfig.Free;
FindClose(SR);
end;
end;
 
if sPluginID = '' then
for i := 0 to tob.count-1 do
begin
@fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier);
if not Assigned(fPluginIdentifier) then
x := tob.items[i] as TUD2PluginLoader;
x.WaitFor;
Errors.AddStrings(x.Errors);
if Assigned(x.pl) then
begin
ReportError(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile]));
Exit;
end;
pluginID := fPluginIdentifier();
sPluginID := GUIDToString(pluginID);
end;
 
if (FGUIDLookup.Values[sPluginID] <> '') and (FGUIDLookup.Values[sPluginID] <> dllFile) then
sPluginID := GUIDToString(x.pl.PluginGUID);
v := FGUIDLookup.Values[sPluginID];
if (v <> '') and (v <> x.pl.PluginDLL) then
begin
ReportError(Format(LNG_PLUGINS_SAME_GUID, [FGUIDLookup.Values[sPluginID], dllFile]));
Exit;
Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [v, x.pl.PluginDLL]));
x.pl.Free;
end
else
begin
FGUIDLookup.Values[GUIDToString(pluginID)] := dllFile;
FGUIDLookup.Values[sPluginID] := x.pl.PluginDLL;
LoadedPlugins.Add(x.pl);
end;
 
statusCode := fCheckLicense(nil);
if statusCode <> UD2_STATUS_OK then
begin
ReportError(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnCheckLicense, dllFile]));
Exit;
end;
 
statusCode := fPluginNameW(@sPluginName, cchBufferSize, lngID);
if statusCode <> UD2_STATUS_OK then
begin
ReportError(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnPluginNameW, dllFile]));
Exit;
x.Free;
end;
 
statusCode := fPluginVendorW(@sPluginVendor, cchBufferSize, lngID);
if statusCode <> UD2_STATUS_OK then
begin
ReportError(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnPluginVendorW, dllFile]));
Exit;
end;
 
statusCode := fPluginVersionW(@sPluginVersion, cchBufferSize, lngID);
if statusCode <> UD2_STATUS_OK then
begin
ReportError(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnPluginVersionW, dllFile]));
Exit;
end;
 
statusCode := fIdentificationMethodNameW(@sIdentificationMethodName, cchBufferSize);
if statusCode <> UD2_STATUS_OK then
begin
ReportError(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile]));
Exit;
end;
 
pl := TUD2Plugin.Create;
pl.PluginDLL := dllFile;
pl.PluginGUID := pluginID;
pl.PluginName := sPluginName;
pl.PluginVendor := sPluginVendor;
pl.PluginVersion := sPluginVersion;
pl.IdentificationMethodName := sIdentificationMethodName;
LoadedPlugins.Add(pl);
 
statusCode := fIdentificationStringW(@sIdentifier, cchBufferSize);
if statusCode <> UD2_STATUS_OK then
begin
ReportError(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnIdentificationStringW, dllFile]));
Exit;
end;
 
if sIdentifier = '' then Exit;
 
// Multiple identifiers (e.g. multiple MAC addresses are delimited via #10 )
SetLength(sIdentifiers, 0);
sIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier);
for i := Low(sIdentifiers) to High(sIdentifiers) do
begin
pl.AddIdentification(sIdentifiers[i]);
end;
finally
FreeLibrary(dllHandle);
tob.free;
end;
end;
 
procedure TUD2.HandlePluginDir(APluginDir: string);
Var
SR: TSearchRec;
path: string;
begin
path := IncludeTrailingPathDelimiter(APluginDir);
if FindFirst(path + '*.dll', 0, SR) = 0 then
begin
repeat
try
HandleDLL(path + sr.Name);
except
on E: Exception do
begin
MessageDlg(E.Message, mtError, [mbOK], 0);
end;
end;
until FindNext(SR) <> 0;
FindClose(SR);
end;
end;
 
destructor TUD2.Destroy;
begin
FIniFile.Free;
389,8 → 264,10
end;
 
function TUD2.GetTaskName(AShortTaskName: string): string;
resourcestring
LNG_NO_DESCRIPTION = '(%s)';
begin
result := FIniFile.ReadString(AShortTaskName, 'Description', '('+AShortTaskName+')');
result := FIniFile.ReadString(AShortTaskName, 'Description', Format(LNG_NO_DESCRIPTION, [AShortTaskName]));
end;
 
procedure TUD2.GetTaskListing(outSL: TStrings);
506,4 → 383,232
end;
end;
 
{ TUD2PluginLoader }
 
procedure TUD2PluginLoader.Execute;
begin
inherited;
 
HandleDLL;
end;
 
constructor TUD2PluginLoader.Create(Suspended: boolean; DLL: string; alngid: LANGID);
begin
inherited Create(Suspended);
dllfile := dll;
pl := nil;
Errors := TStringList.Create;
lngid := alngid;
end;
 
destructor TUD2PluginLoader.Destroy;
begin
Errors.Free;
inherited;
end;
 
procedure TUD2PluginLoader.HandleDLL;
var
sIdentifier: WideString;
sIdentifiers: TArrayOfString;
buf: array[0..cchBufferSize-1] of WideChar;
sPluginConfigFile: string;
iniConfig: TINIFile;
sOverrideGUID: string;
pluginIDfound: boolean;
pluginInterfaceID: TGUID;
dllHandle: cardinal;
fPluginInterfaceID: TFuncPluginInterfaceID;
fPluginIdentifier: TFuncPluginIdentifier;
fPluginNameW: TFuncPluginNameW;
fPluginVendorW: TFuncPluginVendorW;
fPluginVersionW: TFuncPluginVersionW;
fIdentificationMethodNameW: TFuncIdentificationMethodNameW;
fIdentificationStringW: TFuncIdentificationStringW;
fCheckLicense: TFuncCheckLicense;
statusCode: UD2_STATUS;
i: integer;
starttime, endtime, time: cardinal;
loadSuccessful: boolean;
resourcestring
LNG_DLL_NOT_LOADED = 'Plugin DLL "%s" could not be loaded.';
LNG_METHOD_NOT_FOUND = 'Method "%s" not found in plugin "%s". The DLL is probably not a valid plugin DLL.';
LNG_INVALID_PLUGIN = 'The plugin "%s" is not a valid plugin for this program version.';
LNG_METHOD_FAILURE = 'Error "%s" at method "%s" of plugin "%s".';
begin
loadSuccessful := false;
startTime := GetTickCount;
 
dllHandle := LoadLibrary(PChar(dllFile));
if dllHandle = 0 then
begin
Errors.Add(Format(LNG_DLL_NOT_LOADED, [dllFile]));
end;
try
@fPluginInterfaceID := GetProcAddress(dllHandle, mnPluginInterfaceID);
if not Assigned(fPluginInterfaceID) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginInterfaceID, dllFile]));
Exit;
end;
pluginInterfaceID := fPluginInterfaceID();
if not IsEqualGUID(pluginInterfaceID, GUID_USERDETECT2_IDPLUGIN_V1) then
begin
Errors.Add(Format(LNG_INVALID_PLUGIN, [dllFile]));
Exit;
end;
 
@fIdentificationStringW := GetProcAddress(dllHandle, mnIdentificationStringW);
if not Assigned(fIdentificationStringW) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationStringW, dllFile]));
Exit;
end;
 
@fPluginNameW := GetProcAddress(dllHandle, mnPluginNameW);
if not Assigned(fPluginNameW) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginNameW, dllFile]));
Exit;
end;
 
@fPluginVendorW := GetProcAddress(dllHandle, mnPluginVendorW);
if not Assigned(fPluginVendorW) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVendorW, dllFile]));
Exit;
end;
 
@fPluginVersionW := GetProcAddress(dllHandle, mnPluginVersionW);
if not Assigned(fPluginVersionW) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginVersionW, dllFile]));
Exit;
end;
 
@fCheckLicense := GetProcAddress(dllHandle, mnCheckLicense);
if not Assigned(fCheckLicense) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnCheckLicense, dllFile]));
Exit;
end;
 
@fIdentificationMethodNameW := GetProcAddress(dllHandle, mnIdentificationMethodNameW);
if not Assigned(fIdentificationMethodNameW) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnIdentificationMethodNameW, dllFile]));
Exit;
end;
 
pl := TUD2Plugin.Create;
pl.PluginDLL := dllFile;
 
pluginIDfound := false;
sPluginConfigFile := ChangeFileExt(dllFile, '.ini');
if FileExists(sPluginConfigFile) then
begin
iniConfig := TIniFile.Create(sPluginConfigFile);
try
sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', '');
if sOverrideGUID <> '' then
begin
pl.PluginGUID := StringToGUID(sOverrideGUID);
pluginIDfound := true;
end;
finally
iniConfig.Free;
end;
end;
 
if not pluginIDfound then
begin
@fPluginIdentifier := GetProcAddress(dllHandle, mnPluginIdentifier);
if not Assigned(fPluginIdentifier) then
begin
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile]));
Exit;
end;
pl.PluginGUID := fPluginIdentifier();
end;
 
statusCode := fCheckLicense(nil);
if UD2_STATUS_Failed(statusCode) then
begin
Errors.Add(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnCheckLicense, dllFile]));
Exit;
end;
 
statusCode := fPluginNameW(@buf, cchBufferSize, lngID);
if UD2_STATUS_Successful(statusCode) then pl.PluginName := PWideChar(@buf)
else if UD2_STATUS_NotAvail(statusCode) then pl.PluginName := ''
else
begin
Errors.Add(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnPluginNameW, dllFile]));
Exit;
end;
 
statusCode := fPluginVendorW(@buf, cchBufferSize, lngID);
if UD2_STATUS_Successful(statusCode) then pl.PluginVendor := PWideChar(@buf)
else if UD2_STATUS_NotAvail(statusCode) then pl.PluginVendor := ''
else
begin
Errors.Add(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnPluginVendorW, dllFile]));
Exit;
end;
 
statusCode := fPluginVersionW(@buf, cchBufferSize, lngID);
if UD2_STATUS_Successful(statusCode) then pl.PluginVersion := PWideChar(@buf)
else if UD2_STATUS_NotAvail(statusCode) then pl.PluginVersion := ''
else
begin
Errors.Add(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnPluginVersionW, dllFile]));
Exit;
end;
 
statusCode := fIdentificationMethodNameW(@buf, cchBufferSize);
if UD2_STATUS_Successful(statusCode) then pl.IdentificationMethodName := PWideChar(@buf)
else if UD2_STATUS_NotAvail(statusCode) then pl.IdentificationMethodName := ''
else
begin
Errors.Add(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile]));
Exit;
end;
 
statusCode := fIdentificationStringW(@buf, cchBufferSize);
if UD2_STATUS_Successful(statusCode) then
begin
sIdentifier := PWideChar(@buf);
if statusCode = UD2_STATUS_OK_MULTILINE then
begin
// Multiple identifiers (e.g. multiple MAC addresses are delimited via #10 )
SetLength(sIdentifiers, 0);
sIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier);
for i := Low(sIdentifiers) to High(sIdentifiers) do
begin
pl.AddIdentification(sIdentifiers[i]);
end;
end
else
begin
pl.AddIdentification(sIdentifier);
end;
end
else if not UD2_STATUS_NotAvail(statusCode) then
begin
Errors.Add(Format(LNG_METHOD_FAILURE, [UD2_ErrorLookup(statusCode), mnIdentificationStringW, dllFile]));
Exit;
end;
 
endtime := GetTickCount;
time := endtime - starttime;
if endtime < starttime then time := High(Cardinal) - time;
pl.time := time;
 
loadSuccessful := true;
finally
if not loadSuccessful and Assigned(pl) then FreeAndNil(pl);
FreeLibrary(dllHandle);
end;
end;
 
end.