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