Don't return from overlapped ReadFile on EAGAIN and other non-fatal
[wine/gsoc_dplay.git] / dlls / quartz / devenum.c
blob925f9733abb937b24842d166f42b75598d807604
1 /*
2 * Implementation of CLSID_SystemDeviceEnum.
3 * Implements IMoniker for CLSID_CDeviceMoniker.
4 * Implements IPropertyBag. (internal)
6 * hidenori@a2.ctktv.ne.jp
7 */
9 #include "config.h"
11 #include "windef.h"
12 #include "winbase.h"
13 #include "wingdi.h"
14 #include "winuser.h"
15 #include "winreg.h"
16 #include "winerror.h"
17 #include "objidl.h"
18 #include "oleidl.h"
19 #include "ocidl.h"
20 #include "oleauto.h"
21 #include "strmif.h"
22 #include "uuids.h"
24 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(quartz);
27 #include "quartz_private.h"
28 #include "devenum.h"
29 #include "enumunk.h"
30 #include "complist.h"
31 #include "regsvr.h"
33 #ifndef NUMELEMS
34 #define NUMELEMS(elem) (sizeof(elem)/sizeof(elem[0]))
35 #endif /* NUMELEMS */
37 /***************************************************************************
39 * new/delete for CLSID_SystemDeviceEnum
43 /* can I use offsetof safely? - FIXME? */
44 static QUARTZ_IFEntry CSysDevEnum_IFEntries[] =
46 { &IID_ICreateDevEnum, offsetof(CSysDevEnum,createdevenum)-offsetof(CSysDevEnum,unk) },
50 static void QUARTZ_DestroySystemDeviceEnum(IUnknown* punk)
52 CSysDevEnum_THIS(punk,unk);
54 CSysDevEnum_UninitICreateDevEnum( This );
57 HRESULT QUARTZ_CreateSystemDeviceEnum(IUnknown* punkOuter,void** ppobj)
59 CSysDevEnum* psde;
60 HRESULT hr;
62 TRACE("(%p,%p)\n",punkOuter,ppobj);
64 psde = (CSysDevEnum*)QUARTZ_AllocObj( sizeof(CSysDevEnum) );
65 if ( psde == NULL )
66 return E_OUTOFMEMORY;
68 QUARTZ_IUnkInit( &psde->unk, punkOuter );
70 hr = CSysDevEnum_InitICreateDevEnum( psde );
71 if ( FAILED(hr) )
73 QUARTZ_FreeObj( psde );
74 return hr;
77 psde->unk.pEntries = CSysDevEnum_IFEntries;
78 psde->unk.dwEntries = sizeof(CSysDevEnum_IFEntries)/sizeof(CSysDevEnum_IFEntries[0]);
79 psde->unk.pOnFinalRelease = QUARTZ_DestroySystemDeviceEnum;
81 *ppobj = (void*)(&psde->unk);
83 return S_OK;
87 /***************************************************************************
89 * CSysDevEnum::ICreateDevEnum
94 static HRESULT WINAPI
95 ICreateDevEnum_fnQueryInterface(ICreateDevEnum* iface,REFIID riid,void** ppobj)
97 CSysDevEnum_THIS(iface,createdevenum);
99 TRACE("(%p)->()\n",This);
101 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
104 static ULONG WINAPI
105 ICreateDevEnum_fnAddRef(ICreateDevEnum* iface)
107 CSysDevEnum_THIS(iface,createdevenum);
109 TRACE("(%p)->()\n",This);
111 return IUnknown_AddRef(This->unk.punkControl);
114 static ULONG WINAPI
115 ICreateDevEnum_fnRelease(ICreateDevEnum* iface)
117 CSysDevEnum_THIS(iface,createdevenum);
119 TRACE("(%p)->()\n",This);
121 return IUnknown_Release(This->unk.punkControl);
124 static HRESULT WINAPI
125 ICreateDevEnum_fnCreateClassEnumerator(ICreateDevEnum* iface,REFCLSID rclsidDeviceClass,IEnumMoniker** ppobj, DWORD dwFlags)
127 CSysDevEnum_THIS(iface,createdevenum);
128 HRESULT hr;
129 HKEY hKey;
130 QUARTZ_CompList* pMonList;
131 IMoniker* pMon;
132 DWORD dwIndex;
133 LONG lr;
134 WCHAR wszPath[ 1024 ];
135 DWORD dwLen;
136 DWORD dwNameMax;
137 DWORD cbName;
138 FILETIME ftLastWrite;
140 TRACE("(%p)->(%s,%p,%08lx)\n",This,
141 debugstr_guid(rclsidDeviceClass),ppobj,dwFlags);
142 if ( dwFlags != 0 )
144 FIXME("unknown flags %08lx\n",dwFlags);
145 return E_NOTIMPL;
148 if ( ppobj == NULL )
149 return E_POINTER;
150 *ppobj = NULL;
152 hr = QUARTZ_CreateCLSIDPath(
153 wszPath, sizeof(wszPath)/sizeof(wszPath[0]) - 16,
154 rclsidDeviceClass, QUARTZ_wszInstance );
155 if ( FAILED(hr) )
156 return hr;
158 lr = RegOpenKeyExW( HKEY_CLASSES_ROOT, wszPath,
159 0, KEY_READ, &hKey );
160 if ( lr != ERROR_SUCCESS )
162 TRACE("cannot open %s\n",debugstr_w(wszPath));
163 if ( lr == ERROR_FILE_NOT_FOUND ||
164 lr == ERROR_PATH_NOT_FOUND )
165 return S_FALSE;
166 return E_FAIL;
169 dwLen = lstrlenW(wszPath);
170 wszPath[dwLen++] = '\\'; wszPath[dwLen] = 0;
171 dwNameMax = sizeof(wszPath)/sizeof(wszPath[0]) - dwLen - 8;
173 pMonList = QUARTZ_CompList_Alloc();
174 if ( pMonList == NULL )
176 hr = E_OUTOFMEMORY;
177 goto err;
180 /* enumerate all subkeys. */
181 dwIndex = 0;
182 while ( 1 )
184 cbName = dwNameMax;
185 lr = RegEnumKeyExW(
186 hKey, dwIndex, &wszPath[dwLen], &cbName,
187 NULL, NULL, NULL, &ftLastWrite );
188 if ( lr == ERROR_NO_MORE_ITEMS )
189 break;
190 if ( lr != ERROR_SUCCESS )
192 TRACE("RegEnumKeyEx returns %08lx\n",lr);
193 hr = E_FAIL;
194 goto err;
197 hr = QUARTZ_CreateDeviceMoniker(
198 HKEY_CLASSES_ROOT, wszPath, &pMon );
199 if ( FAILED(hr) )
200 goto err;
202 hr = QUARTZ_CompList_AddComp(
203 pMonList, (IUnknown*)pMon, NULL, 0 );
204 IMoniker_Release( pMon );
206 if ( FAILED(hr) )
207 goto err;
209 dwIndex ++;
212 /* create an enumerator. */
213 hr = QUARTZ_CreateEnumUnknown(
214 &IID_IEnumMoniker, (void**)ppobj, pMonList );
215 if ( FAILED(hr) )
216 goto err;
218 hr = S_OK;
219 err:
220 if ( pMonList != NULL )
221 QUARTZ_CompList_Free( pMonList );
222 RegCloseKey( hKey );
224 return hr;
227 static ICOM_VTABLE(ICreateDevEnum) icreatedevenum =
229 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
230 /* IUnknown fields */
231 ICreateDevEnum_fnQueryInterface,
232 ICreateDevEnum_fnAddRef,
233 ICreateDevEnum_fnRelease,
234 /* ICreateDevEnum fields */
235 ICreateDevEnum_fnCreateClassEnumerator,
238 HRESULT CSysDevEnum_InitICreateDevEnum( CSysDevEnum* psde )
240 TRACE("(%p)\n",psde);
241 ICOM_VTBL(&psde->createdevenum) = &icreatedevenum;
243 return NOERROR;
246 void CSysDevEnum_UninitICreateDevEnum( CSysDevEnum* psde )
248 TRACE("(%p)\n",psde);
252 /***************************************************************************
254 * CDeviceMoniker::IMoniker
258 static HRESULT WINAPI
259 IMoniker_fnQueryInterface(IMoniker* iface,REFIID riid,void** ppobj)
261 CDeviceMoniker_THIS(iface,moniker);
263 TRACE("(%p)->()\n",This);
265 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
268 static ULONG WINAPI
269 IMoniker_fnAddRef(IMoniker* iface)
271 CDeviceMoniker_THIS(iface,moniker);
273 TRACE("(%p)->()\n",This);
275 return IUnknown_AddRef(This->unk.punkControl);
278 static ULONG WINAPI
279 IMoniker_fnRelease(IMoniker* iface)
281 CDeviceMoniker_THIS(iface,moniker);
283 TRACE("(%p)->()\n",This);
285 return IUnknown_Release(This->unk.punkControl);
288 static HRESULT WINAPI IMoniker_fnGetClassID(IMoniker* iface, CLSID *pClassID)
290 CDeviceMoniker_THIS(iface,moniker);
292 TRACE("(%p)->()\n",This);
294 if ( pClassID == NULL )
295 return E_POINTER;
296 memcpy( pClassID, &CLSID_CDeviceMoniker, sizeof(CLSID) );
298 return NOERROR;
301 static HRESULT WINAPI IMoniker_fnIsDirty(IMoniker* iface)
303 CDeviceMoniker_THIS(iface,moniker);
305 FIXME("(%p)->() stub!\n",This);
307 return E_NOTIMPL;
310 static HRESULT WINAPI IMoniker_fnLoad(IMoniker* iface, IStream* pStm)
312 CDeviceMoniker_THIS(iface,moniker);
314 FIXME("(%p)->() stub!\n",This);
316 return E_NOTIMPL;
319 static HRESULT WINAPI IMoniker_fnSave(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
321 CDeviceMoniker_THIS(iface,moniker);
323 FIXME("(%p)->() stub!\n",This);
325 return E_NOTIMPL;
328 static HRESULT WINAPI IMoniker_fnGetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
330 CDeviceMoniker_THIS(iface,moniker);
332 FIXME("(%p)->() stub!\n",This);
334 return E_NOTIMPL;
337 static HRESULT WINAPI IMoniker_fnBindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
339 CDeviceMoniker_THIS(iface,moniker);
340 HRESULT hr;
341 IPropertyBag* pPropBag;
342 IPersistPropertyBag* pPersistPropBag;
343 VARIANT vClsid;
344 CLSID clsid;
346 TRACE("(%p)->(%p,%p,%s,%p)\n",This,
347 pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
348 if ( pbc != NULL )
350 FIXME("IBindCtx* pbc != NULL not implemented.\n");
351 return E_FAIL;
353 if ( pmkToLeft != NULL )
355 FIXME("IMoniker* pmkToLeft != NULL not implemented.\n");
356 return E_FAIL;
358 if ( ppvResult == NULL )
359 return E_POINTER;
361 hr = QUARTZ_CreateRegPropertyBag(
362 This->m_hkRoot, This->m_pwszPath, &pPropBag );
363 if ( FAILED(hr) )
364 return hr;
366 vClsid.n1.n2.vt = VT_BSTR;
367 hr = IPropertyBag_Read(
368 pPropBag, QUARTZ_wszCLSID, &vClsid, NULL );
369 IPropertyBag_Release( pPropBag );
370 if ( FAILED(hr) )
371 return hr;
373 hr = CLSIDFromString( vClsid.n1.n2.n3.bstrVal, &clsid );
374 SysFreeString(vClsid.n1.n2.n3.bstrVal);
375 if ( FAILED(hr) )
376 return hr;
378 hr = CoCreateInstance(
379 &clsid, NULL, CLSCTX_INPROC_SERVER, riid, ppvResult );
380 if ( FAILED(hr) )
381 return hr;
383 hr = IUnknown_QueryInterface((IUnknown*)*ppvResult,&IID_IPersistPropertyBag,(void**)&pPersistPropBag);
384 if ( hr == E_NOINTERFACE )
386 hr = S_OK;
388 else
389 if ( SUCCEEDED(hr) )
391 hr = QUARTZ_CreateRegPropertyBag(
392 This->m_hkRoot, This->m_pwszPath, &pPropBag );
393 if ( SUCCEEDED(hr) )
395 hr = IPersistPropertyBag_Load(pPersistPropBag,pPropBag,NULL);
396 IPropertyBag_Release( pPropBag );
398 IPersistPropertyBag_Release(pPersistPropBag);
401 if ( FAILED(hr) )
403 IUnknown_Release((IUnknown*)*ppvResult);
404 *ppvResult = NULL;
407 TRACE( "hr = %08lx\n", hr );
409 return hr;
412 static HRESULT WINAPI IMoniker_fnBindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
414 CDeviceMoniker_THIS(iface,moniker);
415 HRESULT hr;
417 TRACE("(%p)->(%p,%p,%s,%p)\n",This,
418 pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
419 if ( pbc != NULL )
421 FIXME("IBindCtx* pbc != NULL not implemented.\n");
422 return E_FAIL;
424 if ( pmkToLeft != NULL )
426 FIXME("IMoniker* pmkToLeft != NULL not implemented.\n");
427 return E_FAIL;
429 if ( ppvResult == NULL )
430 return E_POINTER;
432 hr = E_NOINTERFACE;
433 if ( IsEqualGUID(riid,&IID_IUnknown) ||
434 IsEqualGUID(riid,&IID_IPropertyBag) )
436 hr = QUARTZ_CreateRegPropertyBag(
437 This->m_hkRoot, This->m_pwszPath,
438 (IPropertyBag**)ppvResult );
441 return hr;
444 static HRESULT WINAPI IMoniker_fnReduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
446 CDeviceMoniker_THIS(iface,moniker);
448 TRACE("(%p)->()\n",This);
450 if ( ppmkReduced == NULL )
451 return E_POINTER;
453 *ppmkReduced = iface; IMoniker_AddRef(iface);
455 return MK_S_REDUCED_TO_SELF;
458 static HRESULT WINAPI IMoniker_fnComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
460 CDeviceMoniker_THIS(iface,moniker);
462 FIXME("(%p)->() stub!\n",This);
464 return E_NOTIMPL;
467 static HRESULT WINAPI IMoniker_fnEnum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
469 CDeviceMoniker_THIS(iface,moniker);
471 TRACE("(%p)->()\n",This);
473 if ( ppenumMoniker == NULL )
474 return E_POINTER;
476 *ppenumMoniker = NULL;
477 return NOERROR;
480 static HRESULT WINAPI IMoniker_fnIsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
482 CDeviceMoniker_THIS(iface,moniker);
484 FIXME("(%p)->() stub!\n",This);
486 return E_NOTIMPL;
489 static HRESULT WINAPI IMoniker_fnHash(IMoniker* iface,DWORD* pdwHash)
491 CDeviceMoniker_THIS(iface,moniker);
493 FIXME("(%p)->() stub!\n",This);
495 return E_NOTIMPL;
498 static HRESULT WINAPI IMoniker_fnIsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
500 CDeviceMoniker_THIS(iface,moniker);
502 FIXME("(%p)->() stub!\n",This);
504 return E_NOTIMPL;
507 static HRESULT WINAPI IMoniker_fnGetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime)
509 CDeviceMoniker_THIS(iface,moniker);
511 FIXME("(%p)->() stub!\n",This);
513 return E_NOTIMPL;
516 static HRESULT WINAPI IMoniker_fnInverse(IMoniker* iface,IMoniker** ppmk)
518 CDeviceMoniker_THIS(iface,moniker);
520 FIXME("(%p)->() stub!\n",This);
522 return E_NOTIMPL;
525 static HRESULT WINAPI IMoniker_fnCommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix)
527 CDeviceMoniker_THIS(iface,moniker);
529 FIXME("(%p)->() stub!\n",This);
531 return E_NOTIMPL;
534 static HRESULT WINAPI IMoniker_fnRelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
536 CDeviceMoniker_THIS(iface,moniker);
538 FIXME("(%p)->() stub!\n",This);
540 return E_NOTIMPL;
543 static HRESULT WINAPI IMoniker_fnGetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
545 CDeviceMoniker_THIS(iface,moniker);
547 FIXME("(%p)->() stub!\n",This);
549 return E_NOTIMPL;
552 static HRESULT WINAPI IMoniker_fnParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
554 CDeviceMoniker_THIS(iface,moniker);
556 FIXME("(%p)->() stub!\n",This);
558 return E_NOTIMPL;
561 static HRESULT WINAPI IMoniker_fnIsSystemMoniker(IMoniker* iface,DWORD* pdwMksys)
563 CDeviceMoniker_THIS(iface,moniker);
565 TRACE("(%p)->()\n",This);
566 if ( pdwMksys == NULL )
567 return E_POINTER;
569 *pdwMksys = MKSYS_NONE;
570 return S_FALSE;
574 static ICOM_VTABLE(IMoniker) imoniker =
576 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
577 /* IUnknown fields */
578 IMoniker_fnQueryInterface,
579 IMoniker_fnAddRef,
580 IMoniker_fnRelease,
581 /* IPersist fields */
582 IMoniker_fnGetClassID,
583 /* IPersistStream fields */
584 IMoniker_fnIsDirty,
585 IMoniker_fnLoad,
586 IMoniker_fnSave,
587 IMoniker_fnGetSizeMax,
588 /* IMoniker fields */
589 IMoniker_fnBindToObject,
590 IMoniker_fnBindToStorage,
591 IMoniker_fnReduce,
592 IMoniker_fnComposeWith,
593 IMoniker_fnEnum,
594 IMoniker_fnIsEqual,
595 IMoniker_fnHash,
596 IMoniker_fnIsRunning,
597 IMoniker_fnGetTimeOfLastChange,
598 IMoniker_fnInverse,
599 IMoniker_fnCommonPrefixWith,
600 IMoniker_fnRelativePathTo,
601 IMoniker_fnGetDisplayName,
602 IMoniker_fnParseDisplayName,
603 IMoniker_fnIsSystemMoniker,
607 static HRESULT CDeviceMoniker_InitIMoniker(
608 CDeviceMoniker* pdm, HKEY hkRoot, LPCWSTR lpKeyPath )
610 DWORD dwLen;
612 ICOM_VTBL(&pdm->moniker) = &imoniker;
613 pdm->m_hkRoot = hkRoot;
614 pdm->m_pwszPath = NULL;
616 dwLen = sizeof(WCHAR)*(lstrlenW(lpKeyPath)+1);
617 pdm->m_pwszPath = (WCHAR*)QUARTZ_AllocMem( dwLen );
618 if ( pdm->m_pwszPath == NULL )
619 return E_OUTOFMEMORY;
620 memcpy( pdm->m_pwszPath, lpKeyPath, dwLen );
622 return NOERROR;
625 static void CDeviceMoniker_UninitIMoniker(
626 CDeviceMoniker* pdm )
628 if ( pdm->m_pwszPath != NULL )
629 QUARTZ_FreeMem( pdm->m_pwszPath );
632 /***************************************************************************
634 * new/delete for CDeviceMoniker
638 static void QUARTZ_DestroyDeviceMoniker(IUnknown* punk)
640 CDeviceMoniker_THIS(punk,unk);
642 CDeviceMoniker_UninitIMoniker( This );
645 /* can I use offsetof safely? - FIXME? */
646 static QUARTZ_IFEntry CDeviceMoniker_IFEntries[] =
648 { &IID_IPersist, offsetof(CDeviceMoniker,moniker)-offsetof(CDeviceMoniker,unk) },
649 { &IID_IPersistStream, offsetof(CDeviceMoniker,moniker)-offsetof(CDeviceMoniker,unk) },
650 { &IID_IMoniker, offsetof(CDeviceMoniker,moniker)-offsetof(CDeviceMoniker,unk) },
653 HRESULT QUARTZ_CreateDeviceMoniker(
654 HKEY hkRoot, LPCWSTR lpKeyPath,
655 IMoniker** ppMoniker )
657 CDeviceMoniker* pdm;
658 HRESULT hr;
660 TRACE("(%08x,%s,%p)\n",hkRoot,debugstr_w(lpKeyPath),ppMoniker );
662 pdm = (CDeviceMoniker*)QUARTZ_AllocObj( sizeof(CDeviceMoniker) );
663 if ( pdm == NULL )
664 return E_OUTOFMEMORY;
666 QUARTZ_IUnkInit( &pdm->unk, NULL );
667 hr = CDeviceMoniker_InitIMoniker( pdm, hkRoot, lpKeyPath );
668 if ( FAILED(hr) )
670 QUARTZ_FreeObj( pdm );
671 return hr;
674 pdm->unk.pEntries = CDeviceMoniker_IFEntries;
675 pdm->unk.dwEntries = sizeof(CDeviceMoniker_IFEntries)/sizeof(CDeviceMoniker_IFEntries[0]);
676 pdm->unk.pOnFinalRelease = &QUARTZ_DestroyDeviceMoniker;
678 *ppMoniker = (IMoniker*)(&pdm->moniker);
680 return S_OK;
684 /***************************************************************************
686 * CRegPropertyBag::IPropertyBag
690 static HRESULT WINAPI
691 IPropertyBag_fnQueryInterface(IPropertyBag* iface,REFIID riid,void** ppobj)
693 CRegPropertyBag_THIS(iface,propbag);
695 TRACE("(%p)->()\n",This);
697 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
700 static ULONG WINAPI
701 IPropertyBag_fnAddRef(IPropertyBag* iface)
703 CRegPropertyBag_THIS(iface,propbag);
705 TRACE("(%p)->()\n",This);
707 return IUnknown_AddRef(This->unk.punkControl);
710 static ULONG WINAPI
711 IPropertyBag_fnRelease(IPropertyBag* iface)
713 CRegPropertyBag_THIS(iface,propbag);
715 TRACE("(%p)->()\n",This);
717 return IUnknown_Release(This->unk.punkControl);
720 static HRESULT WINAPI
721 IPropertyBag_fnRead(IPropertyBag* iface,LPCOLESTR lpszPropName,VARIANT* pVar,IErrorLog* pLog)
723 CRegPropertyBag_THIS(iface,propbag);
724 HRESULT hr;
725 LONG lr;
726 DWORD dwSize;
727 DWORD dwValueType;
728 DWORD dwDWordValue;
729 SAFEARRAYBOUND sab;
730 SAFEARRAY* pArray;
732 TRACE("(%p)->(%s,%p,%p)\n",This,
733 debugstr_w(lpszPropName),pVar,pLog);
735 if ( lpszPropName == NULL || pVar == NULL )
736 return E_POINTER;
738 dwSize = 0;
739 lr = RegQueryValueExW(
740 This->m_hKey, lpszPropName, NULL,
741 &dwValueType, NULL, &dwSize );
742 if ( lr != ERROR_SUCCESS )
744 WARN( "RegQueryValueExW failed.\n" );
745 return E_INVALIDARG;
748 switch ( dwValueType )
750 case REG_SZ:
751 TRACE( "REG_SZ / length = %lu\n", dwSize );
752 if ( pVar->n1.n2.vt == VT_EMPTY )
753 pVar->n1.n2.vt = VT_BSTR;
754 if ( pVar->n1.n2.vt != VT_BSTR )
756 FIXME( "type of VARIANT is not BSTR.\n" );
757 return E_FAIL;
760 pVar->n1.n2.n3.bstrVal = SysAllocStringByteLen(
761 NULL, dwSize );
762 if ( pVar->n1.n2.n3.bstrVal == NULL )
764 WARN( "out of memory.\n" );
765 return E_OUTOFMEMORY;
767 lr = RegQueryValueExW(
768 This->m_hKey, lpszPropName, NULL,
769 &dwValueType,
770 (BYTE*)pVar->n1.n2.n3.bstrVal, &dwSize );
771 if ( lr != ERROR_SUCCESS )
773 WARN( "failed to query value\n" );
774 SysFreeString(pVar->n1.n2.n3.bstrVal);
775 return E_FAIL;
777 TRACE( "value is BSTR; %s\n", debugstr_w(pVar->n1.n2.n3.bstrVal) );
778 break;
779 case REG_BINARY:
780 TRACE( "REG_BINARY / length = %lu\n", dwSize );
781 if ( pVar->n1.n2.vt == VT_EMPTY )
782 pVar->n1.n2.vt = VT_ARRAY|VT_UI1;
783 if ( pVar->n1.n2.vt != (VT_ARRAY|VT_UI1) )
785 FIXME( "type of VARIANT is not VT_ARRAY|VT_UI1.\n" );
786 return E_FAIL;
788 sab.lLbound = 0;
789 sab.cElements = dwSize;
790 pArray = SafeArrayCreate( VT_UI1, 1, &sab );
791 if ( pArray == NULL )
792 return E_OUTOFMEMORY;
793 hr = SafeArrayLock( pArray );
794 if ( FAILED(hr) )
796 WARN( "safe array can't be locked\n" );
797 SafeArrayDestroy( pArray );
798 return hr;
800 lr = RegQueryValueExW(
801 This->m_hKey, lpszPropName, NULL,
802 &dwValueType,
803 (BYTE*)pArray->pvData, &dwSize );
804 SafeArrayUnlock( pArray );
805 if ( lr != ERROR_SUCCESS )
807 WARN( "failed to query value\n" );
808 SafeArrayDestroy( pArray );
809 return E_FAIL;
811 pVar->n1.n2.n3.parray = pArray;
812 TRACE( "value is SAFEARRAY - array of BYTE; \n" );
813 break;
814 case REG_DWORD:
815 TRACE( "REG_DWORD / length = %lu\n", dwSize );
816 if ( dwSize != sizeof(DWORD) )
818 WARN( "The length of REG_DWORD value is not sizeof(DWORD).\n" );
819 return E_FAIL;
821 if ( pVar->n1.n2.vt == VT_EMPTY )
822 pVar->n1.n2.vt = VT_I4;
823 if ( pVar->n1.n2.vt != VT_I4 )
825 FIXME( "type of VARIANT is not VT_I4.\n" );
826 return E_FAIL;
828 lr = RegQueryValueExW(
829 This->m_hKey, lpszPropName, NULL,
830 &dwValueType,
831 (BYTE*)(&dwDWordValue), &dwSize );
832 if ( lr != ERROR_SUCCESS )
834 WARN( "failed to query value\n" );
835 return E_FAIL;
837 pVar->n1.n2.n3.lVal = dwDWordValue;
838 TRACE( "value is DWORD; %08lx\n", dwDWordValue );
839 break;
840 default:
841 FIXME("(%p)->(%s,%p,%p) - unsupported value type.\n",This,
842 debugstr_w(lpszPropName),pVar,pLog);
843 return E_FAIL;
846 TRACE( "returned successfully.\n" );
847 return NOERROR;
850 static HRESULT WINAPI
851 IPropertyBag_fnWrite(IPropertyBag* iface,LPCOLESTR lpszPropName,VARIANT* pVar)
853 CRegPropertyBag_THIS(iface,propbag);
854 HRESULT hr;
855 LONG lr;
856 DWORD dwDWordValue;
857 SAFEARRAY* pArray;
859 TRACE("(%p)->(%s,%p)\n",This,
860 debugstr_w(lpszPropName),pVar);
862 if ( lpszPropName == NULL || pVar == NULL )
863 return E_POINTER;
865 switch ( pVar->n1.n2.vt )
867 case VT_I4: /* REG_DWORD */
868 dwDWordValue = pVar->n1.n2.n3.lVal;
869 lr = RegSetValueExW(
870 This->m_hKey, lpszPropName, 0,
871 REG_DWORD,
872 (const BYTE*)(&dwDWordValue), sizeof(DWORD) );
873 if ( lr != ERROR_SUCCESS )
875 WARN( "failed to set value\n" );
876 return E_FAIL;
878 break;
879 case VT_BSTR: /* REG_SZ */
880 lr = RegSetValueExW(
881 This->m_hKey, lpszPropName, 0,
882 REG_SZ,
883 (const BYTE*)(pVar->n1.n2.n3.bstrVal),
884 SysStringByteLen( pVar->n1.n2.n3.bstrVal ) );
885 if ( lr != ERROR_SUCCESS )
887 WARN( "failed to set value\n" );
888 return E_FAIL;
890 break;
891 case (VT_ARRAY|VT_UI1): /* REG_BINARY */
892 pArray = pVar->n1.n2.n3.parray;
893 if ( pArray->cDims != 1 || pArray->cbElements != 1 ||
894 pArray->rgsabound[0].lLbound != 0 )
896 WARN( "invalid array\n" );
897 return E_INVALIDARG;
899 hr = SafeArrayLock( pArray );
900 if ( FAILED(hr) )
902 WARN( "safe array can't be locked\n" );
903 return hr;
905 lr = RegSetValueExW(
906 This->m_hKey, lpszPropName, 0,
907 REG_BINARY,
908 (const BYTE*)pArray->pvData,
909 pArray->rgsabound[0].cElements );
910 SafeArrayUnlock( pArray );
911 if ( lr != ERROR_SUCCESS )
913 WARN( "failed to set value\n" );
914 return E_FAIL;
916 break;
917 default:
918 FIXME("(%p)->(%s,%p) invalid/unsupported VARIANT type %04x\n",This,
919 debugstr_w(lpszPropName),pVar,pVar->n1.n2.vt);
920 return E_INVALIDARG;
923 TRACE( "returned successfully.\n" );
924 return NOERROR;
930 static ICOM_VTABLE(IPropertyBag) ipropbag =
932 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
933 /* IUnknown fields */
934 IPropertyBag_fnQueryInterface,
935 IPropertyBag_fnAddRef,
936 IPropertyBag_fnRelease,
937 /* IPropertyBag fields */
938 IPropertyBag_fnRead,
939 IPropertyBag_fnWrite,
942 static HRESULT CRegPropertyBag_InitIPropertyBag(
943 CRegPropertyBag* prpb, HKEY hkRoot, LPCWSTR lpKeyPath )
945 WCHAR wszREG_SZ[ NUMELEMS(QUARTZ_wszREG_SZ) ];
946 DWORD dwDisp;
948 ICOM_VTBL(&prpb->propbag) = &ipropbag;
950 memcpy(wszREG_SZ,QUARTZ_wszREG_SZ,sizeof(QUARTZ_wszREG_SZ) );
952 if ( RegCreateKeyExW(
953 hkRoot, lpKeyPath, 0, wszREG_SZ,
954 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
955 &prpb->m_hKey, &dwDisp ) != ERROR_SUCCESS )
956 return E_FAIL;
958 return NOERROR;
961 static void CRegPropertyBag_UninitIPropertyBag(
962 CRegPropertyBag* prpb )
964 RegCloseKey( prpb->m_hKey );
968 /***************************************************************************
970 * new/delete for CRegPropertyBag
974 static void QUARTZ_DestroyRegPropertyBag(IUnknown* punk)
976 CRegPropertyBag_THIS(punk,unk);
978 CRegPropertyBag_UninitIPropertyBag(This);
982 /* can I use offsetof safely? - FIXME? */
983 static QUARTZ_IFEntry CRegPropertyBag_IFEntries[] =
985 { &IID_IPropertyBag, offsetof(CRegPropertyBag,propbag)-offsetof(CRegPropertyBag,unk) },
988 HRESULT QUARTZ_CreateRegPropertyBag(
989 HKEY hkRoot, LPCWSTR lpKeyPath,
990 IPropertyBag** ppPropBag )
992 CRegPropertyBag* prpb;
993 HRESULT hr;
995 TRACE("(%08x,%s,%p)\n",hkRoot,debugstr_w(lpKeyPath),ppPropBag );
997 prpb = (CRegPropertyBag*)QUARTZ_AllocObj( sizeof(CRegPropertyBag) );
998 if ( prpb == NULL )
999 return E_OUTOFMEMORY;
1001 QUARTZ_IUnkInit( &prpb->unk, NULL );
1002 hr = CRegPropertyBag_InitIPropertyBag( prpb, hkRoot, lpKeyPath );
1003 if ( FAILED(hr) )
1005 QUARTZ_FreeObj( prpb );
1006 return hr;
1009 prpb->unk.pEntries = CRegPropertyBag_IFEntries;
1010 prpb->unk.dwEntries = sizeof(CRegPropertyBag_IFEntries)/sizeof(CRegPropertyBag_IFEntries[0]);
1011 prpb->unk.pOnFinalRelease = &QUARTZ_DestroyRegPropertyBag;
1013 *ppPropBag = (IPropertyBag*)(&prpb->propbag);
1015 return S_OK;
1018 /***************************************************************************
1020 * Helper for registering filters.
1024 HRESULT QUARTZ_GetFilterRegPath(
1025 WCHAR** ppwszPath, /* [OUT] path from HKEY_CLASSES_ROOT */
1026 const CLSID* pguidFilterCategory, /* [IN] Category */
1027 const CLSID* pclsid, /* [IN] CLSID of this filter */
1028 LPCWSTR lpInstance ) /* [IN] instance */
1030 HRESULT hr;
1031 WCHAR szKey[ 1024 ];
1032 WCHAR szFilterPath[ 512 ];
1033 WCHAR szCLSID[ 256 ];
1034 int buflen;
1036 TRACE("(%p,%s,%s,%s)\n",ppwszPath,debugstr_guid(pguidFilterCategory),debugstr_guid(pclsid),debugstr_w(lpInstance) );
1038 *ppwszPath = NULL;
1040 QUARTZ_GUIDtoString( szCLSID, pclsid );
1041 lstrcpyW( szFilterPath, QUARTZ_wszInstance );
1042 QUARTZ_CatPathSepW( szFilterPath );
1043 if ( lpInstance != NULL )
1045 if ( lstrlenW(lpInstance) >= 256 )
1046 return E_INVALIDARG;
1047 lstrcatW( szFilterPath, lpInstance );
1049 else
1051 lstrcatW( szFilterPath, szCLSID );
1054 hr = QUARTZ_CreateCLSIDPath(
1055 szKey, NUMELEMS(szKey),
1056 pguidFilterCategory, szFilterPath );
1057 if ( FAILED(hr) )
1058 return hr;
1060 buflen = sizeof(WCHAR)*(lstrlenW(szKey)+1);
1061 *ppwszPath = QUARTZ_AllocMem( buflen );
1062 if ( *ppwszPath == NULL )
1063 return E_OUTOFMEMORY;
1064 memcpy( *ppwszPath, szKey, buflen );
1065 return S_OK;
1068 HRESULT QUARTZ_RegisterFilterToMoniker(
1069 IMoniker* pMoniker, /* [IN] Moniker */
1070 const CLSID* pclsid, /* [IN] CLSID of this filter */
1071 LPCWSTR lpFriendlyName, /* [IN] friendly name */
1072 const BYTE* pbFilterData, /* [IN] filter data */
1073 DWORD cbFilterData ) /* [IN] size of the filter data */
1075 IPropertyBag* pPropBag = NULL;
1076 WCHAR wszClsid[128];
1077 VARIANT var;
1078 HRESULT hr;
1079 SAFEARRAYBOUND sab;
1080 SAFEARRAY* pArray = NULL;
1082 TRACE("(%p,%s,%s,%p,%08lu)\n",pMoniker,debugstr_guid(pclsid),debugstr_w(lpFriendlyName),pbFilterData,cbFilterData);
1084 hr = IMoniker_BindToStorage(pMoniker,NULL,NULL,&IID_IPropertyBag,(void**)&pPropBag);
1085 if ( FAILED(hr) )
1086 goto err;
1087 QUARTZ_GUIDtoString( wszClsid, pclsid );
1088 var.n1.n2.vt = VT_BSTR;
1089 var.n1.n2.n3.bstrVal = SysAllocString(wszClsid);
1090 if ( var.n1.n2.n3.bstrVal == NULL )
1092 hr = E_OUTOFMEMORY;
1093 goto err;
1095 hr = IPropertyBag_Write(pPropBag,QUARTZ_wszCLSID,&var);
1096 SysFreeString(var.n1.n2.n3.bstrVal);
1097 if ( FAILED(hr) )
1098 goto err;
1100 var.n1.n2.vt = VT_BSTR;
1101 var.n1.n2.n3.bstrVal = SysAllocString(lpFriendlyName);
1102 if ( var.n1.n2.n3.bstrVal == NULL )
1104 hr = E_OUTOFMEMORY;
1105 goto err;
1107 hr = IPropertyBag_Write(pPropBag,QUARTZ_wszFriendlyName,&var);
1108 SysFreeString(var.n1.n2.n3.bstrVal);
1109 if ( FAILED(hr) )
1110 goto err;
1112 if ( pbFilterData != NULL )
1114 var.n1.n2.vt = VT_ARRAY|VT_UI1;
1115 sab.lLbound = 0;
1116 sab.cElements = cbFilterData;
1117 pArray = SafeArrayCreate( VT_UI1, 1, &sab );
1118 if ( pArray == NULL )
1120 hr = E_OUTOFMEMORY;
1121 goto err;
1123 hr = SafeArrayLock( pArray );
1124 if ( FAILED(hr) )
1125 goto err;
1126 var.n1.n2.n3.parray = pArray;
1127 memcpy( pArray->pvData, pbFilterData, cbFilterData );
1128 hr = IPropertyBag_Write(pPropBag,QUARTZ_wszFilterData,&var);
1129 SafeArrayUnlock( pArray );
1130 if ( FAILED(hr) )
1131 goto err;
1134 hr = NOERROR;
1135 err:
1136 if ( pArray != NULL )
1137 SafeArrayDestroy( pArray );
1138 if ( pPropBag != NULL )
1139 IPropertyBag_Release(pPropBag);
1141 return hr;
1144 HRESULT QUARTZ_RegDeleteKey( HKEY hkRoot, LPCWSTR lpKeyPath )
1146 LONG lr;
1147 HRESULT hr;
1148 HKEY hKey;
1149 DWORD dwIndex;
1150 DWORD cbName;
1151 FILETIME ftLastWrite;
1152 DWORD dwType;
1153 WCHAR wszPath[ 512 ];
1155 TRACE("(%08x,%s)\n",hkRoot,debugstr_w(lpKeyPath));
1157 lr = RegOpenKeyExW( hkRoot, lpKeyPath, 0, KEY_ALL_ACCESS, &hKey );
1158 if ( lr == ERROR_SUCCESS )
1160 dwIndex = 0;
1161 while ( 1 )
1163 cbName = NUMELEMS(wszPath);
1164 lr = RegEnumKeyExW(
1165 hKey, dwIndex, wszPath, &cbName,
1166 NULL, NULL, NULL, &ftLastWrite );
1167 if ( lr != ERROR_SUCCESS )
1168 break;
1169 hr = QUARTZ_RegDeleteKey( hKey, wszPath );
1170 if ( FAILED(hr) )
1171 return hr;
1172 if ( hr != S_OK )
1173 dwIndex ++;
1175 while ( 1 )
1177 cbName = NUMELEMS(wszPath);
1178 lr = RegEnumValueW(
1179 hKey, 0, wszPath, &cbName, 0,
1180 &dwType, NULL, 0 );
1181 if ( lr != ERROR_SUCCESS )
1182 break;
1183 lr = RegDeleteValueW( hKey, wszPath );
1184 if ( lr != ERROR_SUCCESS )
1186 WARN("RegDeleteValueW - %08lx\n",lr);
1187 return E_FAIL;
1191 RegCloseKey( hKey );
1193 lr = RegDeleteKeyW( hkRoot, lpKeyPath );
1194 WARN("RegDeleteKeyW - %08lx\n",lr);
1195 if ( lr != ERROR_SUCCESS && lr != ERROR_FILE_NOT_FOUND )
1196 return S_FALSE;
1197 return S_OK;
1200 static
1201 HRESULT QUARTZ_GetPropertyFromMoniker(
1202 IMoniker* pMoniker, /* [IN] Moniker */
1203 LPCOLESTR lpszPropName, /* [IN] Property */
1204 VARIANT* pVar ) /* [OUT] */
1206 IPropertyBag* pPropBag = NULL;
1207 HRESULT hr;
1209 TRACE("(%p,%s,%p)\n",pMoniker,debugstr_w(lpszPropName),pVar);
1211 hr = IMoniker_BindToStorage(pMoniker,NULL,NULL,&IID_IPropertyBag,(void**)&pPropBag);
1212 if ( FAILED(hr) )
1213 return hr;
1214 hr = IPropertyBag_Read(pPropBag,lpszPropName,pVar,NULL);
1215 IPropertyBag_Release(pPropBag);
1217 return hr;
1220 HRESULT QUARTZ_GetCLSIDFromMoniker(
1221 IMoniker* pMoniker, /* [IN] Moniker */
1222 CLSID* pclsid ) /* [OUT] */
1224 VARIANT var;
1225 HRESULT hr;
1227 var.n1.n2.vt = VT_BSTR;
1228 hr = QUARTZ_GetPropertyFromMoniker(
1229 pMoniker, QUARTZ_wszCLSID, &var );
1230 if ( hr == S_OK )
1232 hr = CLSIDFromString(var.n1.n2.n3.bstrVal,pclsid);
1233 SysFreeString(var.n1.n2.n3.bstrVal);
1236 return hr;
1239 HRESULT QUARTZ_GetMeritFromMoniker(
1240 IMoniker* pMoniker, /* [IN] Moniker */
1241 DWORD* pdwMerit ) /* [OUT] */
1243 VARIANT var;
1244 HRESULT hr;
1246 var.n1.n2.vt = VT_I4;
1247 hr = QUARTZ_GetPropertyFromMoniker(
1248 pMoniker, QUARTZ_wszMerit, &var );
1249 if ( hr == S_OK )
1250 *pdwMerit = var.n1.n2.n3.lVal;
1252 return hr;
1255 HRESULT QUARTZ_GetFilterDataFromMoniker(
1256 IMoniker* pMoniker, /* [IN] Moniker */
1257 BYTE** ppbFilterData, /* [OUT] */
1258 DWORD* pcbFilterData ) /* [OUT] */
1260 VARIANT var;
1261 HRESULT hr;
1262 SAFEARRAY* pArray;
1264 var.n1.n2.vt = VT_ARRAY|VT_UI1;
1265 hr = QUARTZ_GetPropertyFromMoniker(
1266 pMoniker, QUARTZ_wszFilterData, &var );
1267 if ( hr == S_OK )
1269 pArray = var.n1.n2.n3.parray;
1270 hr = SafeArrayLock( pArray );
1271 if ( SUCCEEDED(hr) )
1273 *pcbFilterData = pArray->rgsabound[0].cElements - pArray->rgsabound[0].lLbound;
1274 *ppbFilterData = (BYTE*)QUARTZ_AllocMem( *pcbFilterData );
1275 if ( *ppbFilterData == NULL )
1276 hr = E_OUTOFMEMORY;
1277 else
1278 memcpy( *ppbFilterData, pArray->pvData, *pcbFilterData );
1280 SafeArrayUnlock( pArray );
1282 SafeArrayDestroy( pArray );
1285 return hr;