Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenshlinstobj.c
Go to the documentation of this file.
00001 /* 00002 * Shell Instance Objects - Add hot water and stir until dissolved. 00003 * 00004 * Copyright 2005 Michael Jung 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 /* 'Shell Instance Objects' allow you to add a node to the shell namespace 00022 * (typically a shortcut to some location in the filesystem), just by setting 00023 * some registry entries. This feature was introduced with win2k. Please 00024 * search for 'Shell Instance Objects' on MSDN to get more information. */ 00025 00026 #include <stdarg.h> 00027 00028 #define COBJMACROS 00029 00030 #include "windef.h" 00031 #include "winbase.h" 00032 #include "winreg.h" 00033 #include "objbase.h" 00034 #include "oleauto.h" 00035 00036 #include "shdocvw.h" 00037 00038 #include "wine/unicode.h" 00039 #include "wine/debug.h" 00040 00041 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); 00042 00043 #define ADJUST_THIS(c,m,p) ((c*)(((long)p)-(long)&(((c*)0)->lp##m##Vtbl))) 00044 #define STATIC_CAST(i,p) ((i*)&p->lp##i##Vtbl) 00045 #define CHARS_IN_GUID 39 00046 00047 /****************************************************************************** 00048 * RegistryPropertyBag 00049 * 00050 * Gives access to a registry key's values via the IPropertyBag interface. 00051 */ 00052 typedef struct _RegistryPropertyBag { 00053 const IPropertyBagVtbl *lpIPropertyBagVtbl; 00054 LONG m_cRef; 00055 HKEY m_hInitPropertyBagKey; 00056 } RegistryPropertyBag; 00057 00058 static void RegistryPropertyBag_Destroy(RegistryPropertyBag *This) { 00059 TRACE("This=%p)\n", This); 00060 00061 RegCloseKey(This->m_hInitPropertyBagKey); 00062 heap_free(This); 00063 } 00064 00065 static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_QueryInterface(IPropertyBag *iface, 00066 REFIID riid, void **ppv) 00067 { 00068 RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface); 00069 00070 TRACE("(iface=%p, riid=%s, ppv=%p)\n", iface, debugstr_guid(riid), ppv); 00071 00072 if (!ppv) 00073 return E_INVALIDARG; 00074 00075 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPropertyBag, riid)) { 00076 *ppv = STATIC_CAST(IPropertyBag, This); 00077 } else { 00078 *ppv = NULL; 00079 return E_NOINTERFACE; 00080 } 00081 00082 IUnknown_AddRef((IUnknown*)*ppv); 00083 return S_OK; 00084 } 00085 00086 static ULONG WINAPI RegistryPropertyBag_IPropertyBag_AddRef(IPropertyBag *iface) { 00087 RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface); 00088 ULONG cRef; 00089 00090 TRACE("(iface=%p)\n", iface); 00091 00092 cRef = InterlockedIncrement(&This->m_cRef); 00093 00094 if (cRef == 1) 00095 SHDOCVW_LockModule(); 00096 00097 return cRef; 00098 } 00099 00100 static ULONG WINAPI RegistryPropertyBag_IPropertyBag_Release(IPropertyBag *iface) { 00101 RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface); 00102 ULONG cRef; 00103 00104 TRACE("(iface=%p)\n", iface); 00105 00106 cRef = InterlockedDecrement(&This->m_cRef); 00107 00108 if (cRef == 0) { 00109 RegistryPropertyBag_Destroy(This); 00110 SHDOCVW_UnlockModule(); 00111 } 00112 00113 return cRef; 00114 } 00115 00116 static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Read(IPropertyBag *iface, 00117 LPCOLESTR pwszPropName, VARIANT *pVar, IErrorLog *pErrorLog) 00118 { 00119 RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface); 00120 WCHAR *pwszValue; 00121 DWORD dwType, cbData; 00122 LONG res; 00123 VARTYPE vtDst = V_VT(pVar); 00124 HRESULT hr = S_OK; 00125 00126 TRACE("(iface=%p, pwszPropName=%s, pVar=%p, pErrorLog=%p)\n", iface, debugstr_w(pwszPropName), 00127 pVar, pErrorLog); 00128 00129 res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, NULL, &cbData); 00130 if (res != ERROR_SUCCESS) 00131 return E_INVALIDARG; 00132 00133 pwszValue = heap_alloc(cbData); 00134 if (!pwszValue) 00135 return E_OUTOFMEMORY; 00136 00137 res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, 00138 (LPBYTE)pwszValue, &cbData); 00139 if (res != ERROR_SUCCESS) { 00140 heap_free(pwszValue); 00141 return E_INVALIDARG; 00142 } 00143 00144 V_VT(pVar) = VT_BSTR; 00145 V_BSTR(pVar) = SysAllocString(pwszValue); 00146 heap_free(pwszValue); 00147 00148 if (vtDst != VT_BSTR) { 00149 hr = VariantChangeTypeEx(pVar, pVar, LOCALE_SYSTEM_DEFAULT, 0, vtDst); 00150 if (FAILED(hr)) 00151 SysFreeString(V_BSTR(pVar)); 00152 } 00153 00154 return hr; 00155 } 00156 00157 static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Write(IPropertyBag *iface, 00158 LPCOLESTR pwszPropName, VARIANT *pVar) 00159 { 00160 FIXME("(iface=%p, pwszPropName=%s, pVar=%p) stub\n", iface, debugstr_w(pwszPropName), pVar); 00161 return E_NOTIMPL; 00162 } 00163 00164 static const IPropertyBagVtbl RegistryPropertyBag_IPropertyBagVtbl = { 00165 RegistryPropertyBag_IPropertyBag_QueryInterface, 00166 RegistryPropertyBag_IPropertyBag_AddRef, 00167 RegistryPropertyBag_IPropertyBag_Release, 00168 RegistryPropertyBag_IPropertyBag_Read, 00169 RegistryPropertyBag_IPropertyBag_Write 00170 }; 00171 00172 static HRESULT RegistryPropertyBag_Constructor(HKEY hInitPropertyBagKey, REFIID riid, LPVOID *ppvObject) { 00173 HRESULT hr = E_FAIL; 00174 RegistryPropertyBag *pRegistryPropertyBag; 00175 00176 TRACE("(hInitPropertyBagKey=%p, riid=%s, ppvObject=%p)\n", hInitPropertyBagKey, 00177 debugstr_guid(riid), ppvObject); 00178 00179 pRegistryPropertyBag = heap_alloc(sizeof(RegistryPropertyBag)); 00180 if (pRegistryPropertyBag) { 00181 pRegistryPropertyBag->lpIPropertyBagVtbl = &RegistryPropertyBag_IPropertyBagVtbl; 00182 pRegistryPropertyBag->m_cRef = 0; 00183 pRegistryPropertyBag->m_hInitPropertyBagKey = hInitPropertyBagKey; 00184 00185 /* The clasping AddRef/Release is for the case that QueryInterface fails, which will result 00186 * in a reference count of 0 in the Release call, which will result in object destruction.*/ 00187 IPropertyBag_AddRef(STATIC_CAST(IPropertyBag, pRegistryPropertyBag)); 00188 hr = IPropertyBag_QueryInterface(STATIC_CAST(IPropertyBag, pRegistryPropertyBag), riid, ppvObject); 00189 IPropertyBag_Release(STATIC_CAST(IPropertyBag, pRegistryPropertyBag)); 00190 } 00191 00192 return hr; 00193 } 00194 00195 /****************************************************************************** 00196 * InstanceObjectFactory 00197 * Builds Instance Objects and asks them to initialize themselves based on the 00198 * values of a PropertyBag. 00199 */ 00200 typedef struct _InstanceObjectFactory { 00201 const IClassFactoryVtbl *lpIClassFactoryVtbl; 00202 LONG m_cRef; 00203 CLSID m_clsidInstance; /* CLSID of the objects to create. */ 00204 IPropertyBag *m_pPropertyBag; /* PropertyBag to initialize those objects. */ 00205 } InstanceObjectFactory; 00206 00207 static void InstanceObjectFactory_Destroy(InstanceObjectFactory *This) { 00208 IPropertyBag_Release(This->m_pPropertyBag); 00209 heap_free(This); 00210 } 00211 00212 static HRESULT WINAPI InstanceObjectFactory_IClassFactory_QueryInterface(IClassFactory *iface, 00213 REFIID riid, LPVOID* ppv) 00214 { 00215 InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface); 00216 00217 TRACE("iface=%p, riid=%s, ppv=%p)\n", iface, debugstr_guid(riid), ppv); 00218 00219 if (!ppv) 00220 return E_INVALIDARG; 00221 00222 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IClassFactory, riid)) { 00223 *ppv = STATIC_CAST(IClassFactory, This); 00224 } else { 00225 *ppv = NULL; 00226 return E_NOINTERFACE; 00227 } 00228 00229 IUnknown_AddRef((IUnknown*)*ppv); 00230 return S_OK; 00231 } 00232 00233 static ULONG WINAPI InstanceObjectFactory_IClassFactory_AddRef(IClassFactory *iface) 00234 { 00235 InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface); 00236 ULONG cRef; 00237 00238 TRACE("(iface=%p)\n", iface); 00239 00240 cRef = InterlockedIncrement(&This->m_cRef); 00241 00242 if (cRef == 1) 00243 IClassFactory_LockServer(iface, TRUE); 00244 00245 return cRef; 00246 } 00247 00248 static ULONG WINAPI InstanceObjectFactory_IClassFactory_Release(IClassFactory *iface) 00249 { 00250 InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface); 00251 ULONG cRef; 00252 00253 TRACE("(iface=%p)\n", iface); 00254 00255 cRef = InterlockedDecrement(&This->m_cRef); 00256 00257 if (cRef == 0) { 00258 IClassFactory_LockServer(iface, FALSE); 00259 InstanceObjectFactory_Destroy(This); 00260 } 00261 00262 return cRef; 00263 } 00264 00265 static HRESULT WINAPI InstanceObjectFactory_IClassFactory_CreateInstance(IClassFactory *iface, 00266 IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObj) 00267 { 00268 InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface); 00269 IPersistPropertyBag *pPersistPropertyBag; 00270 HRESULT hr; 00271 00272 TRACE("(pUnkOuter=%p, riid=%s, ppvObj=%p)\n", pUnkOuter, debugstr_guid(riid), ppvObj); 00273 00274 hr = CoCreateInstance(&This->m_clsidInstance, NULL, CLSCTX_INPROC_SERVER, 00275 &IID_IPersistPropertyBag, (LPVOID*)&pPersistPropertyBag); 00276 if (FAILED(hr)) { 00277 TRACE("Failed to create instance of %s. hr = %08x\n", 00278 debugstr_guid(&This->m_clsidInstance), hr); 00279 return hr; 00280 } 00281 00282 hr = IPersistPropertyBag_Load(pPersistPropertyBag, This->m_pPropertyBag, NULL); 00283 if (FAILED(hr)) { 00284 TRACE("Failed to initialize object from ProperyBag: hr = %08x\n", hr); 00285 IPersistPropertyBag_Release(pPersistPropertyBag); 00286 return hr; 00287 } 00288 00289 hr = IPersistPropertyBag_QueryInterface(pPersistPropertyBag, riid, ppvObj); 00290 IPersistPropertyBag_Release(pPersistPropertyBag); 00291 00292 return hr; 00293 } 00294 00295 static HRESULT WINAPI InstanceObjectFactory_IClassFactory_LockServer(IClassFactory *iface, 00296 BOOL fLock) 00297 { 00298 TRACE("(iface=%p, fLock=%d) stub\n", iface, fLock); 00299 00300 if (fLock) 00301 SHDOCVW_LockModule(); 00302 else 00303 SHDOCVW_UnlockModule(); 00304 00305 return S_OK; 00306 } 00307 00308 static const IClassFactoryVtbl InstanceObjectFactory_IClassFactoryVtbl = { 00309 InstanceObjectFactory_IClassFactory_QueryInterface, 00310 InstanceObjectFactory_IClassFactory_AddRef, 00311 InstanceObjectFactory_IClassFactory_Release, 00312 InstanceObjectFactory_IClassFactory_CreateInstance, 00313 InstanceObjectFactory_IClassFactory_LockServer 00314 }; 00315 00316 static HRESULT InstanceObjectFactory_Constructor(REFCLSID rclsid, IPropertyBag *pPropertyBag, 00317 REFIID riid, LPVOID *ppvObject) 00318 { 00319 InstanceObjectFactory *pInstanceObjectFactory; 00320 HRESULT hr = E_FAIL; 00321 00322 TRACE("(RegistryPropertyBag=%p, riid=%s, ppvObject=%p)\n", pPropertyBag, 00323 debugstr_guid(riid), ppvObject); 00324 00325 pInstanceObjectFactory = heap_alloc(sizeof(InstanceObjectFactory)); 00326 if (pInstanceObjectFactory) { 00327 pInstanceObjectFactory->lpIClassFactoryVtbl = &InstanceObjectFactory_IClassFactoryVtbl; 00328 pInstanceObjectFactory->m_cRef = 0; 00329 pInstanceObjectFactory->m_clsidInstance = *rclsid; 00330 pInstanceObjectFactory->m_pPropertyBag = pPropertyBag; 00331 IPropertyBag_AddRef(pPropertyBag); 00332 00333 IClassFactory_AddRef(STATIC_CAST(IClassFactory, pInstanceObjectFactory)); 00334 hr = IClassFactory_QueryInterface(STATIC_CAST(IClassFactory, pInstanceObjectFactory), 00335 riid, ppvObject); 00336 IClassFactory_Release(STATIC_CAST(IClassFactory, pInstanceObjectFactory)); 00337 } 00338 00339 return hr; 00340 } 00341 00342 /****************************************************************************** 00343 * SHDOCVW_GetShellInstanceObjectClassObject [Internal] 00344 * 00345 * Figure if there is a 'Shell Instance Object' conformant registry entry for 00346 * the given CLSID and if so create and return a corresponding ClassObject. 00347 * 00348 * PARAMS 00349 * rclsid [I] CLSID of the 'Shell Instance Object'. 00350 * riid [I] Desired interface. Only IClassFactory supported. 00351 * ppvClassObj [O] The corresponding ClassObject. 00352 * 00353 * RETURNS 00354 * Success: S_OK, 00355 * Failure: CLASS_E_CLASSNOTAVAILABLE 00356 */ 00357 HRESULT SHDOCVW_GetShellInstanceObjectClassObject(REFCLSID rclsid, REFIID riid, 00358 LPVOID *ppvClassObj) 00359 { 00360 WCHAR wszInstanceKey[] = { 'C','L','S','I','D','\\','{','0','0','0','0','0','0','0','0','-', 00361 '0','0','0','0','-','0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0', 00362 '0','0','0','0','}','\\','I','n','s','t','a','n','c','e', 0 }; 00363 const WCHAR wszCLSID[] = { 'C','L','S','I','D',0 }; 00364 const WCHAR wszInitPropertyBag[] = 00365 { 'I','n','i','t','P','r','o','p','e','r','t','y','B','a','g',0 }; 00366 WCHAR wszCLSIDInstance[CHARS_IN_GUID]; 00367 CLSID clsidInstance; 00368 HKEY hInstanceKey, hInitPropertyBagKey; 00369 DWORD dwType, cbBytes = sizeof(wszCLSIDInstance); 00370 IPropertyBag *pInitPropertyBag; 00371 HRESULT hr; 00372 LONG res; 00373 00374 TRACE("(rclsid=%s, riid=%s, ppvClassObject=%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), 00375 ppvClassObj); 00376 00377 /* Figure if there is an 'Instance' subkey for the given CLSID and acquire a handle. */ 00378 if (!StringFromGUID2(rclsid, wszInstanceKey + 6, CHARS_IN_GUID) || 00379 !(wszInstanceKey[5+CHARS_IN_GUID]='\\') || /* Repair the null-termination. */ 00380 ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT, wszInstanceKey, 0, KEY_READ, &hInstanceKey)) 00381 { 00382 /* If there is no 'Instance' subkey, then it's not a Shell Instance Object. */ 00383 return CLASS_E_CLASSNOTAVAILABLE; 00384 } 00385 00386 if (RegQueryValueExW(hInstanceKey, wszCLSID, NULL, &dwType, (LPBYTE)wszCLSIDInstance, &cbBytes) 00387 != ERROR_SUCCESS || FAILED(CLSIDFromString(wszCLSIDInstance, &clsidInstance))) 00388 { 00389 /* 'Instance' should have a 'CLSID' value with a well-formed clsid-string. */ 00390 FIXME("Failed to infer instance CLSID! %s\n", debugstr_w(wszCLSIDInstance)); 00391 RegCloseKey(hInstanceKey); 00392 return CLASS_E_CLASSNOTAVAILABLE; 00393 } 00394 00395 /* Try to open the 'InitPropertyBag' subkey. */ 00396 res = RegOpenKeyExW(hInstanceKey, wszInitPropertyBag, 0, KEY_READ, &hInitPropertyBagKey); 00397 RegCloseKey(hInstanceKey); 00398 if (res != ERROR_SUCCESS) { 00399 /* Besides 'InitPropertyBag's, shell instance objects might be initialized by streams. 00400 * So this case might not be an error. */ 00401 TRACE("No InitPropertyBag key found!\n"); 00402 return CLASS_E_CLASSNOTAVAILABLE; 00403 } 00404 00405 /* If the construction succeeds, the new RegistryPropertyBag is responsible for closing 00406 * hInitProperyBagKey. */ 00407 hr = RegistryPropertyBag_Constructor(hInitPropertyBagKey, &IID_IPropertyBag, 00408 (LPVOID*)&pInitPropertyBag); 00409 if (FAILED(hr)) { 00410 RegCloseKey(hInitPropertyBagKey); 00411 return hr; 00412 } 00413 00414 /* Construct an Instance Object Factory, which creates objects of class 'clsidInstance' 00415 * and asks them to initialize themselves with the help of the 'pInitiPropertyBag' */ 00416 hr = InstanceObjectFactory_Constructor(&clsidInstance, pInitPropertyBag, riid, ppvClassObj); 00417 IPropertyBag_Release(pInitPropertyBag); /* The factory will hold a reference the bag. */ 00418 00419 return hr; 00420 } Generated on Sat May 26 2012 04:24:52 for ReactOS by
1.7.6.1
|