Commit | Line | Data |
---|---|---|
d38cce8d RS |
1 | /* |
2 | * exported dll functions for devenum.dll | |
3 | * | |
4 | * Copyright (C) 2002 John K. Hohm | |
5 | * Copyright (C) 2002 Robert Shearman | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
21 | ||
22 | #include "devenum_private.h" | |
2e27f8c9 | 23 | #include "wine/debug.h" |
d38cce8d | 24 | #include "winreg.h" |
2e27f8c9 DS |
25 | |
26 | WINE_DEFAULT_DEBUG_CHANNEL(devenum); | |
27 | ||
d38cce8d RS |
28 | DWORD dll_ref = 0; |
29 | HINSTANCE DEVENUM_hInstance; | |
30 | ||
31 | typedef struct | |
32 | { | |
33 | REFCLSID clsid; | |
34 | LPCWSTR friendly_name; | |
35 | BOOL instance; | |
36 | } register_info; | |
37 | ||
38 | static HRESULT register_clsids(int count, const register_info * pRegInfo, LPCWSTR pszThreadingModel); | |
39 | ||
40 | /*********************************************************************** | |
41 | * Global string constant definitions | |
42 | */ | |
43 | const WCHAR clsid_keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 }; | |
44 | ||
45 | ||
46 | /*********************************************************************** | |
47 | * DllEntryPoint | |
48 | */ | |
49 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) | |
50 | { | |
51 | TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); | |
52 | ||
53 | switch(fdwReason) { | |
54 | case DLL_PROCESS_ATTACH: | |
55 | DEVENUM_hInstance = hinstDLL; | |
56 | DisableThreadLibraryCalls(hinstDLL); | |
57 | break; | |
58 | ||
59 | case DLL_PROCESS_DETACH: | |
60 | DEVENUM_hInstance = 0; | |
61 | break; | |
62 | } | |
63 | return TRUE; | |
64 | } | |
65 | ||
66 | /*********************************************************************** | |
67 | * DllGetClassObject (DEVENUM.@) | |
68 | */ | |
69 | HRESULT WINAPI DEVENUM_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) | |
70 | { | |
71 | TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv); | |
72 | ||
73 | *ppv = NULL; | |
74 | ||
75 | /* FIXME: we should really have two class factories. | |
76 | * Oh well - works just fine as it is */ | |
77 | if (IsEqualGUID(rclsid, &CLSID_SystemDeviceEnum) || | |
78 | IsEqualGUID(rclsid, &CLSID_CDeviceMoniker)) | |
26904868 | 79 | return IClassFactory_QueryInterface((LPCLASSFACTORY)(char*)&DEVENUM_ClassFactory, iid, ppv); |
d38cce8d RS |
80 | FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); |
81 | return CLASS_E_CLASSNOTAVAILABLE; | |
82 | } | |
83 | ||
84 | /*********************************************************************** | |
85 | * DllCanUnloadNow (DEVENUM.@) | |
86 | */ | |
87 | HRESULT WINAPI DEVENUM_DllCanUnloadNow(void) | |
88 | { | |
89 | return dll_ref != 0 ? S_FALSE : S_OK; | |
90 | } | |
91 | ||
92 | /*********************************************************************** | |
93 | * DllRegisterServer (DEVENUM.@) | |
94 | */ | |
95 | HRESULT WINAPI DEVENUM_DllRegisterServer(void) | |
96 | { | |
97 | HRESULT res; | |
98 | HKEY hkeyClsid = NULL; | |
99 | HKEY hkey1 = NULL; | |
100 | HKEY hkey2 = NULL; | |
101 | LPOLESTR pszClsidDevMon = NULL; | |
102 | IFilterMapper2 * pMapper = NULL; | |
103 | const WCHAR threadingModel[] = {'B','o','t','h',0}; | |
104 | const WCHAR sysdevenum[] = {'S','y','s','t','e','m',' ','D','e','v','i','c','e',' ','E','n','u','m',0}; | |
105 | const WCHAR devmon[] = {'D','e','v','i','c','e','M','o','n','i','k','e','r',0}; | |
106 | const WCHAR acmcat[] = {'A','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0}; | |
107 | const WCHAR vidcat[] = {'I','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0}; | |
108 | const WCHAR filtcat[] = {'A','c','t','i','v','e','M','o','v','i','e',' ','F','i','l','t','e','r',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0}; | |
109 | const WCHAR vfwcat[] = {'V','F','W',' ','C','a','p','t','u','r','e',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0}; | |
110 | const WCHAR wavein[] = {'W','a','v','e','I','n',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r', 0}; | |
111 | const WCHAR waveout[] = {'W','a','v','e','O','u','t',' ','a','n','d',' ','D','S','o','u','n','d',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0}; | |
112 | const WCHAR midiout[] = {'M','i','d','i','O','u','t',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0}; | |
113 | const WCHAR amcat[] = {'A','c','t','i','v','e','M','o','v','i','e',' ','F','i','l','t','e','r',' ','C','a','t','e','g','o','r','i','e','s',0}; | |
114 | const WCHAR device[] = {'d','e','v','i','c','e',0}; | |
115 | const WCHAR device_1[] = {'d','e','v','i','c','e','.','1',0}; | |
116 | const register_info ri[] = | |
117 | { | |
118 | {&CLSID_SystemDeviceEnum, sysdevenum, FALSE}, | |
119 | {&CLSID_CDeviceMoniker, devmon, FALSE}, | |
120 | {&CLSID_AudioCompressorCategory, acmcat, TRUE}, | |
121 | {&CLSID_VideoCompressorCategory, vidcat, TRUE}, | |
122 | {&CLSID_LegacyAmFilterCategory, filtcat, TRUE}, | |
123 | {&CLSID_VideoInputDeviceCategory, vfwcat, FALSE}, | |
124 | {&CLSID_AudioInputDeviceCategory, wavein, FALSE}, | |
125 | {&CLSID_AudioRendererCategory, waveout, FALSE}, | |
126 | {&CLSID_MidiRendererCategory, midiout, FALSE}, | |
127 | {&CLSID_ActiveMovieCategories, amcat, TRUE} | |
128 | }; | |
129 | ||
130 | TRACE("\n"); | |
131 | ||
132 | res = register_clsids(sizeof(ri) / sizeof(register_info), ri, threadingModel); | |
133 | ||
134 | /*** ActiveMovieFilter Categories ***/ | |
135 | { | |
136 | const WCHAR friendlyvidcap[] = {'V','i','d','e','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0}; | |
137 | const WCHAR friendlydshow[] = {'D','i','r','e','c','t','S','h','o','w',' ','F','i','l','t','e','r','s',0}; | |
138 | const WCHAR friendlyvidcomp[] = {'V','i','d','e','o',' ','C','o','m','p','r','e','s','s','o','r','s',0}; | |
139 | const WCHAR friendlyaudcap[] = {'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0}; | |
140 | const WCHAR friendlyaudcomp[] = {'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','o','r','s',0}; | |
141 | const WCHAR friendlyaudrend[] = {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r','s',0}; | |
142 | const WCHAR friendlymidirend[] = {'M','i','d','i',' ','R','e','n','d','e','r','e','r','s',0}; | |
143 | const WCHAR friendlyextrend[] = {'E','x','t','e','r','n','a','l',' ','R','e','n','d','e','r','e','r','s',0}; | |
144 | const WCHAR friendlydevctrl[] = {'D','e','v','i','c','e',' ','C','o','n','t','r','o','l',' ','F','i','l','t','e','r','s',0}; | |
26904868 MM |
145 | LPVOID mapvptr; |
146 | ||
d38cce8d | 147 | CoInitialize(NULL); |
26904868 | 148 | |
d38cce8d | 149 | res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, |
26904868 MM |
150 | &IID_IFilterMapper2, &mapvptr); |
151 | pMapper = (IFilterMapper2*)mapvptr; | |
d38cce8d RS |
152 | |
153 | IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoInputDeviceCategory, MERIT_DO_NOT_USE, friendlyvidcap); | |
154 | IFilterMapper2_CreateCategory(pMapper, &CLSID_LegacyAmFilterCategory, MERIT_NORMAL, friendlydshow); | |
155 | IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoCompressorCategory, MERIT_DO_NOT_USE, friendlyvidcomp); | |
156 | IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioInputDeviceCategory, MERIT_DO_NOT_USE, friendlyaudcap); | |
157 | IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioCompressorCategory, MERIT_DO_NOT_USE, friendlyaudcomp); | |
158 | IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioRendererCategory, MERIT_NORMAL, friendlyaudrend); | |
159 | IFilterMapper2_CreateCategory(pMapper, &CLSID_MidiRendererCategory, MERIT_NORMAL, friendlymidirend); | |
160 | IFilterMapper2_CreateCategory(pMapper, &CLSID_TransmitCategory, MERIT_DO_NOT_USE, friendlyextrend); | |
161 | IFilterMapper2_CreateCategory(pMapper, &CLSID_DeviceControlCategory, MERIT_DO_NOT_USE, friendlydevctrl); | |
162 | ||
163 | IFilterMapper2_Release(pMapper); | |
164 | CoUninitialize(); | |
165 | } | |
166 | ||
167 | /*** CDeviceMoniker ***/ | |
168 | if (SUCCEEDED(res)) | |
169 | { | |
170 | res = StringFromCLSID(&CLSID_CDeviceMoniker, &pszClsidDevMon); | |
171 | } | |
172 | if (SUCCEEDED(res)) | |
173 | { | |
174 | res = RegOpenKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkeyClsid) | |
175 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
176 | } | |
177 | if (SUCCEEDED(res)) | |
178 | { | |
179 | res = RegOpenKeyW(hkeyClsid, pszClsidDevMon, &hkey1) | |
180 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
181 | } | |
182 | if (SUCCEEDED(res)) | |
183 | { | |
184 | const WCHAR wszProgID[] = {'P','r','o','g','I','D',0}; | |
185 | res = RegCreateKeyW(hkey1, wszProgID, &hkey2) | |
186 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
187 | } | |
188 | if (SUCCEEDED(res)) | |
189 | { | |
190 | res = RegSetValueW(hkey2, NULL, REG_SZ, device_1, (lstrlenW(device_1) + 1) * sizeof(WCHAR)) | |
191 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
192 | } | |
193 | RegCloseKey(hkey2); | |
194 | if (SUCCEEDED(res)) | |
195 | { | |
196 | const WCHAR wszVProgID[] = {'V','e','r','s','i','o','n','I','n','d','e','p','e','d','e','n','t','P','r','o','g','I','D',0}; | |
197 | res = RegCreateKeyW(hkey1, wszVProgID, &hkey2) | |
198 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
199 | } | |
200 | if (SUCCEEDED(res)) | |
201 | { | |
202 | res = RegSetValueW(hkey2, NULL, REG_SZ, device, (lstrlenW(device) + 1) * sizeof(WCHAR)) | |
203 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
204 | } | |
205 | RegCloseKey(hkey2); | |
206 | RegCloseKey(hkey1); | |
207 | if (SUCCEEDED(res)) | |
208 | { | |
209 | res = RegCreateKeyW(HKEY_CLASSES_ROOT, device, &hkey1) | |
210 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
211 | } | |
212 | if (SUCCEEDED(res)) | |
213 | { | |
214 | res = RegCreateKeyW(hkey1, clsid_keyname, &hkey2) | |
215 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
216 | } | |
217 | if (SUCCEEDED(res)) | |
218 | { | |
219 | res = RegSetValueW(hkey2, NULL, REG_SZ, pszClsidDevMon, (lstrlenW(pszClsidDevMon) + 1) * sizeof(WCHAR)) | |
220 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
221 | } | |
222 | RegCloseKey(hkey2); | |
223 | RegCloseKey(hkey1); | |
224 | ||
225 | if (SUCCEEDED(res)) | |
226 | { | |
227 | res = RegCreateKeyW(HKEY_CLASSES_ROOT, device_1, &hkey1) | |
228 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
229 | } | |
230 | if (SUCCEEDED(res)) | |
231 | { | |
232 | res = RegCreateKeyW(hkey1, clsid_keyname, &hkey2) | |
233 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
234 | } | |
235 | if (SUCCEEDED(res)) | |
236 | { | |
237 | res = RegSetValueW(hkey2, NULL, REG_SZ, pszClsidDevMon, (lstrlenW(pszClsidDevMon) + 1) * sizeof(WCHAR)) | |
238 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
239 | } | |
240 | RegCloseKey(hkey2); | |
241 | RegCloseKey(hkey1); | |
242 | ||
243 | RegCloseKey(hkeyClsid); | |
244 | ||
245 | if (pszClsidDevMon) | |
246 | CoTaskMemFree(pszClsidDevMon); | |
247 | ||
248 | return res; | |
249 | } | |
250 | ||
2e27f8c9 | 251 | /*********************************************************************** |
d38cce8d | 252 | * DllUnregisterServer (DEVENUM.@) |
2e27f8c9 | 253 | */ |
d38cce8d | 254 | HRESULT WINAPI DEVENUM_DllUnregisterServer(void) |
2e27f8c9 | 255 | { |
d38cce8d RS |
256 | FIXME("stub!\n"); |
257 | return E_FAIL; | |
258 | } | |
259 | ||
260 | static HRESULT register_clsids(int count, const register_info * pRegInfo, LPCWSTR pszThreadingModel) | |
261 | { | |
262 | HRESULT res = S_OK; | |
263 | WCHAR dll_module[MAX_PATH]; | |
264 | LPOLESTR clsidString; | |
265 | HKEY hkeyClsid; | |
266 | HKEY hkeySub; | |
267 | HKEY hkeyInproc32; | |
268 | HKEY hkeyInstance = NULL; | |
269 | int i; | |
270 | const WCHAR wcszInproc32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0}; | |
271 | const WCHAR wcszThreadingModel[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; | |
272 | ||
273 | res = RegOpenKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkeyClsid) | |
274 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
275 | ||
276 | TRACE("HModule = %p\n", DEVENUM_hInstance); | |
277 | if (!GetModuleFileNameW(DEVENUM_hInstance, dll_module, | |
278 | sizeof(dll_module) / sizeof(WCHAR))) | |
279 | return HRESULT_FROM_WIN32(GetLastError()); | |
280 | ||
281 | for (i = 0; i < count; i++) | |
282 | { | |
283 | if (SUCCEEDED(res)) | |
284 | { | |
285 | res = StringFromCLSID(pRegInfo[i].clsid, &clsidString); | |
286 | } | |
287 | if (SUCCEEDED(res)) | |
288 | { | |
289 | res = RegCreateKeyW(hkeyClsid, clsidString, &hkeySub) | |
290 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
291 | } | |
292 | if (pRegInfo[i].instance && SUCCEEDED(res)) | |
293 | { | |
294 | res = RegCreateKeyW(hkeySub, wszInstanceKeyName, &hkeyInstance) | |
295 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
296 | RegCloseKey(hkeyInstance); | |
297 | } | |
298 | if (SUCCEEDED(res)) | |
299 | { | |
300 | RegSetValueW(hkeySub, | |
301 | NULL, | |
302 | REG_SZ, | |
303 | pRegInfo->friendly_name ? pRegInfo[i].friendly_name : clsidString, | |
304 | (lstrlenW(pRegInfo[i].friendly_name ? pRegInfo->friendly_name : clsidString) + 1) * sizeof(WCHAR)); | |
305 | res = RegCreateKeyW(hkeySub, wcszInproc32, &hkeyInproc32) | |
306 | == ERROR_SUCCESS ? S_OK : E_FAIL; | |
307 | } | |
308 | if (SUCCEEDED(res)) | |
309 | { | |
310 | RegSetValueW(hkeyInproc32, | |
311 | NULL, | |
312 | REG_SZ, | |
313 | dll_module, | |
314 | (lstrlenW(dll_module) + 1) * sizeof(WCHAR)); | |
315 | RegSetValueExW(hkeyInproc32, | |
316 | wcszThreadingModel, | |
317 | 0, | |
318 | REG_SZ, | |
319 | (LPVOID)pszThreadingModel, | |
320 | (lstrlenW(pszThreadingModel) + 1) * sizeof(WCHAR)); | |
321 | RegCloseKey(hkeyInproc32); | |
322 | } | |
323 | RegCloseKey(hkeySub); | |
324 | CoTaskMemFree(clsidString); | |
325 | clsidString = NULL; | |
326 | } | |
327 | ||
328 | RegCloseKey(hkeyClsid); | |
329 | ||
330 | return res; | |
2e27f8c9 | 331 | } |