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