When including 'wine/port.h', include it first.
[wine] / dlls / quartz / regsvr.c
1 /*
2  * Regster/Unregister servers. (for internal use)
3  *
4  * hidenori@a2.ctktv.ne.jp
5  */
6
7 #include "config.h"
8
9 #include "windef.h"
10 #include "winbase.h"
11 #include "wingdi.h"
12 #include "winuser.h"
13 #include "winerror.h"
14 #include "winreg.h"
15 #include "uuids.h"
16
17 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(quartz);
19
20 #include "regsvr.h"
21
22 #ifndef NUMELEMS
23 #define NUMELEMS(elem)  (sizeof(elem)/sizeof((elem)[0]))
24 #endif  /* NUMELEMS */
25
26 const WCHAR QUARTZ_wszREG_SZ[] =
27         {'R','E','G','_','S','Z',0};
28 const WCHAR QUARTZ_wszInprocServer32[] =
29         {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
30 const WCHAR QUARTZ_wszThreadingModel[] =
31         {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
32 const WCHAR QUARTZ_wszBoth[] =
33         {'B','o','t','h',0};
34 const WCHAR QUARTZ_wszCLSID[] =
35         {'C','L','S','I','D',0};
36 const WCHAR QUARTZ_wszFilterData[] =
37         {'F','i','l','t','e','r',' ','D','a','t','a',0};
38 const WCHAR QUARTZ_wszFriendlyName[] =
39         {'F','r','i','e','n','d','l','y','N','a','m','e',0};
40 const WCHAR QUARTZ_wszInstance[] =
41         {'I','n','s','t','a','n','c','e',0};
42 const WCHAR QUARTZ_wszMerit[] =
43         {'M','e','r','i','t',0};
44
45 static
46 void QUARTZ_CatPathSepW( WCHAR* pBuf )
47 {
48         int     len = lstrlenW(pBuf);
49         pBuf[len] = '\\';
50         pBuf[len+1] = 0;
51 }
52
53 static
54 void QUARTZ_GUIDtoString( WCHAR* pBuf, const GUID* pguid )
55 {
56         /* W"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}" */
57         static const WCHAR wszFmt[] =
58                 {'{','%','0','8','X','-','%','0','4','X','-','%','0','4','X',
59                  '-','%','0','2','X','%','0','2','X','-','%','0','2','X','%',
60                  '0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
61                  '%','0','2','X','}',0};
62
63         wsprintfW( pBuf, wszFmt,
64                 pguid->Data1, pguid->Data2, pguid->Data3,
65                 pguid->Data4[0], pguid->Data4[1],
66                 pguid->Data4[2], pguid->Data4[3],
67                 pguid->Data4[4], pguid->Data4[5],
68                 pguid->Data4[6], pguid->Data4[7] );
69 }
70
71 static
72 LONG QUARTZ_RegOpenKeyW(
73         HKEY hkRoot, LPCWSTR lpszPath,
74         REGSAM rsAccess, HKEY* phKey,
75         BOOL fCreateKey )
76 {
77         DWORD   dwDisp;
78         WCHAR   wszREG_SZ[ NUMELEMS(QUARTZ_wszREG_SZ) ];
79
80         memcpy(wszREG_SZ,QUARTZ_wszREG_SZ,sizeof(QUARTZ_wszREG_SZ) );
81
82         if ( fCreateKey )
83                 return RegCreateKeyExW(
84                         hkRoot, lpszPath, 0, wszREG_SZ,
85                         REG_OPTION_NON_VOLATILE, rsAccess, NULL, phKey, &dwDisp );
86         else
87                 return RegOpenKeyExW(
88                         hkRoot, lpszPath, 0, rsAccess, phKey );
89 }
90
91 static
92 LONG QUARTZ_RegSetValueString(
93         HKEY hKey, LPCWSTR lpszName, LPCWSTR lpValue )
94 {
95         return RegSetValueExW(
96                 hKey, lpszName, 0, REG_SZ,
97                 (const BYTE*)lpValue,
98                 sizeof(lpValue[0]) * (lstrlenW(lpValue)+1) );
99 }
100
101 static
102 LONG QUARTZ_RegSetValueDWord(
103         HKEY hKey, LPCWSTR lpszName, DWORD dwValue )
104 {
105         return RegSetValueExW(
106                 hKey, lpszName, 0, REG_DWORD,
107                 (const BYTE*)(&dwValue), sizeof(DWORD) );
108 }
109
110 static
111 LONG QUARTZ_RegSetValueBinary(
112         HKEY hKey, LPCWSTR lpszName,
113         const BYTE* pData, int iLenOfData )
114 {
115         return RegSetValueExW(
116                 hKey, lpszName, 0, REG_BINARY, pData, iLenOfData );
117 }
118
119 HRESULT QUARTZ_CreateCLSIDPath(
120         WCHAR* pwszBuf, DWORD dwBufLen,
121         const CLSID* pclsid,
122         LPCWSTR lpszPathFromCLSID )
123 {
124         int avail;
125
126         lstrcpyW( pwszBuf, QUARTZ_wszCLSID );
127         QUARTZ_CatPathSepW( pwszBuf+5 );
128         QUARTZ_GUIDtoString( pwszBuf+6, pclsid );
129         if ( lpszPathFromCLSID != NULL )
130         {
131                 avail = (int)dwBufLen - lstrlenW(pwszBuf) - 8;
132                 if ( avail <= lstrlenW(lpszPathFromCLSID) )
133                         return E_FAIL;
134                 QUARTZ_CatPathSepW( pwszBuf );
135                 lstrcatW( pwszBuf, lpszPathFromCLSID );
136         }
137
138         return NOERROR;
139 }
140
141 HRESULT QUARTZ_OpenCLSIDKey(
142         HKEY* phKey,    /* [OUT] hKey */
143         REGSAM rsAccess,        /* [IN] access */
144         BOOL fCreate,   /* TRUE = RegCreateKey, FALSE = RegOpenKey */
145         const CLSID* pclsid,    /* CLSID */
146         LPCWSTR lpszPathFromCLSID )     /* related path from CLSID */
147 {
148         WCHAR   szKey[ 1024 ];
149         HRESULT hr;
150         LONG    lr;
151
152         hr = QUARTZ_CreateCLSIDPath(
153                 szKey, NUMELEMS(szKey),
154                 pclsid, lpszPathFromCLSID );
155         if ( FAILED(hr) )
156                 return hr;
157
158         lr = QUARTZ_RegOpenKeyW(
159                 HKEY_CLASSES_ROOT, szKey, rsAccess, phKey, fCreate );
160         if ( lr != ERROR_SUCCESS )
161                 return E_FAIL;
162
163         return S_OK;
164 }
165
166
167
168 HRESULT QUARTZ_RegisterAMovieDLLServer(
169         const CLSID* pclsid,    /* [IN] CLSID */
170         LPCWSTR lpFriendlyName, /* [IN] Friendly name */
171         LPCWSTR lpNameOfDLL,    /* [IN] name of the registered DLL */
172         BOOL fRegister )        /* [IN] TRUE = register, FALSE = unregister */
173 {
174         HRESULT hr;
175         HKEY    hKey;
176
177         if ( fRegister )
178         {
179                 hr = QUARTZ_OpenCLSIDKey(
180                         &hKey, KEY_ALL_ACCESS, TRUE,
181                         pclsid, NULL );
182                 if ( FAILED(hr) )
183                         return hr;
184
185                         if ( lpFriendlyName != NULL && QUARTZ_RegSetValueString(
186                                 hKey, NULL, lpFriendlyName ) != ERROR_SUCCESS )
187                                 hr = E_FAIL;
188
189                 RegCloseKey( hKey );
190                 if ( FAILED(hr) )
191                         return hr;
192
193                 hr = QUARTZ_OpenCLSIDKey(
194                         &hKey, KEY_ALL_ACCESS, TRUE,
195                         pclsid, QUARTZ_wszInprocServer32 );
196                 if ( FAILED(hr) )
197                         return hr;
198
199                         if ( QUARTZ_RegSetValueString(
200                                 hKey, NULL, lpNameOfDLL ) != ERROR_SUCCESS )
201                                 hr = E_FAIL;
202                         if ( QUARTZ_RegSetValueString(
203                                 hKey, QUARTZ_wszThreadingModel,
204                                 QUARTZ_wszBoth ) != ERROR_SUCCESS )
205                                 hr = E_FAIL;
206
207                 RegCloseKey( hKey );
208                 if ( FAILED(hr) )
209                         return hr;
210         }
211         else
212         {
213                 hr = QUARTZ_OpenCLSIDKey(
214                         &hKey, KEY_ALL_ACCESS, FALSE,
215                         pclsid, NULL );
216                 if ( FAILED(hr) )
217                         return NOERROR;
218
219                         RegDeleteValueW( hKey, NULL );
220                         RegDeleteValueW( hKey, QUARTZ_wszThreadingModel );
221
222                 RegCloseKey( hKey );
223                 if ( FAILED(hr) )
224                         return hr;
225
226                 /* I think key should be deleted only if no subkey exists. */
227                 FIXME( "unregister %s - key should be removed!\n",
228                                 debugstr_guid(pclsid) );
229         }
230
231         return NOERROR;
232 }
233
234
235 HRESULT QUARTZ_RegisterCategory(
236         const CLSID* pguidFilterCategory,       /* [IN] Category */
237         LPCWSTR lpFriendlyName, /* [IN] friendly name */
238         DWORD dwMerit,  /* [IN] merit */
239         BOOL fRegister )        /* [IN] TRUE = register, FALSE = unregister */
240 {
241         HRESULT hr;
242         HKEY    hKey;
243         WCHAR   szFilterPath[ 256 ];
244         WCHAR   szCLSID[ 256 ];
245
246         QUARTZ_GUIDtoString( szCLSID, pguidFilterCategory );
247         lstrcpyW( szFilterPath, QUARTZ_wszInstance );
248         QUARTZ_CatPathSepW( szFilterPath );
249         lstrcatW( szFilterPath, szCLSID );
250
251         if ( fRegister )
252         {
253                 hr = QUARTZ_OpenCLSIDKey(
254                         &hKey, KEY_ALL_ACCESS, TRUE,
255                         &CLSID_ActiveMovieCategories, szFilterPath );
256                 if ( FAILED(hr) )
257                         return hr;
258
259                         if ( QUARTZ_RegSetValueString(
260                                 hKey, QUARTZ_wszCLSID, szCLSID ) != ERROR_SUCCESS )
261                                 hr = E_FAIL;
262                         if ( lpFriendlyName != NULL && QUARTZ_RegSetValueString(
263                                 hKey, QUARTZ_wszFriendlyName,
264                                 lpFriendlyName ) != ERROR_SUCCESS )
265                                 hr = E_FAIL;
266                         if ( dwMerit != 0 &&
267                                  QUARTZ_RegSetValueDWord(
268                                         hKey, QUARTZ_wszMerit, dwMerit ) != ERROR_SUCCESS )
269                                 hr = E_FAIL;
270
271                 RegCloseKey( hKey );
272                 if ( FAILED(hr) )
273                         return hr;
274         }
275         else
276         {
277                 hr = QUARTZ_OpenCLSIDKey(
278                         &hKey, KEY_ALL_ACCESS, FALSE,
279                         &CLSID_ActiveMovieCategories, szFilterPath );
280                 if ( FAILED(hr) )
281                         return NOERROR;
282
283                         RegDeleteValueW( hKey, QUARTZ_wszCLSID );
284                         RegDeleteValueW( hKey, QUARTZ_wszFriendlyName );
285                         RegDeleteValueW( hKey, QUARTZ_wszMerit );
286
287                 RegCloseKey( hKey );
288                 if ( FAILED(hr) )
289                         return hr;
290
291                 /* I think key should be deleted only if no subkey exists. */
292                 FIXME( "unregister category %s - key should be removed!\n",
293                         debugstr_guid(pguidFilterCategory) );
294         }
295
296         return NOERROR;
297 }
298
299
300 HRESULT QUARTZ_RegisterAMovieFilter(
301         const CLSID* pguidFilterCategory,       /* [IN] Category */
302         const CLSID* pclsid,    /* [IN] CLSID of this filter */
303         const BYTE* pbFilterData,       /* [IN] filter data(no spec) */
304         DWORD cbFilterData,     /* [IN] size of the filter data */
305         LPCWSTR lpFriendlyName, /* [IN] friendly name */
306         LPCWSTR lpInstance,     /* [IN] instance */
307         BOOL fRegister )        /* [IN] TRUE = register, FALSE = unregister */
308 {
309         HRESULT hr;
310         HKEY    hKey;
311         WCHAR   szFilterPath[ 256 ];
312         WCHAR   szCLSID[ 256 ];
313
314         QUARTZ_GUIDtoString( szCLSID, pclsid );
315         lstrcpyW( szFilterPath, QUARTZ_wszInstance );
316         QUARTZ_CatPathSepW( szFilterPath );
317         lstrcatW( szFilterPath, ( lpInstance != NULL ) ? lpInstance : szCLSID );
318
319         if ( fRegister )
320         {
321                 hr = QUARTZ_OpenCLSIDKey(
322                         &hKey, KEY_ALL_ACCESS, TRUE,
323                         pguidFilterCategory, szFilterPath );
324                 if ( FAILED(hr) )
325                         return hr;
326
327                         if ( QUARTZ_RegSetValueString(
328                                 hKey, QUARTZ_wszCLSID, szCLSID ) != ERROR_SUCCESS )
329                                 hr = E_FAIL;
330                         if ( pbFilterData != NULL && cbFilterData > 0 &&
331                                  QUARTZ_RegSetValueBinary(
332                                         hKey, QUARTZ_wszFilterData,
333                                         pbFilterData, cbFilterData ) != ERROR_SUCCESS )
334                                 hr = E_FAIL;
335                         if ( lpFriendlyName != NULL && QUARTZ_RegSetValueString(
336                                 hKey, QUARTZ_wszFriendlyName,
337                                 lpFriendlyName ) != ERROR_SUCCESS )
338                                 hr = E_FAIL;
339
340                 RegCloseKey( hKey );
341                 if ( FAILED(hr) )
342                         return hr;
343         }
344         else
345         {
346                 hr = QUARTZ_OpenCLSIDKey(
347                         &hKey, KEY_ALL_ACCESS, FALSE,
348                         pguidFilterCategory, szFilterPath );
349                 if ( FAILED(hr) )
350                         return NOERROR;
351
352                         RegDeleteValueW( hKey, QUARTZ_wszCLSID );
353                         RegDeleteValueW( hKey, QUARTZ_wszFilterData );
354                         RegDeleteValueW( hKey, QUARTZ_wszFriendlyName );
355
356                 RegCloseKey( hKey );
357                 if ( FAILED(hr) )
358                         return hr;
359
360                 /* I think key should be deleted only if no subkey exists. */
361                 FIXME( "unregister category %s filter %s - key should be removed!\n",
362                         debugstr_guid(pguidFilterCategory),
363                         debugstr_guid(pclsid) );
364         }
365
366         return NOERROR;
367 }
368
369
370