ReactOS  0.4.15-dev-313-g8fde48b
shlinstobj.c
Go to the documentation of this file.
1 /*
2  * Shell Instance Objects - Add hot water and stir until dissolved.
3  *
4  * Copyright 2005 Michael Jung
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /* 'Shell Instance Objects' allow you to add a node to the shell namespace
22  * (typically a shortcut to some location in the filesystem), just by setting
23  * some registry entries. This feature was introduced with win2k. Please
24  * search for 'Shell Instance Objects' on MSDN to get more information. */
25 
26 #include <stdarg.h>
27 
28 #define COBJMACROS
29 
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "objbase.h"
34 #include "oleauto.h"
35 
36 #include "shdocvw.h"
37 
38 #include "wine/debug.h"
39 
41 
42 #define CHARS_IN_GUID 39
43 
44 /******************************************************************************
45  * RegistryPropertyBag
46  *
47  * Gives access to a registry key's values via the IPropertyBag interface.
48  */
49 typedef struct _RegistryPropertyBag {
54 
56 {
57  return CONTAINING_RECORD(iface, RegistryPropertyBag, IPropertyBag_iface);
58 }
59 
61  REFIID riid, void **ppv)
62 {
64 
65  TRACE("(iface=%p, riid=%s, ppv=%p)\n", iface, debugstr_guid(riid), ppv);
66 
67  if (!ppv)
68  return E_INVALIDARG;
69 
71  *ppv = &This->IPropertyBag_iface;
72  } else {
73  *ppv = NULL;
74  return E_NOINTERFACE;
75  }
76 
77  IUnknown_AddRef((IUnknown*)*ppv);
78  return S_OK;
79 }
80 
82 {
84  ULONG cRef;
85 
86  TRACE("(iface=%p)\n", iface);
87 
88  cRef = InterlockedIncrement(&This->m_cRef);
89 
90  if (cRef == 1)
92 
93  return cRef;
94 }
95 
97 {
99  ULONG cRef;
100 
101  TRACE("(iface=%p)\n", iface);
102 
103  cRef = InterlockedDecrement(&This->m_cRef);
104 
105  if (cRef == 0) {
106  TRACE("Destroying This=%p)\n", This);
107  RegCloseKey(This->m_hInitPropertyBagKey);
108  heap_free(This);
110  }
111 
112  return cRef;
113 }
114 
116  LPCOLESTR pwszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
117 {
119  WCHAR *pwszValue;
120  DWORD dwType, cbData;
121  LONG res;
122  VARTYPE vtDst = V_VT(pVar);
123  HRESULT hr = S_OK;
124 
125  TRACE("(iface=%p, pwszPropName=%s, pVar=%p, pErrorLog=%p)\n", iface, debugstr_w(pwszPropName),
126  pVar, pErrorLog);
127 
128  res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, NULL, &cbData);
129  if (res != ERROR_SUCCESS)
130  return E_INVALIDARG;
131 
132  pwszValue = heap_alloc(cbData);
133  if (!pwszValue)
134  return E_OUTOFMEMORY;
135 
136  res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType,
137  (LPBYTE)pwszValue, &cbData);
138  if (res != ERROR_SUCCESS) {
139  heap_free(pwszValue);
140  return E_INVALIDARG;
141  }
142 
143  V_VT(pVar) = VT_BSTR;
144  V_BSTR(pVar) = SysAllocString(pwszValue);
145  heap_free(pwszValue);
146 
147  if (vtDst != VT_BSTR) {
148  hr = VariantChangeTypeEx(pVar, pVar, LOCALE_SYSTEM_DEFAULT, 0, vtDst);
149  if (FAILED(hr))
150  SysFreeString(V_BSTR(pVar));
151  }
152 
153  return hr;
154 }
155 
157  LPCOLESTR pwszPropName, VARIANT *pVar)
158 {
159  FIXME("(iface=%p, pwszPropName=%s, pVar=%p) stub\n", iface, debugstr_w(pwszPropName), pVar);
160  return E_NOTIMPL;
161 }
162 
163 static const IPropertyBagVtbl RegistryPropertyBag_IPropertyBagVtbl = {
169 };
170 
172  HRESULT hr = E_FAIL;
173  RegistryPropertyBag *pRegistryPropertyBag;
174 
175  TRACE("(hInitPropertyBagKey=%p, riid=%s, ppvObject=%p)\n", hInitPropertyBagKey,
177 
178  pRegistryPropertyBag = heap_alloc(sizeof(RegistryPropertyBag));
179  if (pRegistryPropertyBag) {
180  pRegistryPropertyBag->IPropertyBag_iface.lpVtbl = &RegistryPropertyBag_IPropertyBagVtbl;
181  pRegistryPropertyBag->m_cRef = 0;
182  pRegistryPropertyBag->m_hInitPropertyBagKey = hInitPropertyBagKey;
183 
184  /* The clasping AddRef/Release is for the case that QueryInterface fails, which will result
185  * in a reference count of 0 in the Release call, which will result in object destruction.*/
186  IPropertyBag_AddRef(&pRegistryPropertyBag->IPropertyBag_iface);
187  hr = IPropertyBag_QueryInterface(&pRegistryPropertyBag->IPropertyBag_iface, riid, ppvObject);
188  IPropertyBag_Release(&pRegistryPropertyBag->IPropertyBag_iface);
189  }
190 
191  return hr;
192 }
193 
194 /******************************************************************************
195  * InstanceObjectFactory
196  * Builds Instance Objects and asks them to initialize themselves based on the
197  * values of a PropertyBag.
198  */
199 typedef struct _InstanceObjectFactory {
202  CLSID m_clsidInstance; /* CLSID of the objects to create. */
203  IPropertyBag *m_pPropertyBag; /* PropertyBag to initialize those objects. */
205 
207 {
208  return CONTAINING_RECORD(iface, InstanceObjectFactory, IClassFactory_iface);
209 }
210 
212  REFIID riid, void **ppv)
213 {
215 
216  TRACE("iface=%p, riid=%s, ppv=%p)\n", iface, debugstr_guid(riid), ppv);
217 
218  if (!ppv)
219  return E_INVALIDARG;
220 
222  *ppv = &This->IClassFactory_iface;
223  } else {
224  *ppv = NULL;
225  return E_NOINTERFACE;
226  }
227 
228  IUnknown_AddRef((IUnknown*)*ppv);
229  return S_OK;
230 }
231 
233 {
235  ULONG cRef;
236 
237  TRACE("(iface=%p)\n", iface);
238 
239  cRef = InterlockedIncrement(&This->m_cRef);
240 
241  if (cRef == 1)
242  IClassFactory_LockServer(iface, TRUE);
243 
244  return cRef;
245 }
246 
248 {
250  ULONG cRef;
251 
252  TRACE("(iface=%p)\n", iface);
253 
254  cRef = InterlockedDecrement(&This->m_cRef);
255 
256  if (cRef == 0) {
257  IClassFactory_LockServer(iface, FALSE);
258  IPropertyBag_Release(This->m_pPropertyBag);
259  heap_free(This);
260  }
261 
262  return cRef;
263 }
264 
266  IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObj)
267 {
269  IPersistPropertyBag *pPersistPropertyBag;
270  HRESULT hr;
271 
272  TRACE("(pUnkOuter=%p, riid=%s, ppvObj=%p)\n", pUnkOuter, debugstr_guid(riid), ppvObj);
273 
274  hr = CoCreateInstance(&This->m_clsidInstance, NULL, CLSCTX_INPROC_SERVER,
275  &IID_IPersistPropertyBag, (LPVOID*)&pPersistPropertyBag);
276  if (FAILED(hr)) {
277  TRACE("Failed to create instance of %s. hr = %08x\n",
278  debugstr_guid(&This->m_clsidInstance), hr);
279  return hr;
280  }
281 
282  hr = IPersistPropertyBag_Load(pPersistPropertyBag, This->m_pPropertyBag, NULL);
283  if (FAILED(hr)) {
284  TRACE("Failed to initialize object from PropertyBag: hr = %08x\n", hr);
285  IPersistPropertyBag_Release(pPersistPropertyBag);
286  return hr;
287  }
288 
289  hr = IPersistPropertyBag_QueryInterface(pPersistPropertyBag, riid, ppvObj);
290  IPersistPropertyBag_Release(pPersistPropertyBag);
291 
292  return hr;
293 }
294 
296  BOOL fLock)
297 {
298  TRACE("(iface=%p, fLock=%d) stub\n", iface, fLock);
299 
300  if (fLock)
302  else
304 
305  return S_OK;
306 }
307 
308 static const IClassFactoryVtbl InstanceObjectFactory_IClassFactoryVtbl = {
314 };
315 
318 {
319  InstanceObjectFactory *pInstanceObjectFactory;
320  HRESULT hr = E_FAIL;
321 
322  TRACE("(RegistryPropertyBag=%p, riid=%s, ppvObject=%p)\n", pPropertyBag,
324 
325  pInstanceObjectFactory = heap_alloc(sizeof(InstanceObjectFactory));
326  if (pInstanceObjectFactory) {
327  pInstanceObjectFactory->IClassFactory_iface.lpVtbl = &InstanceObjectFactory_IClassFactoryVtbl;
328  pInstanceObjectFactory->m_cRef = 0;
329  pInstanceObjectFactory->m_clsidInstance = *rclsid;
330  pInstanceObjectFactory->m_pPropertyBag = pPropertyBag;
331  IPropertyBag_AddRef(pPropertyBag);
332 
333  IClassFactory_AddRef(&pInstanceObjectFactory->IClassFactory_iface);
334  hr = IClassFactory_QueryInterface(&pInstanceObjectFactory->IClassFactory_iface,
335  riid, ppvObject);
336  IClassFactory_Release(&pInstanceObjectFactory->IClassFactory_iface);
337  }
338 
339  return hr;
340 }
341 
342 /******************************************************************************
343  * SHDOCVW_GetShellInstanceObjectClassObject [Internal]
344  *
345  * Figure if there is a 'Shell Instance Object' conformant registry entry for
346  * the given CLSID and if so create and return a corresponding ClassObject.
347  *
348  * PARAMS
349  * rclsid [I] CLSID of the 'Shell Instance Object'.
350  * riid [I] Desired interface. Only IClassFactory supported.
351  * ppvClassObj [O] The corresponding ClassObject.
352  *
353  * RETURNS
354  * Success: S_OK,
355  * Failure: CLASS_E_CLASSNOTAVAILABLE
356  */
358  LPVOID *ppvClassObj)
359 {
360  WCHAR wszInstanceKey[] = { 'C','L','S','I','D','\\','{','0','0','0','0','0','0','0','0','-',
361  '0','0','0','0','-','0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0',
362  '0','0','0','0','}','\\','I','n','s','t','a','n','c','e', 0 };
363  static const WCHAR wszCLSID[] = { 'C','L','S','I','D',0 };
364  static const WCHAR wszInitPropertyBag[] =
365  { 'I','n','i','t','P','r','o','p','e','r','t','y','B','a','g',0 };
366  WCHAR wszCLSIDInstance[CHARS_IN_GUID];
367  CLSID clsidInstance;
368  HKEY hInstanceKey, hInitPropertyBagKey;
369  DWORD dwType, cbBytes = sizeof(wszCLSIDInstance);
370  IPropertyBag *pInitPropertyBag;
371  HRESULT hr;
372  LONG res;
373 
374  TRACE("(rclsid=%s, riid=%s, ppvClassObject=%p)\n", debugstr_guid(rclsid), debugstr_guid(riid),
375  ppvClassObj);
376 
377  /* Figure if there is an 'Instance' subkey for the given CLSID and acquire a handle. */
378  if (!StringFromGUID2(rclsid, wszInstanceKey + 6, CHARS_IN_GUID))
380  wszInstanceKey[5+CHARS_IN_GUID] = '\\'; /* Repair the null-termination. */
381  if (ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT, wszInstanceKey, 0, KEY_READ, &hInstanceKey))
382  /* If there is no 'Instance' subkey, then it's not a Shell Instance Object. */
384 
385  if (ERROR_SUCCESS != RegQueryValueExW(hInstanceKey, wszCLSID, NULL, &dwType, (LPBYTE)wszCLSIDInstance, &cbBytes) ||
386  FAILED(CLSIDFromString(wszCLSIDInstance, &clsidInstance)))
387  {
388  /* 'Instance' should have a 'CLSID' value with a well-formed clsid-string. */
389  FIXME("Failed to infer instance CLSID! %s\n", debugstr_w(wszCLSIDInstance));
390  RegCloseKey(hInstanceKey);
392  }
393 
394  /* Try to open the 'InitPropertyBag' subkey. */
395  res = RegOpenKeyExW(hInstanceKey, wszInitPropertyBag, 0, KEY_READ, &hInitPropertyBagKey);
396  RegCloseKey(hInstanceKey);
397  if (res != ERROR_SUCCESS) {
398  /* Besides 'InitPropertyBag's, shell instance objects might be initialized by streams.
399  * So this case might not be an error. */
400  TRACE("No InitPropertyBag key found!\n");
402  }
403 
404  /* If the construction succeeds, the new RegistryPropertyBag is responsible for closing
405  * hInitPropertyBagKey. */
406  hr = RegistryPropertyBag_Constructor(hInitPropertyBagKey, &IID_IPropertyBag,
407  (LPVOID*)&pInitPropertyBag);
408  if (FAILED(hr)) {
409  RegCloseKey(hInitPropertyBagKey);
410  return hr;
411  }
412 
413  /* Construct an Instance Object Factory, which creates objects of class 'clsidInstance'
414  * and asks them to initialize themselves with the help of the 'pInitiPropertyBag' */
415  hr = InstanceObjectFactory_Constructor(&clsidInstance, pInitPropertyBag, riid, ppvClassObj);
416  IPropertyBag_Release(pInitPropertyBag); /* The factory will hold a reference the bag. */
417 
418  return hr;
419 }
static ULONG WINAPI RegistryPropertyBag_IPropertyBag_Release(IPropertyBag *iface)
Definition: shlinstobj.c:96
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
#define ERROR_SUCCESS
Definition: deptool.c:10
HRESULT hr
Definition: shlfolder.c:183
struct _RegistryPropertyBag RegistryPropertyBag
#define KEY_READ
Definition: nt_native.h:1023
REFIID riid
Definition: precomp.h:44
#define REFCLSID
Definition: guiddef.h:117
static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
Definition: shlinstobj.c:60
REFIID LPVOID * ppv
Definition: atlbase.h:39
WINE_DEFAULT_DEBUG_CHANNEL(shdocvw)
static HRESULT InstanceObjectFactory_Constructor(REFCLSID rclsid, IPropertyBag *pPropertyBag, REFIID riid, LPVOID *ppvObject)
Definition: shlinstobj.c:316
IClassFactory IClassFactory_iface
Definition: shlinstobj.c:200
#define E_FAIL
Definition: ddrawi.h:102
#define CLASS_E_CLASSNOTAVAILABLE
Definition: winerror.h:2663
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
const GUID IID_IPersistPropertyBag
Definition: proxy.cpp:11
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
const GUID IID_IPropertyBag
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Write(IPropertyBag *iface, LPCOLESTR pwszPropName, VARIANT *pVar)
Definition: shlinstobj.c:156
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static ULONG WINAPI InstanceObjectFactory_IClassFactory_Release(IClassFactory *iface)
Definition: shlinstobj.c:247
struct _InstanceObjectFactory InstanceObjectFactory
#define TRACE(s)
Definition: solgame.cpp:4
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
static HRESULT WINAPI InstanceObjectFactory_IClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObj)
Definition: shlinstobj.c:265
__wchar_t WCHAR
Definition: xmlstorage.h:180
static HRESULT RegistryPropertyBag_Constructor(HKEY hInitPropertyBagKey, REFIID riid, LPVOID *ppvObject)
Definition: shlinstobj.c:171
LONG HRESULT
Definition: typedefs.h:78
const GUID IID_IUnknown
HRESULT SHDOCVW_GetShellInstanceObjectClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvClassObj)
Definition: shlinstobj.c:357
#define WINAPI
Definition: msvc.h:6
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
#define LOCALE_SYSTEM_DEFAULT
unsigned long DWORD
Definition: ntddk_ex.h:95
#define CHARS_IN_GUID
Definition: shlinstobj.c:42
static const IPropertyBagVtbl RegistryPropertyBag_IPropertyBagVtbl
Definition: shlinstobj.c:163
static ULONG WINAPI RegistryPropertyBag_IPropertyBag_AddRef(IPropertyBag *iface)
Definition: shlinstobj.c:81
#define InterlockedDecrement
Definition: armddk.h:52
static HRESULT WINAPI InstanceObjectFactory_IClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
Definition: shlinstobj.c:211
#define V_VT(A)
Definition: oleauto.h:211
REFIID LPVOID * ppvObject
Definition: precomp.h:44
#define V_BSTR(A)
Definition: oleauto.h:226
IPropertyBag IPropertyBag_iface
Definition: shlinstobj.c:50
static ULONG WINAPI InstanceObjectFactory_IClassFactory_AddRef(IClassFactory *iface)
Definition: shlinstobj.c:232
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
static InstanceObjectFactory * impl_from_IClassFactory(IClassFactory *iface)
Definition: shlinstobj.c:206
static void SHDOCVW_LockModule(void)
Definition: shdocvw.h:50
#define S_OK
Definition: intsafe.h:59
#define InterlockedIncrement
Definition: armddk.h:53
static const IClassFactoryVtbl InstanceObjectFactory_IClassFactoryVtbl
Definition: shlinstobj.c:308
#define E_NOTIMPL
Definition: ddrawi.h:99
static HRESULT WINAPI InstanceObjectFactory_IClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
Definition: shlinstobj.c:295
unsigned short VARTYPE
Definition: compat.h:1904
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
static void SHDOCVW_UnlockModule(void)
Definition: shdocvw.h:51
static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPCOLESTR pwszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
Definition: shlinstobj.c:115
GLuint res
Definition: glext.h:9613
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
unsigned int ULONG
Definition: retypes.h:1
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
IPropertyBag * m_pPropertyBag
Definition: shlinstobj.c:203
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
const GUID IID_IClassFactory
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static RegistryPropertyBag * impl_from_IPropertyBag(IPropertyBag *iface)
Definition: shlinstobj.c:55
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:988
static BOOL heap_free(void *mem)
Definition: appwiz.h:75