12,6 → 12,9 |
Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf, |
UD2_PluginStatus, UD2_Utils, UD2_Parsing; |
|
const |
UD2_TagDescription = 'Description'; |
|
type |
TUD2IdentificationEntry = class; |
|
57,9 → 60,9 |
constructor Create; |
function AddIdentification(IdStr: WideString): TUD2IdentificationEntry; |
|
function InvokeDynamicCheck(dynamicData: WideString; var outIDs: TArrayOfString): boolean; overload; |
function InvokeDynamicCheck(dynamicData: WideString): boolean; overload; |
function GetDynamicRequestResult(dynamicData: WideString): TArrayOfString; |
function InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings; var outIDs: TArrayOfString): boolean; overload; |
function InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings): boolean; overload; |
function GetDynamicRequestResult(dynamicData: WideString; AErrorOut: TStrings=nil): TArrayOfString; |
|
function EqualsMethodNameOrGuid(idMethodNameOrGUID: string): boolean; |
end; |
95,11 → 98,11 |
property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins; |
property IniFile: TMemIniFile read FIniFile; |
procedure GetAllDetectedIDs(outSL: TStrings); |
function FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil): boolean; overload; |
function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; overload; |
function CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil): TUD2CommandArray; |
function FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; overload; |
function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; overload; |
function CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): TUD2CommandArray; |
function FindPluginByMethodNameOrGuid(idMethodName: string): TUD2Plugin; |
function GetCommandList(ShortTaskName: string): TUD2CommandArray; |
function GetCommandList(ShortTaskName: string; AErrorOut: TStrings=nil): TUD2CommandArray; |
procedure HandlePluginDir(APluginDir, AFileMask: string); |
procedure GetTaskListing(outSL: TStrings); |
constructor Create(AIniFileName: string); |
129,7 → 132,7 |
procedure Execute; override; |
function HandleDLL: boolean; |
public |
pl: TUD2Plugin; |
Plugin: TUD2Plugin; |
Errors: TStringList; |
ResultIdentifiers: TArrayOfString; |
constructor Create(Suspended: boolean; DLL: string; alngid: LANGID; useDynamicData: boolean; dynamicData: WideString); |
149,11 → 152,12 |
LNG_STATUS_NOTAVAIL_NO_ENTITIES = 'Not available (No entities to identify)'; |
LNG_STATUS_NOTAVAIL_WINAPI_CALL_FAILURE = 'Not available (A Windows API call failed. Message: %s)'; |
LNG_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC = 'Not available (Arguments required)'; |
LNG_STATUS_NOTAVAIL_INVALID_INPUT = 'Not available (Plugin received invalid input)'; |
LNG_UNKNOWN_NOTAVAIL = 'Not available (Unknown status code %s)'; |
|
LNG_STATUS_FAILURE_UNSPECIFIED = 'Error (Unspecified)'; |
LNG_STATUS_FAILURE_BUFFER_TOO_SMALL = 'Error (The provided buffer is too small!)'; |
LNG_STATUS_FAILURE_INVALID_ARGS = 'Error (The function received invalid arguments!)'; |
LNG_STATUS_FAILURE_INVALID_ARGS = 'Error (An internal function received invalid arguments!)'; |
LNG_STATUS_FAILURE_PLUGIN_NOT_LICENSED = 'Error (The plugin is not licensed)'; |
LNG_STATUS_FAILURE_NO_RETURNED_VALUE = 'Error (Plugin did not return a status)'; |
LNG_STATUS_FAILURE_CATCHED_EXCEPTION = 'Error (Catched unexpected Exception)'; |
171,6 → 175,7 |
else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_NO_ENTITIES, false) then result := LNG_STATUS_NOTAVAIL_NO_ENTITIES |
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)]) |
else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC, false) then result := LNG_STATUS_NOTAVAIL_ONLY_ACCEPT_DYNAMIC |
else if UD2_STATUS_Equal(grStatus, UD2_STATUS_NOTAVAIL_INVALID_INPUT, false) then result := LNG_STATUS_NOTAVAIL_INVALID_INPUT |
|
else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_UNSPECIFIED, false) then result := LNG_STATUS_FAILURE_UNSPECIFIED |
else if UD2_STATUS_Equal(grStatus, UD2_STATUS_FAILURE_BUFFER_TOO_SMALL, false) then result := LNG_STATUS_FAILURE_BUFFER_TOO_SMALL |
213,7 → 218,7 |
FDetectedIdentifications := TObjectList{<TUD2IdentificationEntry>}.Create(true); |
end; |
|
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; var outIDs: TArrayOfString): boolean; |
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings; var outIDs: TArrayOfString): boolean; |
var |
ude: TUD2IdentificationEntry; |
i: integer; |
238,7 → 243,7 |
// The dynamic content was already evaluated (and therefore is already added in FDetectedIdentifications). |
if Length(outIDs) > 0 then exit; |
|
outIDs := GetDynamicRequestResult(dynamicData); |
outIDs := GetDynamicRequestResult(dynamicData, AErrorOut); |
|
for i := 0 to Length(outIDs)-1 do |
begin |
252,20 → 257,32 |
end; |
end; |
|
function TUD2Plugin.GetDynamicRequestResult(dynamicData: WideString): TArrayOfString; |
function TUD2Plugin.GetDynamicRequestResult(dynamicData: WideString; AErrorOut: TStrings=nil): TArrayOfString; |
var |
lngID: LANGID; |
pll: TUD2PluginLoader; |
loader: TUD2PluginLoader; |
begin |
lngID := GetSystemDefaultLangID; |
|
pll := TUD2PluginLoader.Create(false, PluginDLL, lngid, true, dynamicData); |
loader := TUD2PluginLoader.Create(false, PluginDLL, lngid, true, dynamicData); |
try |
pll.WaitFor; |
result := pll.ResultIdentifiers; |
if Assigned(pll.pl) then FreeAndNil(pll.pl); |
loader.WaitFor; |
result := loader.ResultIdentifiers; |
if Assigned(AErrorOut) then |
begin |
AErrorOut.AddStrings(loader.Errors); |
end; |
|
// TODO: Use assign() instead? or allow TUD2PluginLoader to write the TPlugin object directly? |
// Should we even overwrite the current plugin data, or return the new plugin? |
FIdentificationProcedureStatusCode := loader.plugin.IdentificationProcedureStatusCode; |
FIdentificationProcedureStatusCodeDescribed := loader.plugin.IdentificationProcedureStatusCodeDescribed; |
FOSNotSupportedEnforced := loader.plugin.OSNotSupportedEnforced; |
FLoadingTime := loader.Plugin.LoadingTime; |
|
finally |
pll.Free; |
if Assigned(loader.Plugin) then FreeAndNil(loader.Plugin); |
loader.Free; |
end; |
end; |
|
275,11 → 292,11 |
SameText(GUIDToString(PluginGUID), idMethodNameOrGUID) |
end; |
|
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString): boolean; |
function TUD2Plugin.InvokeDynamicCheck(dynamicData: WideString; AErrorOut: TStrings): boolean; |
var |
dummy: TArrayOfString; |
begin |
result := InvokeDynamicCheck(dynamicData, dummy) |
result := InvokeDynamicCheck(dynamicData, AErrorOut, dummy) |
end; |
|
{ TUD2IdentificationEntry } |
302,6 → 319,13 |
APlugin: TUD2Plugin); |
begin |
inherited Create; |
|
// TODO: We need to do this, because ReadSectionValues strips the names of the name-value pairs... |
// We should correct ReadSectionValues... |
// Example: DriveSerial(c:):2SHSWNHA010807 X =calc.exe |
// ReadSectionValues will return "DriveSerial(c:):2SHSWNHA010807 X=calc.exe" |
AIdentificationString := Trim(AIdentificationString); |
|
FIdentificationString := AIdentificationString; |
FPlugin := APlugin; |
end; |
354,30 → 378,30 |
pluginLoader := tob.items[i] as TUD2PluginLoader; |
pluginLoader.WaitFor; |
Errors.AddStrings(pluginLoader.Errors); |
if Assigned(pluginLoader.pl) then |
if Assigned(pluginLoader.Plugin) then |
begin |
{$IFDEF CHECK_FOR_SAME_PLUGIN_GUID} |
if pluginLoader.pl.PluginGUIDSet then |
if pluginLoader.Plugin.PluginGUIDSet then |
begin |
sPluginID := GUIDToString(pluginLoader.pl.PluginGUID); |
sPluginID := GUIDToString(pluginLoader.Plugin.PluginGUID); |
prevDLL := FGUIDLookup.Values[sPluginID]; |
if (prevDLL <> '') and (prevDLL <> pluginLoader.pl.PluginDLL) then |
if (prevDLL <> '') and (prevDLL <> pluginLoader.Plugin.PluginDLL) then |
begin |
Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.pl.PluginDLL])); |
pluginLoader.pl.Free; |
Errors.Add(Format(LNG_PLUGINS_SAME_GUID, [prevDLL, pluginLoader.Plugin.PluginDLL])); |
pluginLoader.Plugin.Free; |
end |
else |
begin |
FGUIDLookup.Values[sPluginID] := pluginLoader.pl.PluginDLL; |
LoadedPlugins.Add(pluginLoader.pl); |
FGUIDLookup.Values[sPluginID] := pluginLoader.Plugin.PluginDLL; |
LoadedPlugins.Add(pluginLoader.Plugin); |
end; |
end |
else |
begin |
LoadedPlugins.Add(pluginLoader.pl); |
LoadedPlugins.Add(pluginLoader.Plugin); |
end; |
{$ELSE} |
LoadedPlugins.Add(pluginLoader.pl); |
LoadedPlugins.Add(pluginLoader.Plugin); |
{$ENDIF} |
end; |
pluginLoader.Free; |
412,7 → 436,7 |
resourcestring |
LNG_NO_DESCRIPTION = '(%s)'; |
begin |
result := FIniFile.ReadString(AShortTaskName, 'Description', Format(LNG_NO_DESCRIPTION, [AShortTaskName])); |
result := FIniFile.ReadString(AShortTaskName, UD2_TagDescription, Format(LNG_NO_DESCRIPTION, [AShortTaskName])); |
end; |
|
procedure TUD2.GetTaskListing(outSL: TStrings); |
481,12 → 505,12 |
end; |
end; |
|
function TUD2.FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil): boolean; |
function TUD2.FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; |
begin |
result := FulfilsEverySubterm(UD2_CondsToStr(conds), slIdNames); |
result := FulfilsEverySubterm(UD2_CondsToStr(conds), slIdNames, AErrorOut); |
end; |
|
function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; |
function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): boolean; |
var |
i: integer; |
p: TUD2Plugin; |
495,6 → 519,15 |
cond: TUD2TDFCondition; |
idName: string; |
begin |
{$IFDEF NO_CONDITIONS_IS_FAILURE} |
if idTerm = '' then |
begin |
SetLength(conds, 0); |
result := false; |
Exit; |
end; |
{$ENDIF} |
|
cleanUpStringList := slIdNames = nil; |
try |
if cleanUpStringList then |
515,7 → 548,7 |
p := FindPluginByMethodNameOrGuid(cond.idMethodName); |
if Assigned(p) then |
begin |
if p.InvokeDynamicCheck(cond.dynamicData) then |
if p.InvokeDynamicCheck(cond.dynamicData, AErrorOut) then |
begin |
// Reload the identifications |
slIdNames.Clear; |
557,7 → 590,7 |
end; |
end; |
|
function TUD2.GetCommandList(ShortTaskName: string): TUD2CommandArray; |
function TUD2.GetCommandList(ShortTaskName: string; AErrorOut: TStrings=nil): TUD2CommandArray; |
var |
i, j, l: integer; |
slSV, slIdNames: TStrings; |
575,7 → 608,7 |
FIniFile.ReadSectionValues(ShortTaskName, slSV); |
for i := 0 to slSV.Count-1 do |
begin |
tmpCmds := CheckTerm(slSV.Strings[i], slIdNames); |
tmpCmds := CheckTerm(slSV.Strings[i], slIdNames, AErrorOut); |
for j := Low(tmpCmds) to High(tmpCmds) do |
begin |
l := Length(result); |
591,7 → 624,7 |
end; |
end; |
|
function TUD2.CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil): TUD2CommandArray; |
function TUD2.CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil; AErrorOut: TStrings=nil): TUD2CommandArray; |
var |
slIdNamesCreated: boolean; |
ent: TUD2TDFEntry; |
608,7 → 641,7 |
end; |
|
if not UD2P_ParseTdfLine(idTermAndCmd, ent) then Exit; |
if FulfilsEverySubterm(ent.ids, slIdNames) then |
if FulfilsEverySubterm(ent.ids, slIdNames, AErrorOut) then |
begin |
result := ent.commands; |
end; |
630,7 → 663,7 |
begin |
inherited Create(Suspended); |
dllfile := dll; |
pl := nil; |
Plugin := nil; |
Errors := TStringList.Create; |
lngid := alngid; |
self.useDynamicData := useDynamicData; |
698,8 → 731,8 |
sOverrideGUID := iniConfig.ReadString('Compatibility', 'OverrideGUID', ''); |
if sOverrideGUID <> '' then |
begin |
pl.FPluginGUIDSet := true; |
pl.FPluginGUID := StringToGUID(sOverrideGUID); |
Plugin.FPluginGUIDSet := true; |
Plugin.FPluginGUID := StringToGUID(sOverrideGUID); |
result := true; |
end; |
finally |
728,12 → 761,12 |
|
procedure _OverwriteStatusToOSNotSupported; |
begin |
pl := TUD2Plugin.Create; |
pl.FPluginDLL := dllFile; |
Plugin := TUD2Plugin.Create; |
Plugin.FPluginDLL := dllFile; |
statusCode := UD2_STATUS_NOTAVAIL_OS_NOT_SUPPORTED; |
pl.FIdentificationProcedureStatusCode := statusCode; |
pl.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
pl.FOSNotSupportedEnforced := true; |
Plugin.FIdentificationProcedureStatusCode := statusCode; |
Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
Plugin.FOSNotSupportedEnforced := true; |
result := true; |
end; |
|
780,16 → 813,16 |
Exit; |
end; |
|
pl := TUD2Plugin.Create; |
pl.FPluginDLL := dllFile; |
Plugin := TUD2Plugin.Create; |
Plugin.FPluginDLL := dllFile; |
|
@fDynamicIdentificationStringW := GetProcAddress(dllHandle, mnDynamicIdentificationStringW); |
pl.FAcceptsDynamicRequests := Assigned(fDynamicIdentificationStringW); |
Plugin.FAcceptsDynamicRequests := Assigned(fDynamicIdentificationStringW); |
|
fIdentificationStringW := nil; |
if useDynamicData then |
begin |
if not pl.AcceptsDynamicRequests then |
if not Plugin.AcceptsDynamicRequests then |
begin |
// TODO xxx: Darf hier ein fataler Fehler entstehen, obwohl dieses Szenario nur durch die INI file auftreten kann? |
// TODO (allgemein): doku |
857,8 → 890,8 |
Errors.Add(Format(LNG_METHOD_NOT_FOUND, [mnPluginIdentifier, dllFile])); |
Exit; |
end; |
pl.FPluginGUIDSet := true; |
pl.FPluginGUID := fPluginIdentifier(); |
Plugin.FPluginGUIDSet := true; |
Plugin.FPluginGUID := fPluginIdentifier(); |
end; |
|
statusCode := fCheckLicense(nil); |
870,8 → 903,8 |
|
ZeroMemory(@buf, cchBufferSize); |
statusCode := fPluginNameW(@buf, cchBufferSize, lngID); |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.FPluginName := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.FPluginName := '' |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then Plugin.FPluginName := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginName := '' |
else |
begin |
Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginNameW, dllFile])); |
880,8 → 913,8 |
|
ZeroMemory(@buf, cchBufferSize); |
statusCode := fPluginVendorW(@buf, cchBufferSize, lngID); |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.FPluginVendor := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.FPluginVendor := '' |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then Plugin.FPluginVendor := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginVendor := '' |
else |
begin |
Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVendorW, dllFile])); |
890,8 → 923,8 |
|
ZeroMemory(@buf, cchBufferSize); |
statusCode := fPluginVersionW(@buf, cchBufferSize, lngID); |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.FPluginVersion := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.FPluginVersion := '' |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then Plugin.FPluginVersion := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FPluginVersion := '' |
else |
begin |
Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnPluginVersionW, dllFile])); |
900,8 → 933,8 |
|
ZeroMemory(@buf, cchBufferSize); |
statusCode := fIdentificationMethodNameW(@buf, cchBufferSize); |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then pl.FIdentificationMethodName := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then pl.FIdentificationMethodName := '' |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then Plugin.FIdentificationMethodName := PWideChar(@buf) |
else if statusCode.wCategory = UD2_STATUSCAT_NOT_AVAIL then Plugin.FIdentificationMethodName := '' |
else |
begin |
Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationMethodNameW, dllFile])); |
918,8 → 951,8 |
begin |
statusCode := fIdentificationStringW(@buf, cchBufferSize); |
end; |
pl.FIdentificationProcedureStatusCode := statusCode; |
pl.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
Plugin.FIdentificationProcedureStatusCode := statusCode; |
Plugin.FIdentificationProcedureStatusCodeDescribed := _ErrorLookup(statusCode); |
if statusCode.wCategory = UD2_STATUSCAT_SUCCESS then |
begin |
sIdentifier := PWideChar(@buf); |
930,12 → 963,12 |
ResultIdentifiers := SplitString(UD2_MULTIPLE_ITEMS_DELIMITER, sIdentifier); |
for i := Low(ResultIdentifiers) to High(ResultIdentifiers) do |
begin |
pl.AddIdentification(ResultIdentifiers[i]); |
Plugin.AddIdentification(ResultIdentifiers[i]); |
end; |
end |
else |
begin |
pl.AddIdentification(sIdentifier); |
Plugin.AddIdentification(sIdentifier); |
|
SetLength(ResultIdentifiers, 1); |
ResultIdentifiers[0] := sIdentifier; |
950,13 → 983,13 |
end; |
|
// Errors.Add(Format(LNG_METHOD_FAILURE, [_ErrorLookup(statusCode), mnIdentificationStringW, dllFile])); |
Errors.Add(Format(LNG_METHOD_FAILURE, [pl.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile])); |
Errors.Add(Format(LNG_METHOD_FAILURE, [Plugin.IdentificationProcedureStatusCodeDescribed, mnIdentificationStringW, dllFile])); |
Exit; |
end; |
|
result := true; |
finally |
if not result and Assigned(pl) then FreeAndNil(pl); |
if not result and Assigned(Plugin) then FreeAndNil(Plugin); |
FreeLibrary(dllHandle); |
end; |
finally |
967,7 → 1000,7 |
endtime := GetTickCount; |
time := endtime - starttime; |
if endtime < starttime then time := High(Cardinal) - time; |
pl.FLoadingTime := time; |
Plugin.FLoadingTime := time; |
end; |
end; |
except |