ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

shlinstobj.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.