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