2 * exported dll functions for devenum.dll
4 * Copyright (C) 2002 John K. Hohm
5 * Copyright (C) 2002 Robert Shearman
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "devenum_private.h"
23 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(devenum
);
29 HINSTANCE DEVENUM_hInstance
;
34 LPCWSTR friendly_name
;
38 static HRESULT
register_clsids(int count
, const register_info
* pRegInfo
, LPCWSTR pszThreadingModel
);
39 static void DEVENUM_RegisterQuartz(void);
41 /***********************************************************************
42 * Global string constant definitions
44 const WCHAR clsid_keyname
[6] = { 'C', 'L', 'S', 'I', 'D', 0 };
46 /***********************************************************************
49 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
51 TRACE("%p 0x%lx %p\n", hinstDLL
, fdwReason
, fImpLoad
);
54 case DLL_PROCESS_ATTACH
:
55 DEVENUM_hInstance
= hinstDLL
;
56 DisableThreadLibraryCalls(hinstDLL
);
59 case DLL_PROCESS_DETACH
:
60 DEVENUM_hInstance
= 0;
66 /***********************************************************************
67 * DllGetClassObject (DEVENUM.@)
69 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID iid
, LPVOID
*ppv
)
71 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid
), debugstr_guid(iid
), ppv
);
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
))
79 return IClassFactory_QueryInterface((IClassFactory
*)&DEVENUM_ClassFactory
, iid
, ppv
);
81 FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid
),debugstr_guid(iid
));
82 return CLASS_E_CLASSNOTAVAILABLE
;
85 /***********************************************************************
86 * DllCanUnloadNow (DEVENUM.@)
88 HRESULT WINAPI
DllCanUnloadNow(void)
90 return dll_refs
!= 0 ? S_FALSE
: S_OK
;
93 /***********************************************************************
94 * DllRegisterServer (DEVENUM.@)
96 HRESULT WINAPI
DllRegisterServer(void)
99 HKEY hkeyClsid
= NULL
;
102 LPOLESTR pszClsidDevMon
= NULL
;
103 IFilterMapper2
* pMapper
= NULL
;
105 static const WCHAR threadingModel
[] = {'B','o','t','h',0};
106 static const WCHAR sysdevenum
[] = {'S','y','s','t','e','m',' ','D','e','v','i','c','e',' ','E','n','u','m',0};
107 static const WCHAR devmon
[] = {'D','e','v','i','c','e','M','o','n','i','k','e','r',0};
108 static const WCHAR acmcat
[] = {'A','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
109 static const WCHAR vidcat
[] = {'I','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
110 static 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};
111 static 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};
112 static const WCHAR wavein
[] = {'W','a','v','e','I','n',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r', 0};
113 static 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};
114 static const WCHAR midiout
[] = {'M','i','d','i','O','u','t',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
115 static 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};
116 static const WCHAR device
[] = {'d','e','v','i','c','e',0};
117 static const WCHAR device_1
[] = {'d','e','v','i','c','e','.','1',0};
118 static const register_info ri
[] =
120 {&CLSID_SystemDeviceEnum
, sysdevenum
, FALSE
},
121 {&CLSID_CDeviceMoniker
, devmon
, FALSE
},
122 {&CLSID_AudioCompressorCategory
, acmcat
, TRUE
},
123 {&CLSID_VideoCompressorCategory
, vidcat
, TRUE
},
124 {&CLSID_LegacyAmFilterCategory
, filtcat
, TRUE
},
125 {&CLSID_VideoInputDeviceCategory
, vfwcat
, FALSE
},
126 {&CLSID_AudioInputDeviceCategory
, wavein
, FALSE
},
127 {&CLSID_AudioRendererCategory
, waveout
, FALSE
},
128 {&CLSID_MidiRendererCategory
, midiout
, FALSE
},
129 {&CLSID_ActiveMovieCategories
, amcat
, TRUE
}
134 res
= register_clsids(sizeof(ri
) / sizeof(register_info
), ri
, threadingModel
);
136 /* Quartz is needed for IFilterMapper2 */
137 DEVENUM_RegisterQuartz();
139 /*** ActiveMovieFilter Categories ***/
143 res
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC
,
144 &IID_IFilterMapper2
, &mapvptr
);
147 static const WCHAR friendlyvidcap
[] = {'V','i','d','e','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0};
148 static const WCHAR friendlydshow
[] = {'D','i','r','e','c','t','S','h','o','w',' ','F','i','l','t','e','r','s',0};
149 static const WCHAR friendlyvidcomp
[] = {'V','i','d','e','o',' ','C','o','m','p','r','e','s','s','o','r','s',0};
150 static const WCHAR friendlyaudcap
[] = {'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0};
151 static const WCHAR friendlyaudcomp
[] = {'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','o','r','s',0};
152 static const WCHAR friendlyaudrend
[] = {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r','s',0};
153 static const WCHAR friendlymidirend
[] = {'M','i','d','i',' ','R','e','n','d','e','r','e','r','s',0};
154 static const WCHAR friendlyextrend
[] = {'E','x','t','e','r','n','a','l',' ','R','e','n','d','e','r','e','r','s',0};
155 static const WCHAR friendlydevctrl
[] = {'D','e','v','i','c','e',' ','C','o','n','t','r','o','l',' ','F','i','l','t','e','r','s',0};
157 pMapper
= (IFilterMapper2
*)mapvptr
;
159 IFilterMapper2_CreateCategory(pMapper
, &CLSID_VideoInputDeviceCategory
, MERIT_DO_NOT_USE
, friendlyvidcap
);
160 IFilterMapper2_CreateCategory(pMapper
, &CLSID_LegacyAmFilterCategory
, MERIT_NORMAL
, friendlydshow
);
161 IFilterMapper2_CreateCategory(pMapper
, &CLSID_VideoCompressorCategory
, MERIT_DO_NOT_USE
, friendlyvidcomp
);
162 IFilterMapper2_CreateCategory(pMapper
, &CLSID_AudioInputDeviceCategory
, MERIT_DO_NOT_USE
, friendlyaudcap
);
163 IFilterMapper2_CreateCategory(pMapper
, &CLSID_AudioCompressorCategory
, MERIT_DO_NOT_USE
, friendlyaudcomp
);
164 IFilterMapper2_CreateCategory(pMapper
, &CLSID_AudioRendererCategory
, MERIT_NORMAL
, friendlyaudrend
);
165 IFilterMapper2_CreateCategory(pMapper
, &CLSID_MidiRendererCategory
, MERIT_NORMAL
, friendlymidirend
);
166 IFilterMapper2_CreateCategory(pMapper
, &CLSID_TransmitCategory
, MERIT_DO_NOT_USE
, friendlyextrend
);
167 IFilterMapper2_CreateCategory(pMapper
, &CLSID_DeviceControlCategory
, MERIT_DO_NOT_USE
, friendlydevctrl
);
169 IFilterMapper2_Release(pMapper
);
172 /*** CDeviceMoniker ***/
175 res
= StringFromCLSID(&CLSID_CDeviceMoniker
, &pszClsidDevMon
);
179 res
= RegOpenKeyW(HKEY_CLASSES_ROOT
, clsid_keyname
, &hkeyClsid
)
180 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
184 res
= RegOpenKeyW(hkeyClsid
, pszClsidDevMon
, &hkey1
)
185 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
189 static const WCHAR wszProgID
[] = {'P','r','o','g','I','D',0};
190 res
= RegCreateKeyW(hkey1
, wszProgID
, &hkey2
)
191 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
195 res
= RegSetValueW(hkey2
, NULL
, REG_SZ
, device_1
, (lstrlenW(device_1
) + 1) * sizeof(WCHAR
))
196 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
207 static 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};
208 res
= RegCreateKeyW(hkey1
, wszVProgID
, &hkey2
)
209 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
213 res
= RegSetValueW(hkey2
, NULL
, REG_SZ
, device
, (lstrlenW(device
) + 1) * sizeof(WCHAR
))
214 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
231 res
= RegCreateKeyW(HKEY_CLASSES_ROOT
, device
, &hkey1
)
232 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
236 res
= RegCreateKeyW(hkey1
, clsid_keyname
, &hkey2
)
237 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
241 res
= RegSetValueW(hkey2
, NULL
, REG_SZ
, pszClsidDevMon
, (lstrlenW(pszClsidDevMon
) + 1) * sizeof(WCHAR
))
242 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
258 res
= RegCreateKeyW(HKEY_CLASSES_ROOT
, device_1
, &hkey1
)
259 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
263 res
= RegCreateKeyW(hkey1
, clsid_keyname
, &hkey2
)
264 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
268 res
= RegSetValueW(hkey2
, NULL
, REG_SZ
, pszClsidDevMon
, (lstrlenW(pszClsidDevMon
) + 1) * sizeof(WCHAR
))
269 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
279 RegCloseKey(hkeyClsid
);
282 CoTaskMemFree(pszClsidDevMon
);
289 /***********************************************************************
290 * DllUnregisterServer (DEVENUM.@)
292 HRESULT WINAPI
DllUnregisterServer(void)
298 static HRESULT
register_clsids(int count
, const register_info
* pRegInfo
, LPCWSTR pszThreadingModel
)
301 WCHAR dll_module
[MAX_PATH
];
302 LPOLESTR clsidString
;
306 HKEY hkeyInstance
= NULL
;
308 static const WCHAR wcszInproc32
[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
309 static const WCHAR wcszThreadingModel
[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
311 res
= RegOpenKeyW(HKEY_CLASSES_ROOT
, clsid_keyname
, &hkeyClsid
)
312 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
314 TRACE("HModule = %p\n", DEVENUM_hInstance
);
315 i
= GetModuleFileNameW(DEVENUM_hInstance
, dll_module
,
316 sizeof(dll_module
) / sizeof(WCHAR
));
318 return HRESULT_FROM_WIN32(GetLastError());
319 if (i
>= sizeof(dll_module
) / sizeof(WCHAR
))
320 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
322 for (i
= 0; i
< count
; i
++)
326 res
= StringFromCLSID(pRegInfo
[i
].clsid
, &clsidString
);
330 res
= RegCreateKeyW(hkeyClsid
, clsidString
, &hkeySub
)
331 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
333 if (pRegInfo
[i
].instance
&& SUCCEEDED(res
))
335 res
= RegCreateKeyW(hkeySub
, wszInstanceKeyName
, &hkeyInstance
)
336 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
337 RegCloseKey(hkeyInstance
);
341 RegSetValueW(hkeySub
,
344 pRegInfo
->friendly_name
? pRegInfo
[i
].friendly_name
: clsidString
,
345 (lstrlenW(pRegInfo
[i
].friendly_name
? pRegInfo
->friendly_name
: clsidString
) + 1) * sizeof(WCHAR
));
346 res
= RegCreateKeyW(hkeySub
, wcszInproc32
, &hkeyInproc32
)
347 == ERROR_SUCCESS
? S_OK
: E_FAIL
;
351 RegSetValueW(hkeyInproc32
,
355 (lstrlenW(dll_module
) + 1) * sizeof(WCHAR
));
356 RegSetValueExW(hkeyInproc32
,
360 (LPCVOID
)pszThreadingModel
,
361 (lstrlenW(pszThreadingModel
) + 1) * sizeof(WCHAR
));
362 RegCloseKey(hkeyInproc32
);
364 RegCloseKey(hkeySub
);
365 CoTaskMemFree(clsidString
);
369 RegCloseKey(hkeyClsid
);
374 typedef HRESULT (WINAPI
*DllRegisterServer_func
)(void);
376 /* calls DllRegisterServer() for the Quartz DLL */
377 static void DEVENUM_RegisterQuartz()
379 HANDLE hDLL
= LoadLibraryA("quartz.dll");
380 DllRegisterServer_func pDllRegisterServer
= NULL
;
382 pDllRegisterServer
= (DllRegisterServer_func
)GetProcAddress(hDLL
, "DllRegisterServer");
383 if (pDllRegisterServer
)
385 HRESULT hr
= pDllRegisterServer();
387 ERR("Failed to register Quartz. Error was 0x%lx)\n", hr
);