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

moniker.c
Go to the documentation of this file.
00001 /*
00002  *  Monikers
00003  *
00004  *  Copyright 1998  Marcus Meissner
00005  *      Copyright 1999  Noomen Hamza
00006  *      Copyright 2005  Robert Shearman (for CodeWeavers)
00007  *      Copyright 2007  Robert Shearman
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include "config.h"
00025 #include "wine/port.h"
00026 
00027 #include <stdarg.h>
00028 #include <string.h>
00029 
00030 #define COBJMACROS
00031 
00032 #include "winerror.h"
00033 #include "windef.h"
00034 #include "winbase.h"
00035 #include "winuser.h"
00036 #include "wtypes.h"
00037 #include "ole2.h"
00038 
00039 #include "wine/list.h"
00040 #include "wine/debug.h"
00041 #include "wine/unicode.h"
00042 #include "wine/exception.h"
00043 
00044 #include "compobj_private.h"
00045 #include "moniker.h"
00046 #include "irot.h"
00047 
00048 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00049 
00050 /* see MSDN docs for IROTData::GetComparisonData, which states what this
00051  * constant is
00052  */
00053 #define MAX_COMPARISON_DATA 2048
00054 
00055 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
00056 {
00057     return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
00058 }
00059 
00060 /* define the structure of the running object table elements */
00061 struct rot_entry
00062 {
00063     struct list        entry;
00064     InterfaceData* object; /* marshaled running object*/
00065     MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */
00066     DWORD              cookie; /* cookie identifying this object */
00067     FILETIME           last_modified;
00068     IrotContextHandle  ctxt_handle;
00069 };
00070 
00071 /* define the RunningObjectTableImpl structure */
00072 typedef struct RunningObjectTableImpl
00073 {
00074     IRunningObjectTable IRunningObjectTable_iface;
00075     LONG ref;
00076 
00077     struct list rot; /* list of ROT entries */
00078     CRITICAL_SECTION lock;
00079 } RunningObjectTableImpl;
00080 
00081 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
00082 static IrotHandle irot_handle;
00083 
00084 /* define the EnumMonikerImpl structure */
00085 typedef struct EnumMonikerImpl
00086 {
00087     IEnumMoniker IEnumMoniker_iface;
00088     LONG ref;
00089 
00090     InterfaceList *moniker_list;
00091     ULONG pos;
00092 } EnumMonikerImpl;
00093 
00094 static inline RunningObjectTableImpl *impl_from_IRunningObjectTable(IRunningObjectTable *iface)
00095 {
00096     return CONTAINING_RECORD(iface, RunningObjectTableImpl, IRunningObjectTable_iface);
00097 }
00098 
00099 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
00100 {
00101     return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
00102 }
00103 
00104 /* IEnumMoniker Local functions*/
00105 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
00106     ULONG pos, IEnumMoniker **ppenumMoniker);
00107 
00108 static IrotHandle get_irot_handle(void)
00109 {
00110     if (!irot_handle)
00111     {
00112         RPC_STATUS status;
00113         RPC_WSTR binding;
00114         IrotHandle new_handle;
00115         unsigned short ncacn_np[] = IROT_PROTSEQ;
00116         unsigned short endpoint[] = IROT_ENDPOINT;
00117         status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding);
00118         if (status == RPC_S_OK)
00119         {
00120             status = RpcBindingFromStringBindingW(binding, &new_handle);
00121             RpcStringFreeW(&binding);
00122         }
00123         if (status != RPC_S_OK)
00124             return NULL;
00125         if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL))
00126             /* another thread beat us to it */
00127             RpcBindingFree(&new_handle);
00128     }
00129     return irot_handle;
00130 }
00131 
00132 static BOOL start_rpcss(void)
00133 {
00134     PROCESS_INFORMATION pi;
00135     STARTUPINFOW si;
00136     WCHAR cmd[MAX_PATH];
00137     static const WCHAR rpcss[] = {'\\','r','p','c','s','s','.','e','x','e',0};
00138     BOOL rslt;
00139     void *redir;
00140 
00141     TRACE("\n");
00142 
00143     ZeroMemory(&si, sizeof(STARTUPINFOA));
00144     si.cb = sizeof(STARTUPINFOA);
00145     GetSystemDirectoryW( cmd, MAX_PATH - sizeof(rpcss)/sizeof(WCHAR) );
00146     strcatW( cmd, rpcss );
00147 
00148     Wow64DisableWow64FsRedirection( &redir );
00149     rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
00150     Wow64RevertWow64FsRedirection( redir );
00151 
00152     if (rslt)
00153     {
00154         CloseHandle(pi.hProcess);
00155         CloseHandle(pi.hThread);
00156         Sleep(100);
00157     }
00158 
00159     return rslt;
00160 }
00161 
00162 static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
00163 {
00164     HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
00165     void *pv = GlobalLock(hglobal);
00166     memcpy(pv, mip->abData, mip->ulCntData);
00167     GlobalUnlock(hglobal);
00168     return CreateStreamOnHGlobal(hglobal, TRUE, stream);
00169 }
00170 
00171 static void rot_entry_delete(struct rot_entry *rot_entry)
00172 {
00173     if (rot_entry->cookie)
00174     {
00175         InterfaceData *object = NULL;
00176         InterfaceData *moniker = NULL;
00177         __TRY
00178         {
00179             IrotRevoke(get_irot_handle(), rot_entry->cookie,
00180                        &rot_entry->ctxt_handle, &object, &moniker);
00181         }
00182         __EXCEPT(rpc_filter)
00183         {
00184         }
00185         __ENDTRY
00186         MIDL_user_free(object);
00187         if (moniker)
00188         {
00189             IStream *stream;
00190             HRESULT hr;
00191             hr = create_stream_on_mip_ro(moniker, &stream);
00192             if (hr == S_OK)
00193             {
00194                 CoReleaseMarshalData(stream);
00195                 IUnknown_Release(stream);
00196             }
00197         }
00198         MIDL_user_free(moniker);
00199     }
00200     if (rot_entry->object)
00201     {
00202         IStream *stream;
00203         HRESULT hr;
00204         hr = create_stream_on_mip_ro(rot_entry->object, &stream);
00205         if (hr == S_OK)
00206         {
00207             CoReleaseMarshalData(stream);
00208             IUnknown_Release(stream);
00209         }
00210     }
00211     HeapFree(GetProcessHeap(), 0, rot_entry->object);
00212     HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
00213     HeapFree(GetProcessHeap(), 0, rot_entry);
00214 }
00215 
00216 /* moniker_data must be freed with HeapFree when no longer in use */
00217 static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data)
00218 {
00219     HRESULT hr;
00220     IROTData *pROTData = NULL;
00221     hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData);
00222     if (SUCCEEDED(hr))
00223     {
00224         ULONG size = MAX_COMPARISON_DATA;
00225         *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size]));
00226         if (!*moniker_data)
00227         {
00228             IROTData_Release(pROTData);
00229             return E_OUTOFMEMORY;
00230         }
00231         hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
00232         IROTData_Release(pROTData);
00233         if (hr != S_OK)
00234         {
00235             ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr);
00236             HeapFree(GetProcessHeap(), 0, *moniker_data);
00237             return hr;
00238         }
00239         (*moniker_data)->ulCntData = size;
00240     }
00241     else
00242     {
00243         IBindCtx *pbc;
00244         LPOLESTR pszDisplayName;
00245         CLSID clsid;
00246         int len;
00247 
00248         TRACE("generating comparison data from display name\n");
00249 
00250         hr = CreateBindCtx(0, &pbc);
00251         if (FAILED(hr))
00252             return hr;
00253         hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName);
00254         IBindCtx_Release(pbc);
00255         if (FAILED(hr))
00256             return hr;
00257         hr = IMoniker_GetClassID(pMoniker, &clsid);
00258         if (FAILED(hr))
00259         {
00260             CoTaskMemFree(pszDisplayName);
00261             return hr;
00262         }
00263 
00264         len = strlenW(pszDisplayName);
00265         *moniker_data = HeapAlloc(GetProcessHeap(), 0,
00266             FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
00267         if (!*moniker_data)
00268         {
00269             CoTaskMemFree(pszDisplayName);
00270             return E_OUTOFMEMORY;
00271         }
00272         (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR);
00273 
00274         memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid));
00275         memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR));
00276         CoTaskMemFree(pszDisplayName);
00277     }
00278     return S_OK;
00279 }
00280 
00281 static HRESULT reduce_moniker(IMoniker *pmk, IBindCtx *pbc, IMoniker **pmkReduced)
00282 {
00283     IBindCtx *pbcNew = NULL;
00284     HRESULT hr;
00285     if (!pbc)
00286     {
00287         hr = CreateBindCtx(0, &pbcNew);
00288         if (FAILED(hr))
00289             return hr;
00290         pbc = pbcNew;
00291     }
00292     hr = IMoniker_Reduce(pmk, pbc, MKRREDUCE_ALL, NULL, pmkReduced);
00293     if (FAILED(hr))
00294         ERR("reducing moniker failed with error 0x%08x\n", hr);
00295     if (pbcNew) IBindCtx_Release(pbcNew);
00296     return hr;
00297 }
00298 
00299 /***********************************************************************
00300  *        RunningObjectTable_QueryInterface
00301  */
00302 static HRESULT WINAPI
00303 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
00304                                       REFIID riid,void** ppvObject)
00305 {
00306     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00307 
00308     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
00309 
00310     /* validate arguments */
00311 
00312     if (ppvObject==0)
00313         return E_INVALIDARG;
00314 
00315     *ppvObject = 0;
00316 
00317     if (IsEqualIID(&IID_IUnknown, riid) ||
00318         IsEqualIID(&IID_IRunningObjectTable, riid))
00319         *ppvObject = This;
00320 
00321     if ((*ppvObject)==0)
00322         return E_NOINTERFACE;
00323 
00324     IRunningObjectTable_AddRef(iface);
00325 
00326     return S_OK;
00327 }
00328 
00329 /***********************************************************************
00330  *        RunningObjectTable_AddRef
00331  */
00332 static ULONG WINAPI
00333 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
00334 {
00335     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00336 
00337     TRACE("(%p)\n",This);
00338 
00339     return InterlockedIncrement(&This->ref);
00340 }
00341 
00342 /***********************************************************************
00343  *        RunningObjectTable_Destroy
00344  */
00345 static HRESULT
00346 RunningObjectTableImpl_Destroy(void)
00347 {
00348     struct list *cursor, *cursor2;
00349     IrotHandle old_handle;
00350 
00351     TRACE("()\n");
00352 
00353     if (runningObjectTableInstance==NULL)
00354         return E_INVALIDARG;
00355 
00356     /* free the ROT table memory */
00357     LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot)
00358     {
00359         struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
00360         list_remove(&rot_entry->entry);
00361         rot_entry_delete(rot_entry);
00362     }
00363 
00364     DEBUG_CLEAR_CRITSEC_NAME(&runningObjectTableInstance->lock);
00365     DeleteCriticalSection(&runningObjectTableInstance->lock);
00366 
00367     /* free the ROT structure memory */
00368     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
00369     runningObjectTableInstance = NULL;
00370 
00371     old_handle = irot_handle;
00372     irot_handle = NULL;
00373     if (old_handle)
00374         RpcBindingFree(&old_handle);
00375 
00376     return S_OK;
00377 }
00378 
00379 /***********************************************************************
00380  *        RunningObjectTable_Release
00381  */
00382 static ULONG WINAPI
00383 RunningObjectTableImpl_Release(IRunningObjectTable* iface)
00384 {
00385     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00386     ULONG ref;
00387 
00388     TRACE("(%p)\n",This);
00389 
00390     ref = InterlockedDecrement(&This->ref);
00391 
00392     /* uninitialize ROT structure if there's no more references to it */
00393     if (ref == 0)
00394     {
00395         struct list *cursor, *cursor2;
00396         LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot)
00397         {
00398             struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
00399             list_remove(&rot_entry->entry);
00400             rot_entry_delete(rot_entry);
00401         }
00402         /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
00403          *  when RunningObjectTableImpl_UnInitialize function is called
00404          */
00405     }
00406 
00407     return ref;
00408 }
00409 
00410 /***********************************************************************
00411  *        RunningObjectTable_Register
00412  *
00413  * PARAMS
00414  * grfFlags       [in] Registration options 
00415  * punkObject     [in] the object being registered
00416  * pmkObjectName  [in] the moniker of the object being registered
00417  * pdwRegister    [out] the value identifying the registration
00418  */
00419 static HRESULT WINAPI
00420 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
00421                IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
00422 {
00423     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00424     struct rot_entry *rot_entry;
00425     HRESULT hr = S_OK;
00426     IStream *pStream = NULL;
00427     DWORD mshlflags;
00428     IBindCtx *pbc;
00429     InterfaceData *moniker = NULL;
00430 
00431     TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
00432 
00433     if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
00434     {
00435         ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
00436         return E_INVALIDARG;
00437     }
00438 
00439     if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
00440         return E_INVALIDARG;
00441 
00442     rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
00443     if (!rot_entry)
00444         return E_OUTOFMEMORY;
00445 
00446     /* marshal object */
00447     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
00448     if (hr != S_OK)
00449     {
00450         rot_entry_delete(rot_entry);
00451         return hr;
00452     }
00453     mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;
00454     hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);
00455     /* FIXME: a cleaner way would be to create an IStream class that writes
00456      * directly to an MInterfacePointer */
00457     if (hr == S_OK)
00458     {
00459         HGLOBAL hglobal;
00460         hr = GetHGlobalFromStream(pStream, &hglobal);
00461         if (hr == S_OK)
00462         {
00463             SIZE_T size = GlobalSize(hglobal);
00464             const void *pv = GlobalLock(hglobal);
00465             rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
00466             rot_entry->object->ulCntData = size;
00467             memcpy(rot_entry->object->abData, pv, size);
00468             GlobalUnlock(hglobal);
00469         }
00470     }
00471     IStream_Release(pStream);
00472     if (hr != S_OK)
00473     {
00474         rot_entry_delete(rot_entry);
00475         return hr;
00476     }
00477 
00478     hr = CreateBindCtx(0, &pbc);
00479     if (FAILED(hr))
00480     {
00481         rot_entry_delete(rot_entry);
00482         return hr;
00483     }
00484 
00485     hr = reduce_moniker(pmkObjectName, pbc, &pmkObjectName);
00486     if (FAILED(hr))
00487     {
00488         rot_entry_delete(rot_entry);
00489         IBindCtx_Release(pbc);
00490         return hr;
00491     }
00492 
00493     hr = IMoniker_GetTimeOfLastChange(pmkObjectName, pbc, NULL,
00494                                       &rot_entry->last_modified);
00495     IBindCtx_Release(pbc);
00496     if (FAILED(hr))
00497     {
00498         CoFileTimeNow(&rot_entry->last_modified);
00499         hr = S_OK;
00500     }
00501 
00502     hr = get_moniker_comparison_data(pmkObjectName,
00503                                      &rot_entry->moniker_data);
00504     if (hr != S_OK)
00505     {
00506         rot_entry_delete(rot_entry);
00507         IMoniker_Release(pmkObjectName);
00508         return hr;
00509     }
00510 
00511     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
00512     if (hr != S_OK)
00513     {
00514         rot_entry_delete(rot_entry);
00515         IMoniker_Release(pmkObjectName);
00516         return hr;
00517     }
00518     /* marshal moniker */
00519     hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName,
00520                             MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
00521     /* FIXME: a cleaner way would be to create an IStream class that writes
00522      * directly to an MInterfacePointer */
00523     if (hr == S_OK)
00524     {
00525         HGLOBAL hglobal;
00526         hr = GetHGlobalFromStream(pStream, &hglobal);
00527         if (hr == S_OK)
00528         {
00529             SIZE_T size = GlobalSize(hglobal);
00530             const void *pv = GlobalLock(hglobal);
00531             moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size]));
00532             moniker->ulCntData = size;
00533             memcpy(moniker->abData, pv, size);
00534             GlobalUnlock(hglobal);
00535         }
00536     }
00537     IStream_Release(pStream);
00538     IMoniker_Release(pmkObjectName);
00539     if (hr != S_OK)
00540     {
00541         HeapFree(GetProcessHeap(), 0, moniker);
00542         rot_entry_delete(rot_entry);
00543         return hr;
00544     }
00545 
00546 
00547     while (TRUE)
00548     {
00549         __TRY
00550         {
00551             hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data,
00552                               rot_entry->object, moniker,
00553                               &rot_entry->last_modified, grfFlags,
00554                               &rot_entry->cookie, &rot_entry->ctxt_handle);
00555         }
00556         __EXCEPT(rpc_filter)
00557         {
00558             hr = HRESULT_FROM_WIN32(GetExceptionCode());
00559         }
00560         __ENDTRY
00561         if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
00562         {
00563             if (start_rpcss())
00564                 continue;
00565         }
00566         break;
00567     }
00568     HeapFree(GetProcessHeap(), 0, moniker);
00569     if (FAILED(hr))
00570     {
00571         rot_entry_delete(rot_entry);
00572         return hr;
00573     }
00574 
00575     /* gives a registration identifier to the registered object*/
00576     *pdwRegister = rot_entry->cookie;
00577 
00578     EnterCriticalSection(&This->lock);
00579     list_add_tail(&This->rot, &rot_entry->entry);
00580     LeaveCriticalSection(&This->lock);
00581 
00582     return hr;
00583 }
00584 
00585 /***********************************************************************
00586  *        RunningObjectTable_Revoke
00587  *
00588  * PARAMS
00589  *  dwRegister [in] Value identifying registration to be revoked
00590  */
00591 static HRESULT WINAPI
00592 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) 
00593 {
00594     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00595     struct rot_entry *rot_entry;
00596 
00597     TRACE("(%p,%d)\n",This,dwRegister);
00598 
00599     EnterCriticalSection(&This->lock);
00600     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
00601     {
00602         if (rot_entry->cookie == dwRegister)
00603         {
00604             list_remove(&rot_entry->entry);
00605             LeaveCriticalSection(&This->lock);
00606 
00607             rot_entry_delete(rot_entry);
00608             return S_OK;
00609         }
00610     }
00611     LeaveCriticalSection(&This->lock);
00612 
00613     return E_INVALIDARG;
00614 }
00615 
00616 /***********************************************************************
00617  *        RunningObjectTable_IsRunning
00618  *
00619  * PARAMS
00620  *  pmkObjectName [in]  moniker of the object whose status is desired 
00621  */
00622 static HRESULT WINAPI
00623 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
00624 {
00625     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00626     MonikerComparisonData *moniker_data;
00627     HRESULT hr;
00628     const struct rot_entry *rot_entry;
00629 
00630     TRACE("(%p,%p)\n",This,pmkObjectName);
00631 
00632     hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
00633     if (FAILED(hr))
00634         return hr;
00635     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
00636     IMoniker_Release(pmkObjectName);
00637     if (hr != S_OK)
00638         return hr;
00639 
00640     hr = S_FALSE;
00641     EnterCriticalSection(&This->lock);
00642     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
00643     {
00644         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
00645             !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
00646         {
00647             hr = S_OK;
00648             break;
00649         }
00650     }
00651     LeaveCriticalSection(&This->lock);
00652 
00653     if (hr == S_FALSE)
00654     {
00655         while (TRUE)
00656         {
00657             __TRY
00658             {
00659                 hr = IrotIsRunning(get_irot_handle(), moniker_data);
00660             }
00661             __EXCEPT(rpc_filter)
00662             {
00663                 hr = HRESULT_FROM_WIN32(GetExceptionCode());
00664             }
00665             __ENDTRY
00666             if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
00667             {
00668                 if (start_rpcss())
00669                     continue;
00670             }
00671             break;
00672         }
00673     }
00674 
00675     HeapFree(GetProcessHeap(), 0, moniker_data);
00676 
00677     return hr;
00678 }
00679 
00680 /***********************************************************************
00681  *        RunningObjectTable_GetObject
00682  *
00683  * PARAMS
00684  * pmkObjectName [in] Pointer to the moniker on the object 
00685  * ppunkObject   [out] variable that receives the IUnknown interface pointer
00686  */
00687 static HRESULT WINAPI
00688 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
00689                      IMoniker *pmkObjectName, IUnknown **ppunkObject)
00690 {
00691     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00692     MonikerComparisonData *moniker_data;
00693     InterfaceData *object = NULL;
00694     IrotCookie cookie;
00695     HRESULT hr;
00696     struct rot_entry *rot_entry;
00697 
00698     TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
00699 
00700     if (ppunkObject == NULL)
00701         return E_POINTER;
00702 
00703     *ppunkObject = NULL;
00704 
00705     hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
00706     if (FAILED(hr))
00707         return hr;
00708     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
00709     IMoniker_Release(pmkObjectName);
00710     if (hr != S_OK)
00711         return hr;
00712 
00713     EnterCriticalSection(&This->lock);
00714     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
00715     {
00716         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
00717             !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
00718         {
00719             IStream *pStream;
00720             hr = create_stream_on_mip_ro(rot_entry->object, &pStream);
00721             if (hr == S_OK)
00722             {
00723                 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
00724                 IStream_Release(pStream);
00725             }
00726 
00727             LeaveCriticalSection(&This->lock);
00728             HeapFree(GetProcessHeap(), 0, moniker_data);
00729 
00730             return hr;
00731         }
00732     }
00733     LeaveCriticalSection(&This->lock);
00734 
00735     TRACE("moniker unavailable locally, calling SCM\n");
00736 
00737     while (TRUE)
00738     {
00739         __TRY
00740         {
00741             hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie);
00742         }
00743         __EXCEPT(rpc_filter)
00744         {
00745             hr = HRESULT_FROM_WIN32(GetExceptionCode());
00746         }
00747         __ENDTRY
00748         if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
00749         {
00750             if (start_rpcss())
00751                 continue;
00752         }
00753         break;
00754     }
00755 
00756     if (SUCCEEDED(hr))
00757     {
00758         IStream *pStream;
00759         hr = create_stream_on_mip_ro(object, &pStream);
00760         if (hr == S_OK)
00761         {
00762             hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
00763             IStream_Release(pStream);
00764         }
00765     }
00766     else
00767         WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr);
00768 
00769     HeapFree(GetProcessHeap(), 0, moniker_data);
00770 
00771     return hr;
00772 }
00773 
00774 /***********************************************************************
00775  *        RunningObjectTable_NoteChangeTime
00776  *
00777  * PARAMS
00778  *  dwRegister [in] Value identifying registration being updated
00779  *  pfiletime  [in] Pointer to structure containing object's last change time
00780  */
00781 static HRESULT WINAPI
00782 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
00783                                       DWORD dwRegister, FILETIME *pfiletime)
00784 {
00785     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00786     struct rot_entry *rot_entry;
00787     HRESULT hr = E_INVALIDARG;
00788 
00789     TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime);
00790 
00791     EnterCriticalSection(&This->lock);
00792     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
00793     {
00794         if (rot_entry->cookie == dwRegister)
00795         {
00796             rot_entry->last_modified = *pfiletime;
00797             LeaveCriticalSection(&This->lock);
00798 
00799             while (TRUE)
00800             {
00801                 __TRY
00802                 {
00803                     hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime);
00804                 }
00805                 __EXCEPT(rpc_filter)
00806                 {
00807                     hr = HRESULT_FROM_WIN32(GetExceptionCode());
00808                 }
00809                 __ENDTRY
00810                 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
00811                 {
00812                     if (start_rpcss())
00813                         continue;
00814                 }
00815                 break;
00816             }
00817 
00818             goto done;
00819         }
00820     }
00821     LeaveCriticalSection(&This->lock);
00822 
00823 done:
00824     TRACE("-- 0x08%x\n", hr);
00825     return hr;
00826 }
00827 
00828 /***********************************************************************
00829  *        RunningObjectTable_GetTimeOfLastChange
00830  *
00831  * PARAMS
00832  *  pmkObjectName  [in]  moniker of the object whose status is desired 
00833  *  pfiletime      [out] structure that receives object's last change time
00834  */
00835 static HRESULT WINAPI
00836 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
00837                             IMoniker *pmkObjectName, FILETIME *pfiletime)
00838 {
00839     HRESULT hr = MK_E_UNAVAILABLE;
00840     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00841     MonikerComparisonData *moniker_data;
00842     const struct rot_entry *rot_entry;
00843 
00844     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
00845 
00846     if (pmkObjectName==NULL || pfiletime==NULL)
00847         return E_INVALIDARG;
00848 
00849     hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
00850     if (FAILED(hr))
00851         return hr;
00852     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
00853     IMoniker_Release(pmkObjectName);
00854     if (hr != S_OK)
00855         return hr;
00856 
00857     hr = MK_E_UNAVAILABLE;
00858 
00859     EnterCriticalSection(&This->lock);
00860     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
00861     {
00862         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
00863             !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
00864         {
00865             *pfiletime = rot_entry->last_modified;
00866             hr = S_OK;
00867             break;
00868         }
00869     }
00870     LeaveCriticalSection(&This->lock);
00871 
00872     if (hr != S_OK)
00873     {
00874         while (TRUE)
00875         {
00876             __TRY
00877             {
00878                 hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime);
00879             }
00880             __EXCEPT(rpc_filter)
00881             {
00882                 hr = HRESULT_FROM_WIN32(GetExceptionCode());
00883             }
00884             __ENDTRY
00885             if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
00886             {
00887                 if (start_rpcss())
00888                     continue;
00889             }
00890             break;
00891         }
00892     }
00893 
00894     HeapFree(GetProcessHeap(), 0, moniker_data);
00895 
00896     TRACE("-- 0x%08x\n", hr);
00897     return hr;
00898 }
00899 
00900 /***********************************************************************
00901  *        RunningObjectTable_EnumRunning
00902  *
00903  * PARAMS
00904  *  ppenumMoniker  [out]  receives the IEnumMoniker interface pointer 
00905  */
00906 static HRESULT WINAPI
00907 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
00908                                    IEnumMoniker **ppenumMoniker)
00909 {
00910     RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
00911     InterfaceList *interface_list = NULL;
00912     HRESULT hr;
00913 
00914     TRACE("(%p, %p)\n", This, ppenumMoniker);
00915 
00916     *ppenumMoniker = NULL;
00917 
00918     while (TRUE)
00919     {
00920         __TRY
00921         {
00922             hr = IrotEnumRunning(get_irot_handle(), &interface_list);
00923         }
00924         __EXCEPT(rpc_filter)
00925         {
00926             hr = HRESULT_FROM_WIN32(GetExceptionCode());
00927         }
00928         __ENDTRY
00929         if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
00930         {
00931             if (start_rpcss())
00932                 continue;
00933         }
00934         break;
00935     }
00936 
00937     if (SUCCEEDED(hr))
00938         hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list,
00939                                                   0, ppenumMoniker);
00940 
00941     return hr;
00942 }
00943 
00944 /* Virtual function table for the IRunningObjectTable class. */
00945 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl =
00946 {
00947     RunningObjectTableImpl_QueryInterface,
00948     RunningObjectTableImpl_AddRef,
00949     RunningObjectTableImpl_Release,
00950     RunningObjectTableImpl_Register,
00951     RunningObjectTableImpl_Revoke,
00952     RunningObjectTableImpl_IsRunning,
00953     RunningObjectTableImpl_GetObject,
00954     RunningObjectTableImpl_NoteChangeTime,
00955     RunningObjectTableImpl_GetTimeOfLastChange,
00956     RunningObjectTableImpl_EnumRunning
00957 };
00958 
00959 /***********************************************************************
00960  *        RunningObjectTable_Initialize
00961  */
00962 HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
00963 {
00964     TRACE("\n");
00965 
00966     /* create the unique instance of the RunningObjectTableImpl structure */
00967     runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
00968 
00969     if (!runningObjectTableInstance)
00970         return E_OUTOFMEMORY;
00971 
00972     /* initialize the virtual table function */
00973     runningObjectTableInstance->IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl;
00974 
00975     /* the initial reference is set to "1" so that it isn't destroyed after its
00976      * first use until the process is destroyed, as the running object table is
00977      * a process-wide cache of a global table */
00978     runningObjectTableInstance->ref = 1;
00979 
00980     list_init(&runningObjectTableInstance->rot);
00981     InitializeCriticalSection(&runningObjectTableInstance->lock);
00982     DEBUG_SET_CRITSEC_NAME(&runningObjectTableInstance->lock, "RunningObjectTableImpl.lock");
00983 
00984     return S_OK;
00985 }
00986 
00987 /***********************************************************************
00988  *        RunningObjectTable_UnInitialize
00989  */
00990 HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void)
00991 {
00992     TRACE("\n");
00993 
00994     if (runningObjectTableInstance==NULL)
00995         return E_POINTER;
00996 
00997     RunningObjectTableImpl_Release(&runningObjectTableInstance->IRunningObjectTable_iface);
00998 
00999     RunningObjectTableImpl_Destroy();
01000 
01001     return S_OK;
01002 }
01003 
01004 /***********************************************************************
01005  *           GetRunningObjectTable (OLE32.@)
01006  *
01007  * Retrieves the global running object table.
01008  *
01009  * PARAMS
01010  *  reserved [I] Reserved. Set to 0.
01011  *  pprot    [O] Address that receives the pointer to the running object table.
01012  *
01013  * RETURNS
01014  *  Success: S_OK.
01015  *  Failure: Any HRESULT code.
01016  */
01017 HRESULT WINAPI
01018 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
01019 {
01020     IID riid=IID_IRunningObjectTable;
01021     HRESULT res;
01022 
01023     TRACE("()\n");
01024 
01025     if (reserved!=0)
01026         return E_UNEXPECTED;
01027 
01028     if(runningObjectTableInstance==NULL)
01029         return CO_E_NOTINITIALIZED;
01030 
01031     res = IRunningObjectTable_QueryInterface(&runningObjectTableInstance->IRunningObjectTable_iface,
01032                                              &riid,(void**)pprot);
01033 
01034     return res;
01035 }
01036 
01037 static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
01038                                                    LPCOLESTR szDisplayName,
01039                                                    LPDWORD pchEaten,
01040                                                    LPMONIKER *ppmk)
01041 {
01042     CLSID clsid;
01043     HRESULT hr;
01044     LPWSTR progid;
01045     LPCWSTR start = szDisplayName;
01046     LPCWSTR end;
01047     int len;
01048     IMoniker *class_moniker;
01049 
01050     if (*start == '@')
01051         start++;
01052 
01053     /* find end delimiter */
01054     for (end = start; *end; end++)
01055         if (*end == ':')
01056             break;
01057 
01058     len = end - start;
01059 
01060     /* must start with '@' or have a ':' somewhere and mustn't be one character
01061      * long (since that looks like an absolute path) */
01062     if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
01063         return MK_E_SYNTAX;
01064 
01065     progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
01066     if (progid)
01067     {
01068         memcpy(progid, start, len * sizeof(WCHAR));
01069         progid[len] = '\0';
01070     }
01071     hr = CLSIDFromProgID(progid, &clsid);
01072     HeapFree(GetProcessHeap(), 0, progid);
01073     if (FAILED(hr))
01074         return MK_E_SYNTAX;
01075 
01076     hr = CreateClassMoniker(&clsid, &class_moniker);
01077     if (SUCCEEDED(hr))
01078     {
01079         IParseDisplayName *pdn;
01080         hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
01081                                    &IID_IParseDisplayName, (void **)&pdn);
01082         /* fallback to using IClassFactory to get IParseDisplayName -
01083          * adsldp.dll depends on this */
01084         if (FAILED(hr))
01085         {
01086             IClassFactory *pcf;
01087             hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
01088                                        &IID_IClassFactory, (void **)&pcf);
01089             if (SUCCEEDED(hr))
01090             {
01091                 hr = IClassFactory_CreateInstance(pcf, NULL,
01092                                                   &IID_IParseDisplayName,
01093                                                   (void **)&pdn);
01094                 IClassFactory_Release(pcf);
01095             }
01096         }
01097         IMoniker_Release(class_moniker);
01098         if (SUCCEEDED(hr))
01099         {
01100             hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
01101                                                     (LPOLESTR)szDisplayName,
01102                                                     pchEaten, ppmk);
01103             IParseDisplayName_Release(pdn);
01104         }
01105     }
01106     return hr;
01107 }
01108 
01109 /******************************************************************************
01110  *              MkParseDisplayName        [OLE32.@]
01111  */
01112 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
01113                 LPDWORD pchEaten, LPMONIKER *ppmk)
01114 {
01115     HRESULT hr = MK_E_SYNTAX;
01116     static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
01117     IMoniker *moniker;
01118     DWORD chEaten;
01119 
01120     TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
01121 
01122     if (!pbc || !IsValidInterface((LPUNKNOWN) pbc))
01123         return E_INVALIDARG;
01124 
01125     if (!szDisplayName || !*szDisplayName)
01126         return E_INVALIDARG;
01127 
01128     if (!pchEaten || !ppmk)
01129         return E_INVALIDARG;
01130 
01131     *pchEaten = 0;
01132     *ppmk = NULL;
01133 
01134     if (!strncmpiW(szDisplayName, wszClsidColon, sizeof(wszClsidColon)/sizeof(wszClsidColon[0])))
01135     {
01136         hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
01137         if (FAILED(hr) && (hr != MK_E_SYNTAX))
01138             return hr;
01139     }
01140     else
01141     {
01142         hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
01143         if (FAILED(hr) && (hr != MK_E_SYNTAX))
01144             return hr;
01145     }
01146 
01147     if (FAILED(hr))
01148     {
01149         hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
01150         if (FAILED(hr) && (hr != MK_E_SYNTAX))
01151             return hr;
01152     }
01153 
01154     if (SUCCEEDED(hr))
01155     {
01156         while (TRUE)
01157         {
01158             IMoniker *next_moniker;
01159             *pchEaten += chEaten;
01160             szDisplayName += chEaten;
01161             if (!*szDisplayName)
01162             {
01163                 *ppmk = moniker;
01164                 return S_OK;
01165             }
01166             chEaten = 0;
01167             hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
01168                                            (LPOLESTR)szDisplayName, &chEaten,
01169                                            &next_moniker);
01170             IMoniker_Release(moniker);
01171             if (FAILED(hr))
01172             {
01173                 *pchEaten = 0;
01174                 break;
01175             }
01176             moniker = next_moniker;
01177         }
01178     }
01179 
01180     return hr;
01181 }
01182 
01183 /***********************************************************************
01184  *        GetClassFile (OLE32.@)
01185  *
01186  * Retrieves the class ID associated with the given filename.
01187  *
01188  * PARAMS
01189  *  filePathName [I] Filename to retrieve the class ID for.
01190  *  pclsid       [O] Address that receives the class ID for the file.
01191  *
01192  * RETURNS
01193  *  Success: S_OK.
01194  *  Failure: Any HRESULT code.
01195  */
01196 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
01197 {
01198     IStorage *pstg=0;
01199     HRESULT res;
01200     int nbElm, length, i;
01201     LONG sizeProgId;
01202     LPOLESTR *pathDec=0,absFile=0,progId=0;
01203     LPWSTR extension;
01204     static const WCHAR bkslashW[] = {'\\',0};
01205     static const WCHAR dotW[] = {'.',0};
01206 
01207     TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
01208 
01209     /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/
01210     if((StgIsStorageFile(filePathName))==S_OK){
01211 
01212         res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
01213 
01214         if (SUCCEEDED(res))
01215             res=ReadClassStg(pstg,pclsid);
01216 
01217         IStorage_Release(pstg);
01218 
01219         return res;
01220     }
01221     /* If the file is not a storage object then attempt to match various bits in the file against a
01222        pattern in the registry. This case is not frequently used, so I present only the pseudocode for
01223        this case.
01224 
01225      for(i=0;i<nFileTypes;i++)
01226 
01227         for(i=0;j<nPatternsForType;j++){
01228 
01229             PATTERN pat;
01230             HANDLE  hFile;
01231 
01232             pat=ReadPatternFromRegistry(i,j);
01233             hFile=CreateFileW(filePathName,,,,,,hFile);
01234             SetFilePosition(hFile,pat.offset);
01235             ReadFile(hFile,buf,pat.size,&r,NULL);
01236             if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
01237 
01238                 *pclsid=ReadCLSIDFromRegistry(i);
01239                 return S_OK;
01240             }
01241         }
01242      */
01243 
01244     /* if the above strategies fail then search for the extension key in the registry */
01245 
01246     /* get the last element (absolute file) in the path name */
01247     nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
01248     absFile=pathDec[nbElm-1];
01249 
01250     /* failed if the path represents a directory and not an absolute file name*/
01251     if (!lstrcmpW(absFile, bkslashW))
01252         return MK_E_INVALIDEXTENSION;
01253 
01254     /* get the extension of the file */
01255     extension = NULL;
01256     length=lstrlenW(absFile);
01257     for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--)
01258         /* nothing */;
01259 
01260     if (!extension || !lstrcmpW(extension, dotW))
01261         return MK_E_INVALIDEXTENSION;
01262 
01263     res=RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
01264 
01265     /* get the progId associated to the extension */
01266     progId = CoTaskMemAlloc(sizeProgId);
01267     res = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
01268 
01269     if (res==ERROR_SUCCESS)
01270         /* return the clsid associated to the progId */
01271         res= CLSIDFromProgID(progId,pclsid);
01272 
01273     for(i=0; pathDec[i]!=NULL;i++)
01274         CoTaskMemFree(pathDec[i]);
01275     CoTaskMemFree(pathDec);
01276 
01277     CoTaskMemFree(progId);
01278 
01279     if (res==ERROR_SUCCESS)
01280         return res;
01281 
01282     return MK_E_INVALIDEXTENSION;
01283 }
01284 
01285 /***********************************************************************
01286  *        EnumMoniker_QueryInterface
01287  */
01288 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
01289 {
01290     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01291 
01292     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
01293 
01294     /* validate arguments */
01295     if (ppvObject == NULL)
01296         return E_INVALIDARG;
01297 
01298     *ppvObject = NULL;
01299 
01300     if (IsEqualIID(&IID_IUnknown, riid))
01301         *ppvObject = This;
01302     else
01303         if (IsEqualIID(&IID_IEnumMoniker, riid))
01304             *ppvObject = This;
01305 
01306     if ((*ppvObject)==NULL)
01307         return E_NOINTERFACE;
01308 
01309     IEnumMoniker_AddRef(iface);
01310 
01311     return S_OK;
01312 }
01313 
01314 /***********************************************************************
01315  *        EnumMoniker_AddRef
01316  */
01317 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
01318 {
01319     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01320 
01321     TRACE("(%p)\n",This);
01322 
01323     return InterlockedIncrement(&This->ref);
01324 }
01325 
01326 /***********************************************************************
01327  *        EnumMoniker_release
01328  */
01329 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
01330 {
01331     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01332     ULONG ref;
01333 
01334     TRACE("(%p)\n",This);
01335 
01336     ref = InterlockedDecrement(&This->ref);
01337 
01338     /* uninitialize rot structure if there's no more reference to it*/
01339     if (ref == 0)
01340     {
01341         ULONG i;
01342 
01343         TRACE("(%p) Deleting\n",This);
01344 
01345         for (i = 0; i < This->moniker_list->size; i++)
01346             HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]);
01347         HeapFree(GetProcessHeap(), 0, This->moniker_list);
01348         HeapFree(GetProcessHeap(), 0, This);
01349     }
01350 
01351     return ref;
01352 }
01353 /***********************************************************************
01354  *        EnumMoniker_Next
01355  */
01356 static HRESULT   WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
01357 {
01358     ULONG i;
01359     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01360     HRESULT hr = S_OK;
01361 
01362     TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size);
01363 
01364     /* retrieve the requested number of moniker from the current position */
01365     for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
01366     {
01367         IStream *stream;
01368         hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
01369         if (hr != S_OK) break;
01370         hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
01371         IStream_Release(stream);
01372         if (hr != S_OK) break;
01373     }
01374 
01375     if (pceltFetched != NULL)
01376         *pceltFetched= i;
01377 
01378     if (hr != S_OK)
01379         return hr;
01380 
01381     if (i == celt)
01382         return S_OK;
01383     else
01384         return S_FALSE;
01385 
01386 }
01387 
01388 /***********************************************************************
01389  *        EnumMoniker_Skip
01390  */
01391 static HRESULT   WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
01392 {
01393     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01394 
01395     TRACE("(%p)\n",This);
01396 
01397     if  (This->pos + celt >= This->moniker_list->size)
01398         return S_FALSE;
01399 
01400     This->pos += celt;
01401 
01402     return S_OK;
01403 }
01404 
01405 /***********************************************************************
01406  *        EnumMoniker_Reset
01407  */
01408 static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
01409 {
01410     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01411 
01412     This->pos = 0;  /* set back to start of list */
01413 
01414     TRACE("(%p)\n",This);
01415 
01416     return S_OK;
01417 }
01418 
01419 /***********************************************************************
01420  *        EnumMoniker_Clone
01421  */
01422 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
01423 {
01424     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01425     InterfaceList *moniker_list;
01426     ULONG i;
01427 
01428     TRACE("(%p)\n",This);
01429 
01430     *ppenum = NULL;
01431 
01432     moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
01433     if (!moniker_list)
01434         return E_OUTOFMEMORY;
01435 
01436     moniker_list->size = This->moniker_list->size;
01437     for (i = 0; i < This->moniker_list->size; i++)
01438     {
01439         SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
01440         moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size);
01441         if (!moniker_list->interfaces[i])
01442         {
01443             ULONG end = i;
01444             for (i = 0; i < end; i++)
01445                 HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]);
01446             HeapFree(GetProcessHeap(), 0, moniker_list);
01447             return E_OUTOFMEMORY;
01448         }
01449         memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
01450     }
01451 
01452     /* copy the enum structure */ 
01453     return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
01454 }
01455 
01456 /* Virtual function table for the IEnumMoniker class. */
01457 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
01458 {
01459     EnumMonikerImpl_QueryInterface,
01460     EnumMonikerImpl_AddRef,
01461     EnumMonikerImpl_Release,
01462     EnumMonikerImpl_Next,
01463     EnumMonikerImpl_Skip,
01464     EnumMonikerImpl_Reset,
01465     EnumMonikerImpl_Clone
01466 };
01467 
01468 /***********************************************************************
01469  *        EnumMonikerImpl_CreateEnumROTMoniker
01470  *        Used by EnumRunning to create the structure and EnumClone
01471  *    to copy the structure
01472  */
01473 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
01474                                                  ULONG current_pos,
01475                                                  IEnumMoniker **ppenumMoniker)
01476 {
01477     EnumMonikerImpl* This = NULL;
01478 
01479     if (!ppenumMoniker)
01480         return E_INVALIDARG;
01481 
01482     This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
01483     if (!This) return E_OUTOFMEMORY;
01484 
01485     TRACE("(%p)\n", This);
01486 
01487     /* initialize the virtual table function */
01488     This->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
01489 
01490     /* the initial reference is set to "1" */
01491     This->ref = 1;          /* set the ref count to one         */
01492     This->pos = current_pos;        /* Set the list start posn */
01493     This->moniker_list = moniker_list;
01494 
01495     *ppenumMoniker =  &This->IEnumMoniker_iface;
01496 
01497     return S_OK;
01498 }
01499 
01500 
01501 /* Shared implementation of moniker marshaler based on saving and loading of
01502  * monikers */
01503 
01504 typedef struct MonikerMarshal
01505 {
01506     IUnknown IUnknown_iface;
01507     IMarshal IMarshal_iface;
01508 
01509     LONG ref;
01510     IMoniker *moniker;
01511 } MonikerMarshal;
01512 
01513 static inline MonikerMarshal *impl_from_IUnknown(IUnknown *iface)
01514 {
01515     return CONTAINING_RECORD(iface, MonikerMarshal, IUnknown_iface);
01516 }
01517 
01518 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
01519 {
01520     return CONTAINING_RECORD(iface, MonikerMarshal, IMarshal_iface);
01521 }
01522 
01523 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
01524 {
01525     MonikerMarshal *This = impl_from_IUnknown(iface);
01526     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
01527     *ppv = NULL;
01528     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
01529     {
01530         *ppv = &This->IMarshal_iface;
01531         IUnknown_AddRef((IUnknown *)&This->IMarshal_iface);
01532         return S_OK;
01533     }
01534     FIXME("No interface for %s\n", debugstr_guid(riid));
01535     return E_NOINTERFACE;
01536 }
01537 
01538 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
01539 {
01540     MonikerMarshal *This = impl_from_IUnknown(iface);
01541     return InterlockedIncrement(&This->ref);
01542 }
01543 
01544 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
01545 {
01546     MonikerMarshal *This = impl_from_IUnknown(iface);
01547     ULONG ref = InterlockedDecrement(&This->ref);
01548 
01549     if (!ref) HeapFree(GetProcessHeap(), 0, This);
01550     return ref;
01551 }
01552 
01553 static const IUnknownVtbl VT_MonikerMarshalInner =
01554 {
01555     MonikerMarshalInner_QueryInterface,
01556     MonikerMarshalInner_AddRef,
01557     MonikerMarshalInner_Release
01558 };
01559 
01560 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
01561 {
01562     MonikerMarshal *This = impl_from_IMarshal(iface);
01563     return IMoniker_QueryInterface(This->moniker, riid, ppv);
01564 }
01565 
01566 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
01567 {
01568     MonikerMarshal *This = impl_from_IMarshal(iface);
01569     return IMoniker_AddRef(This->moniker);
01570 }
01571 
01572 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
01573 {
01574     MonikerMarshal *This = impl_from_IMarshal(iface);
01575     return IMoniker_Release(This->moniker);
01576 }
01577 
01578 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
01579   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
01580   void* pvDestContext, DWORD mshlflags, CLSID* pCid)
01581 {
01582     MonikerMarshal *This = impl_from_IMarshal(iface);
01583 
01584     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
01585         dwDestContext, pvDestContext, mshlflags, pCid);
01586 
01587     return IMoniker_GetClassID(This->moniker, pCid);
01588 }
01589 
01590 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
01591   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
01592   void* pvDestContext, DWORD mshlflags, DWORD* pSize)
01593 {
01594     MonikerMarshal *This = impl_from_IMarshal(iface);
01595     HRESULT hr;
01596     ULARGE_INTEGER size;
01597 
01598     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
01599         dwDestContext, pvDestContext, mshlflags, pSize);
01600 
01601     hr = IMoniker_GetSizeMax(This->moniker, &size);
01602     if (hr == S_OK)
01603         *pSize = (DWORD)size.QuadPart;
01604     return hr;
01605 }
01606 
01607 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, 
01608     REFIID riid, void* pv, DWORD dwDestContext,
01609     void* pvDestContext, DWORD mshlflags)
01610 {
01611     MonikerMarshal *This = impl_from_IMarshal(iface);
01612 
01613     TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
01614         dwDestContext, pvDestContext, mshlflags);
01615 
01616     return IMoniker_Save(This->moniker, pStm, FALSE);
01617 }
01618 
01619 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
01620 {
01621     MonikerMarshal *This = impl_from_IMarshal(iface);
01622     HRESULT hr;
01623 
01624     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
01625 
01626     hr = IMoniker_Load(This->moniker, pStm);
01627     if (hr == S_OK)
01628         hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
01629     return hr;
01630 }
01631 
01632 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
01633 {
01634     TRACE("()\n");
01635     /* can't release a state-based marshal as nothing on server side to
01636      * release */
01637     return S_OK;
01638 }
01639 
01640 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
01641 {
01642     TRACE("()\n");
01643     /* can't disconnect a state-based marshal as nothing on server side to
01644      * disconnect from */
01645     return S_OK;
01646 }
01647 
01648 static const IMarshalVtbl VT_MonikerMarshal =
01649 {
01650     MonikerMarshal_QueryInterface,
01651     MonikerMarshal_AddRef,
01652     MonikerMarshal_Release,
01653     MonikerMarshal_GetUnmarshalClass,
01654     MonikerMarshal_GetMarshalSizeMax,
01655     MonikerMarshal_MarshalInterface,
01656     MonikerMarshal_UnmarshalInterface,
01657     MonikerMarshal_ReleaseMarshalData,
01658     MonikerMarshal_DisconnectObject
01659 };
01660 
01661 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
01662 {
01663     MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
01664     if (!This) return E_OUTOFMEMORY;
01665 
01666     This->IUnknown_iface.lpVtbl = &VT_MonikerMarshalInner;
01667     This->IMarshal_iface.lpVtbl = &VT_MonikerMarshal;
01668     This->ref = 1;
01669     This->moniker = inner;
01670 
01671     *outer = &This->IUnknown_iface;
01672     return S_OK;
01673 }
01674 
01675 void * __RPC_USER MIDL_user_allocate(SIZE_T size)
01676 {
01677     return HeapAlloc(GetProcessHeap(), 0, size);
01678 }
01679 
01680 void __RPC_USER MIDL_user_free(void *p)
01681 {
01682     HeapFree(GetProcessHeap(), 0, p);
01683 }

Generated on Sun May 27 2012 04:24:15 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.