Author: cwittich Date: Mon Aug 24 12:51:15 2009 New Revision: 42905
URL: http://svn.reactos.org/svn/reactos?rev=42905&view=rev Log: sync ole32 with wine 1.1.28
Modified: trunk/reactos/dll/win32/ole32/clipboard.c trunk/reactos/dll/win32/ole32/comcat.c trunk/reactos/dll/win32/ole32/compobj.c trunk/reactos/dll/win32/ole32/compobj_private.h trunk/reactos/dll/win32/ole32/defaulthandler.c trunk/reactos/dll/win32/ole32/errorinfo.c trunk/reactos/dll/win32/ole32/ftmarshal.c trunk/reactos/dll/win32/ole32/marshal.c trunk/reactos/dll/win32/ole32/ole2.c trunk/reactos/dll/win32/ole32/ole32.spec trunk/reactos/dll/win32/ole32/stg_prop.c trunk/reactos/dll/win32/ole32/stg_stream.c trunk/reactos/dll/win32/ole32/storage32.c trunk/reactos/dll/win32/ole32/storage32.h trunk/reactos/dll/win32/ole32/stubmanager.c
Modified: trunk/reactos/dll/win32/ole32/clipboard.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/clipboard.c... ============================================================================== --- trunk/reactos/dll/win32/ole32/clipboard.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/clipboard.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -744,6 +744,30 @@ return hr; }
+static HRESULT get_data_from_enhmetafile(IDataObject *data, FORMATETC *fmt, HGLOBAL *mem) +{ + HENHMETAFILE copy; + HRESULT hr; + FORMATETC mem_fmt; + STGMEDIUM med; + + *mem = NULL; + + mem_fmt = *fmt; + mem_fmt.tymed = TYMED_ENHMF; + + hr = IDataObject_GetData(data, &mem_fmt, &med); + if(FAILED(hr)) return hr; + + copy = CopyEnhMetaFileW(med.u.hEnhMetaFile, NULL); + if(copy) *mem = (HGLOBAL)copy; + else hr = E_FAIL; + + ReleaseStgMedium(&med); + + return hr; +} + /*********************************************************************** * render_format * @@ -772,6 +796,10 @@ else if(fmt->tymed & TYMED_HGLOBAL) { hr = get_data_from_global(data, fmt, &clip_data); + } + else if(fmt->tymed & TYMED_ENHMF) + { + hr = get_data_from_enhmetafile(data, fmt, &clip_data); } else { @@ -997,8 +1025,7 @@ { char buf[100]; GetClipboardFormatNameA(cf, buf, sizeof(buf)); - TRACE("\tcf %04x %s\n", cf, buf); - ; + TRACE("cf %04x %s\n", cf, buf); } TRACE("count %d\n", count); size += count * sizeof(ret->entries[0]); @@ -1106,6 +1133,22 @@ return hr; }
+/************************************************************************ + * get_stgmed_for_emf + * + * Returns a stg medium with an enhanced metafile based on the handle + */ +static HRESULT get_stgmed_for_emf(HENHMETAFILE hemf, STGMEDIUM *med) +{ + med->pUnkForRelease = NULL; + med->tymed = TYMED_NULL; + + med->u.hEnhMetaFile = CopyEnhMetaFileW(hemf, NULL); + if(!med->u.hEnhMetaFile) return E_OUTOFMEMORY; + med->tymed = TYMED_ENHMF; + return S_OK; +} + static inline BOOL string_off_equal(const DVTARGETDEVICE *t1, WORD off1, const DVTARGETDEVICE *t2, WORD off2) { const WCHAR *str1, *str2; @@ -1195,6 +1238,8 @@ hr = get_stgmed_for_global(h, med); else if(mask & TYMED_ISTREAM) hr = get_stgmed_for_stream(h, med); + else if(mask & TYMED_ENHMF) + hr = get_stgmed_for_emf((HENHMETAFILE)h, med); else { FIXME("Unhandled tymed - mask %x req tymed %x\n", mask, fmt->tymed);
Modified: trunk/reactos/dll/win32/ole32/comcat.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/comcat.c?re... ============================================================================== --- trunk/reactos/dll/win32/ole32/comcat.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/comcat.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -278,7 +278,7 @@ LPVOID *ppvObj) { ComCatMgrImpl *This = (ComCatMgrImpl *)iface; - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); + TRACE("%s\n",debugstr_guid(riid));
if (ppvObj == NULL) return E_POINTER;
@@ -515,7 +515,7 @@ HKEY key; HRESULT res;
- TRACE("\n\tCATID:\t%s\n\tLCID:\t%X\n",debugstr_guid(rcatid), lcid); + TRACE("CATID: %s LCID: %x\n",debugstr_guid(rcatid), lcid);
if (rcatid == NULL || ppszDesc == NULL) return E_INVALIDARG;
@@ -596,12 +596,12 @@
if (WINE_TRACE_ON(ole)) { ULONG count; - TRACE("\n\tCLSID:\t%s\n\tImplemented %u\n",debugstr_guid(rclsid),cImplemented); + TRACE("CLSID: %s Implemented %u\n",debugstr_guid(rclsid),cImplemented); for (count = 0; count < cImplemented; ++count) - TRACE("\t\t%s\n",debugstr_guid(&rgcatidImpl[count])); - TRACE("\tRequired %u\n",cRequired); + TRACE(" %s\n",debugstr_guid(&rgcatidImpl[count])); + TRACE("Required %u\n",cRequired); for (count = 0; count < cRequired; ++count) - TRACE("\t\t%s\n",debugstr_guid(&rgcatidReq[count])); + TRACE(" %s\n",debugstr_guid(&rgcatidReq[count])); }
if ((cImplemented && rgcatidImpl == NULL) || @@ -637,7 +637,7 @@ 'n', 't', 'e', 'd', ' ', 'C', 'a', 't', 'e', 'g', 'o', 'r', 'i', 'e', 's', 0 };
- TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid)); + TRACE("%s\n",debugstr_guid(rclsid));
if (rclsid == NULL || ppenumCATID == NULL) return E_POINTER; @@ -659,7 +659,7 @@ 'd', ' ', 'C', 'a', 't', 'e', 'g', 'o', 'r', 'i', 'e', 's', 0 };
- TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid)); + TRACE("%s\n",debugstr_guid(rclsid));
if (rclsid == NULL || ppenumCATID == NULL) return E_POINTER; @@ -719,7 +719,7 @@ REFIID riid, LPVOID *ppvObj) { - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); + TRACE("%s\n",debugstr_guid(riid));
if (ppvObj == NULL) return E_POINTER;
@@ -760,7 +760,7 @@ LPVOID *ppvObj) { HRESULT res; - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); + TRACE("%s\n",debugstr_guid(riid));
if (ppvObj == NULL) return E_POINTER;
@@ -834,7 +834,7 @@ REFIID riid, LPVOID *ppvObj) { - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); + TRACE("%s\n",debugstr_guid(riid));
if (ppvObj == NULL) return E_POINTER;
@@ -1017,7 +1017,7 @@ REFIID riid, LPVOID *ppvObj) { - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); + TRACE("%s\n",debugstr_guid(riid));
if (ppvObj == NULL) return E_POINTER;
@@ -1203,7 +1203,7 @@ REFIID riid, LPVOID *ppvObj) { - TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); + TRACE("%s\n",debugstr_guid(riid));
if (ppvObj == NULL) return E_POINTER;
Modified: trunk/reactos/dll/win32/ole32/compobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/compobj.c?r... ============================================================================== --- trunk/reactos/dll/win32/ole32/compobj.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/compobj.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -52,6 +52,7 @@ #include "winerror.h" #include "winreg.h" #include "winuser.h" +#define USE_COM_CONTEXT_DEF #include "objbase.h" #include "ole2.h" #include "ole2ver.h" @@ -70,11 +71,6 @@ /**************************************************************************** * This section defines variables internal to the COM module. */ - -static HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid, - DWORD dwClsContext, LPUNKNOWN* ppUnk); -static void COM_RevokeAllClasses(const struct apartment *apt); -static HRESULT get_inproc_class_object(APARTMENT *apt, HKEY hkeydll, REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv);
static APARTMENT *MTA; /* protected by csApartment */ static APARTMENT *MainApartment; /* the first STA apartment */ @@ -182,60 +178,146 @@
static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',' ', '0','x','#','#','#','#','#','#','#','#',' ',0}; -static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, - BOOL apartment_threaded, - REFCLSID rclsid, REFIID riid, void **ppv); -static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay); - -static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret); -static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name); -static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry); - -static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen); - -static void COMPOBJ_InitProcess( void ) -{ - WNDCLASSW wclass; - - /* Dispatching to the correct thread in an apartment is done through - * window messages rather than RPC transports. When an interface is - * marshalled into another apartment in the same process, a window of the - * following class is created. The *caller* of CoMarshalInterface (i.e., the - * application) is responsible for pumping the message loop in that thread. - * The WM_USER messages which point to the RPCs are then dispatched to - * apartment_wndproc by the user's code from the apartment in which the - * interface was unmarshalled. - */ - memset(&wclass, 0, sizeof(wclass)); - wclass.lpfnWndProc = apartment_wndproc; - wclass.hInstance = hProxyDll; - wclass.lpszClassName = wszAptWinClass; - RegisterClassW(&wclass); -} - -static void COMPOBJ_UninitProcess( void ) -{ - UnregisterClassW(wszAptWinClass, hProxyDll); -} - -static void COM_TlsDestroy(void) -{ - struct oletls *info = NtCurrentTeb()->ReservedForOle; - if (info) - { - if (info->apt) apartment_release(info->apt); - if (info->errorinfo) IErrorInfo_Release(info->errorinfo); - if (info->state) IUnknown_Release(info->state); - if (info->spy) IUnknown_Release(info->spy); - HeapFree(GetProcessHeap(), 0, info); - NtCurrentTeb()->ReservedForOle = NULL; - } + +/***************************************************************************** + * This section contains OpenDllList implementation + */ + +static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name) +{ + OpenDll *ptr; + OpenDll *ret = NULL; + EnterCriticalSection(&csOpenDllList); + LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry) + { + if (!strcmpiW(library_name, ptr->library_name) && + (InterlockedIncrement(&ptr->refs) != 1) /* entry is being destroy if == 1 */) + { + ret = ptr; + break; + } + } + LeaveCriticalSection(&csOpenDllList); + return ret; +} + +/* caller must ensure that library_name is not already in the open dll list */ +static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret) +{ + OpenDll *entry; + int len; + HRESULT hr = S_OK; + HANDLE hLibrary; + DllCanUnloadNowFunc DllCanUnloadNow; + DllGetClassObjectFunc DllGetClassObject; + + TRACE("\n"); + + *ret = COMPOBJ_DllList_Get(library_name); + if (*ret) return S_OK; + + /* do this outside the csOpenDllList to avoid creating a lock dependency on + * the loader lock */ + hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hLibrary) + { + ERR("couldn't load in-process dll %s\n", debugstr_w(library_name)); + /* failure: DLL could not be loaded */ + return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */ + } + + DllCanUnloadNow = (void *)GetProcAddress(hLibrary, "DllCanUnloadNow"); + /* Note: failing to find DllCanUnloadNow is not a failure */ + DllGetClassObject = (void *)GetProcAddress(hLibrary, "DllGetClassObject"); + if (!DllGetClassObject) + { + /* failure: the dll did not export DllGetClassObject */ + ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name)); + FreeLibrary(hLibrary); + return CO_E_DLLNOTFOUND; + } + + EnterCriticalSection( &csOpenDllList ); + + *ret = COMPOBJ_DllList_Get(library_name); + if (*ret) + { + /* another caller to this function already added the dll while we + * weren't in the critical section */ + FreeLibrary(hLibrary); + } + else + { + len = strlenW(library_name); + entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll)); + if (entry) + entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR)); + if (entry && entry->library_name) + { + memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR)); + entry->library = hLibrary; + entry->refs = 1; + entry->DllCanUnloadNow = DllCanUnloadNow; + entry->DllGetClassObject = DllGetClassObject; + list_add_tail(&openDllList, &entry->entry); + } + else + { + HeapFree(GetProcessHeap(), 0, entry); + hr = E_OUTOFMEMORY; + FreeLibrary(hLibrary); + } + *ret = entry; + } + + LeaveCriticalSection( &csOpenDllList ); + + return hr; +} + +/* pass FALSE for free_entry to release a reference without destroying the + * entry if it reaches zero or TRUE otherwise */ +static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry) +{ + if (!InterlockedDecrement(&entry->refs) && free_entry) + { + EnterCriticalSection(&csOpenDllList); + list_remove(&entry->entry); + LeaveCriticalSection(&csOpenDllList); + + TRACE("freeing %p\n", entry->library); + FreeLibrary(entry->library); + + HeapFree(GetProcessHeap(), 0, entry->library_name); + HeapFree(GetProcessHeap(), 0, entry); + } +} + +/* frees memory associated with active dll list */ +static void COMPOBJ_DllList_Free(void) +{ + OpenDll *entry, *cursor2; + EnterCriticalSection(&csOpenDllList); + LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &openDllList, OpenDll, entry) + { + list_remove(&entry->entry); + + HeapFree(GetProcessHeap(), 0, entry->library_name); + HeapFree(GetProcessHeap(), 0, entry); + } + LeaveCriticalSection(&csOpenDllList); }
/****************************************************************************** * Manage apartments. */ + +static DWORD apartment_addref(struct apartment *apt) +{ + DWORD refs = InterlockedIncrement(&apt->refs); + TRACE("%s: before = %d\n", wine_dbgstr_longlong(apt->oxid), refs - 1); + return refs; +}
/* allocates memory and fills in the necessary fields for a new apartment * object. must be called inside apartment cs */ @@ -335,11 +417,146 @@ return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED)); }
-DWORD apartment_addref(struct apartment *apt) -{ - DWORD refs = InterlockedIncrement(&apt->refs); - TRACE("%s: before = %d\n", wine_dbgstr_longlong(apt->oxid), refs - 1); - return refs; +static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass) +{ + list_remove(&curClass->entry); + + if (curClass->runContext & CLSCTX_LOCAL_SERVER) + RPC_StopLocalServer(curClass->RpcRegistration); + + /* + * Release the reference to the class object. + */ + IUnknown_Release(curClass->classObject); + + if (curClass->pMarshaledData) + { + LARGE_INTEGER zero; + memset(&zero, 0, sizeof(zero)); + IStream_Seek(curClass->pMarshaledData, zero, STREAM_SEEK_SET, NULL); + CoReleaseMarshalData(curClass->pMarshaledData); + IStream_Release(curClass->pMarshaledData); + } + + HeapFree(GetProcessHeap(), 0, curClass); +} + +static void COM_RevokeAllClasses(const struct apartment *apt) +{ + RegisteredClass *curClass, *cursor; + + EnterCriticalSection( &csRegisteredClassList ); + + LIST_FOR_EACH_ENTRY_SAFE(curClass, cursor, &RegisteredClassList, RegisteredClass, entry) + { + if (curClass->apartment_id == apt->oxid) + COM_RevokeRegisteredClassObject(curClass); + } + + LeaveCriticalSection( &csRegisteredClassList ); +} + +/*********************************************************************** + * CoRevokeClassObject [OLE32.@] + * + * Removes a class object from the class registry. + * + * PARAMS + * dwRegister [I] Cookie returned from CoRegisterClassObject(). + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. + * + * NOTES + * Must be called from the same apartment that called CoRegisterClassObject(), + * otherwise it will fail with RPC_E_WRONG_THREAD. + * + * SEE ALSO + * CoRegisterClassObject + */ +HRESULT WINAPI CoRevokeClassObject( + DWORD dwRegister) +{ + HRESULT hr = E_INVALIDARG; + RegisteredClass *curClass; + APARTMENT *apt; + + TRACE("(%08x)\n",dwRegister); + + apt = COM_CurrentApt(); + if (!apt) + { + ERR("COM was not initialized\n"); + return CO_E_NOTINITIALIZED; + } + + EnterCriticalSection( &csRegisteredClassList ); + + LIST_FOR_EACH_ENTRY(curClass, &RegisteredClassList, RegisteredClass, entry) + { + /* + * Check if we have a match on the cookie. + */ + if (curClass->dwCookie == dwRegister) + { + if (curClass->apartment_id == apt->oxid) + { + COM_RevokeRegisteredClassObject(curClass); + hr = S_OK; + } + else + { + ERR("called from wrong apartment, should be called from %s\n", + wine_dbgstr_longlong(curClass->apartment_id)); + hr = RPC_E_WRONG_THREAD; + } + break; + } + } + + LeaveCriticalSection( &csRegisteredClassList ); + + return hr; +} + +/* frees unused libraries loaded by apartment_getclassobject by calling the + * DLL's DllCanUnloadNow entry point */ +static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay) +{ + struct apartment_loaded_dll *entry, *next; + EnterCriticalSection(&apt->cs); + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry) + { + if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK)) + { + DWORD real_delay = delay; + + if (real_delay == INFINITE) + { + /* DLLs that return multi-threaded objects aren't unloaded + * straight away to cope for programs that have races between + * last object destruction and threads in the DLLs that haven't + * finished, despite DllCanUnloadNow returning S_OK */ + if (entry->multi_threaded) + real_delay = 10 * 60 * 1000; /* 10 minutes */ + else + real_delay = 0; + } + + if (!real_delay || (entry->unload_time && (entry->unload_time < GetTickCount()))) + { + list_remove(&entry->entry); + COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); + HeapFree(GetProcessHeap(), 0, entry); + } + else + entry->unload_time = GetTickCount() + real_delay; + } + else if (entry->unload_time) + entry->unload_time = 0; + } + LeaveCriticalSection(&apt->cs); }
DWORD apartment_release(struct apartment *apt) @@ -517,6 +734,106 @@
LeaveCriticalSection(&csApartment); return result; +} + +/* gets the specified class object by loading the appropriate DLL, if + * necessary and calls the DllGetClassObject function for the DLL */ +static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, + BOOL apartment_threaded, + REFCLSID rclsid, REFIID riid, void **ppv) +{ + static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0}; + HRESULT hr = S_OK; + BOOL found = FALSE; + struct apartment_loaded_dll *apartment_loaded_dll; + + if (!strcmpiW(dllpath, wszOle32)) + { + /* we don't need to control the lifetime of this dll, so use the local + * implementation of DllGetClassObject directly */ + TRACE("calling ole32!DllGetClassObject\n"); + hr = DllGetClassObject(rclsid, riid, ppv); + + if (hr != S_OK) + ERR("DllGetClassObject returned error 0x%08x\n", hr); + + return hr; + } + + EnterCriticalSection(&apt->cs); + + LIST_FOR_EACH_ENTRY(apartment_loaded_dll, &apt->loaded_dlls, struct apartment_loaded_dll, entry) + if (!strcmpiW(dllpath, apartment_loaded_dll->dll->library_name)) + { + TRACE("found %s already loaded\n", debugstr_w(dllpath)); + found = TRUE; + break; + } + + if (!found) + { + apartment_loaded_dll = HeapAlloc(GetProcessHeap(), 0, sizeof(*apartment_loaded_dll)); + if (!apartment_loaded_dll) + hr = E_OUTOFMEMORY; + if (SUCCEEDED(hr)) + { + apartment_loaded_dll->unload_time = 0; + apartment_loaded_dll->multi_threaded = FALSE; + hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll ); + if (FAILED(hr)) + HeapFree(GetProcessHeap(), 0, apartment_loaded_dll); + } + if (SUCCEEDED(hr)) + { + TRACE("added new loaded dll %s\n", debugstr_w(dllpath)); + list_add_tail(&apt->loaded_dlls, &apartment_loaded_dll->entry); + } + } + + LeaveCriticalSection(&apt->cs); + + if (SUCCEEDED(hr)) + { + /* one component being multi-threaded overrides any number of + * apartment-threaded components */ + if (!apartment_threaded) + apartment_loaded_dll->multi_threaded = TRUE; + + TRACE("calling DllGetClassObject %p\n", apartment_loaded_dll->dll->DllGetClassObject); + /* OK: get the ClassObject */ + hr = apartment_loaded_dll->dll->DllGetClassObject(rclsid, riid, ppv); + + if (hr != S_OK) + ERR("DllGetClassObject returned error 0x%08x\n", hr); + } + + return hr; +} + +/*********************************************************************** + * COM_RegReadPath [internal] + * + * Reads a registry value and expands it when necessary + */ +static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen) +{ + DWORD ret; + HKEY key; + DWORD keytype; + WCHAR src[MAX_PATH]; + DWORD dwLength = dstlen * sizeof(WCHAR); + + if((ret = RegOpenKeyExW(hkeyroot, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) { + if( (ret = RegQueryValueExW(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) { + if (keytype == REG_EXPAND_SZ) { + if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) ret = ERROR_MORE_DATA; + } else { + lstrcpynW(dst, src, dstlen); + } + } + RegCloseKey (key); + } + return ret; }
struct host_object_params @@ -781,246 +1098,44 @@ COM_CurrentInfo()->apt = MTA; }
-/* gets the specified class object by loading the appropriate DLL, if - * necessary and calls the DllGetClassObject function for the DLL */ -static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, - BOOL apartment_threaded, - REFCLSID rclsid, REFIID riid, void **ppv) -{ - static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0}; - HRESULT hr = S_OK; - BOOL found = FALSE; - struct apartment_loaded_dll *apartment_loaded_dll; - - if (!strcmpiW(dllpath, wszOle32)) - { - /* we don't need to control the lifetime of this dll, so use the local - * implementation of DllGetClassObject directly */ - TRACE("calling ole32!DllGetClassObject\n"); - hr = DllGetClassObject(rclsid, riid, ppv); - - if (hr != S_OK) - ERR("DllGetClassObject returned error 0x%08x\n", hr); - - return hr; - } - - EnterCriticalSection(&apt->cs); - - LIST_FOR_EACH_ENTRY(apartment_loaded_dll, &apt->loaded_dlls, struct apartment_loaded_dll, entry) - if (!strcmpiW(dllpath, apartment_loaded_dll->dll->library_name)) - { - TRACE("found %s already loaded\n", debugstr_w(dllpath)); - found = TRUE; - break; - } - - if (!found) - { - apartment_loaded_dll = HeapAlloc(GetProcessHeap(), 0, sizeof(*apartment_loaded_dll)); - if (!apartment_loaded_dll) - hr = E_OUTOFMEMORY; - if (SUCCEEDED(hr)) - { - apartment_loaded_dll->unload_time = 0; - apartment_loaded_dll->multi_threaded = FALSE; - hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll ); - if (FAILED(hr)) - HeapFree(GetProcessHeap(), 0, apartment_loaded_dll); - } - if (SUCCEEDED(hr)) - { - TRACE("added new loaded dll %s\n", debugstr_w(dllpath)); - list_add_tail(&apt->loaded_dlls, &apartment_loaded_dll->entry); - } - } - - LeaveCriticalSection(&apt->cs); - - if (SUCCEEDED(hr)) - { - /* one component being multi-threaded overrides any number of - * apartment-threaded components */ - if (!apartment_threaded) - apartment_loaded_dll->multi_threaded = TRUE; - - TRACE("calling DllGetClassObject %p\n", apartment_loaded_dll->dll->DllGetClassObject); - /* OK: get the ClassObject */ - hr = apartment_loaded_dll->dll->DllGetClassObject(rclsid, riid, ppv); - - if (hr != S_OK) - ERR("DllGetClassObject returned error 0x%08x\n", hr); - } - - return hr; -} - -/* frees unused libraries loaded by apartment_getclassobject by calling the - * DLL's DllCanUnloadNow entry point */ -static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay) -{ - struct apartment_loaded_dll *entry, *next; - EnterCriticalSection(&apt->cs); - LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry) - { - if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK)) - { - DWORD real_delay = delay; - - if (real_delay == INFINITE) - { - /* DLLs that return multi-threaded objects aren't unloaded - * straight away to cope for programs that have races between - * last object destruction and threads in the DLLs that haven't - * finished, despite DllCanUnloadNow returning S_OK */ - if (entry->multi_threaded) - real_delay = 10 * 60 * 1000; /* 10 minutes */ - else - real_delay = 0; - } - - if (!real_delay || (entry->unload_time && (entry->unload_time < GetTickCount()))) - { - list_remove(&entry->entry); - COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); - HeapFree(GetProcessHeap(), 0, entry); - } - else - entry->unload_time = GetTickCount() + real_delay; - } - else if (entry->unload_time) - entry->unload_time = 0; - } - LeaveCriticalSection(&apt->cs); -} - -/***************************************************************************** - * This section contains OpenDllList implementation - */ - -/* caller must ensure that library_name is not already in the open dll list */ -static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret) -{ - OpenDll *entry; - int len; - HRESULT hr = S_OK; - HANDLE hLibrary; - DllCanUnloadNowFunc DllCanUnloadNow; - DllGetClassObjectFunc DllGetClassObject; - - TRACE("\n"); - - *ret = COMPOBJ_DllList_Get(library_name); - if (*ret) return S_OK; - - /* do this outside the csOpenDllList to avoid creating a lock dependency on - * the loader lock */ - hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!hLibrary) - { - ERR("couldn't load in-process dll %s\n", debugstr_w(library_name)); - /* failure: DLL could not be loaded */ - return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */ - } - - DllCanUnloadNow = (void *)GetProcAddress(hLibrary, "DllCanUnloadNow"); - /* Note: failing to find DllCanUnloadNow is not a failure */ - DllGetClassObject = (void *)GetProcAddress(hLibrary, "DllGetClassObject"); - if (!DllGetClassObject) - { - /* failure: the dll did not export DllGetClassObject */ - ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name)); - FreeLibrary(hLibrary); - return CO_E_DLLNOTFOUND; - } - - EnterCriticalSection( &csOpenDllList ); - - *ret = COMPOBJ_DllList_Get(library_name); - if (*ret) - { - /* another caller to this function already added the dll while we - * weren't in the critical section */ - FreeLibrary(hLibrary); - } - else - { - len = strlenW(library_name); - entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll)); - if (entry) - entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR)); - if (entry && entry->library_name) - { - memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR)); - entry->library = hLibrary; - entry->refs = 1; - entry->DllCanUnloadNow = DllCanUnloadNow; - entry->DllGetClassObject = DllGetClassObject; - list_add_tail(&openDllList, &entry->entry); - } - else - { - HeapFree(GetProcessHeap(), 0, entry); - hr = E_OUTOFMEMORY; - FreeLibrary(hLibrary); - } - *ret = entry; - } - - LeaveCriticalSection( &csOpenDllList ); - - return hr; -} - -static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name) -{ - OpenDll *ptr; - OpenDll *ret = NULL; - EnterCriticalSection(&csOpenDllList); - LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry) - { - if (!strcmpiW(library_name, ptr->library_name) && - (InterlockedIncrement(&ptr->refs) != 1) /* entry is being destroy if == 1 */) - { - ret = ptr; - break; - } - } - LeaveCriticalSection(&csOpenDllList); - return ret; -} - -/* pass FALSE for free_entry to release a reference without destroying the - * entry if it reaches zero or TRUE otherwise */ -static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry) -{ - if (!InterlockedDecrement(&entry->refs) && free_entry) - { - EnterCriticalSection(&csOpenDllList); - list_remove(&entry->entry); - LeaveCriticalSection(&csOpenDllList); - - TRACE("freeing %p\n", entry->library); - FreeLibrary(entry->library); - - HeapFree(GetProcessHeap(), 0, entry->library_name); - HeapFree(GetProcessHeap(), 0, entry); - } -} - -/* frees memory associated with active dll list */ -static void COMPOBJ_DllList_Free(void) -{ - OpenDll *entry, *cursor2; - EnterCriticalSection(&csOpenDllList); - LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &openDllList, OpenDll, entry) - { - list_remove(&entry->entry); - - HeapFree(GetProcessHeap(), 0, entry->library_name); - HeapFree(GetProcessHeap(), 0, entry); - } - LeaveCriticalSection(&csOpenDllList); +static void COMPOBJ_InitProcess( void ) +{ + WNDCLASSW wclass; + + /* Dispatching to the correct thread in an apartment is done through + * window messages rather than RPC transports. When an interface is + * marshalled into another apartment in the same process, a window of the + * following class is created. The *caller* of CoMarshalInterface (i.e., the + * application) is responsible for pumping the message loop in that thread. + * The WM_USER messages which point to the RPCs are then dispatched to + * apartment_wndproc by the user's code from the apartment in which the + * interface was unmarshalled. + */ + memset(&wclass, 0, sizeof(wclass)); + wclass.lpfnWndProc = apartment_wndproc; + wclass.hInstance = hProxyDll; + wclass.lpszClassName = wszAptWinClass; + RegisterClassW(&wclass); +} + +static void COMPOBJ_UninitProcess( void ) +{ + UnregisterClassW(wszAptWinClass, hProxyDll); +} + +static void COM_TlsDestroy(void) +{ + struct oletls *info = NtCurrentTeb()->ReservedForOle; + if (info) + { + if (info->apt) apartment_release(info->apt); + if (info->errorinfo) IErrorInfo_Release(info->errorinfo); + if (info->state) IUnknown_Release(info->state); + if (info->spy) IUnknown_Release(info->spy); + if (info->context_token) IObjContext_Release(info->context_token); + HeapFree(GetProcessHeap(), 0, info); + NtCurrentTeb()->ReservedForOle = NULL; + } }
/****************************************************************************** @@ -2031,135 +2146,6 @@ return S_OK; }
-static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass) -{ - list_remove(&curClass->entry); - - if (curClass->runContext & CLSCTX_LOCAL_SERVER) - RPC_StopLocalServer(curClass->RpcRegistration); - - /* - * Release the reference to the class object. - */ - IUnknown_Release(curClass->classObject); - - if (curClass->pMarshaledData) - { - LARGE_INTEGER zero; - memset(&zero, 0, sizeof(zero)); - IStream_Seek(curClass->pMarshaledData, zero, STREAM_SEEK_SET, NULL); - CoReleaseMarshalData(curClass->pMarshaledData); - IStream_Release(curClass->pMarshaledData); - } - - HeapFree(GetProcessHeap(), 0, curClass); -} - -static void COM_RevokeAllClasses(const struct apartment *apt) -{ - RegisteredClass *curClass, *cursor; - - EnterCriticalSection( &csRegisteredClassList ); - - LIST_FOR_EACH_ENTRY_SAFE(curClass, cursor, &RegisteredClassList, RegisteredClass, entry) - { - if (curClass->apartment_id == apt->oxid) - COM_RevokeRegisteredClassObject(curClass); - } - - LeaveCriticalSection( &csRegisteredClassList ); -} - -/*********************************************************************** - * CoRevokeClassObject [OLE32.@] - * - * Removes a class object from the class registry. - * - * PARAMS - * dwRegister [I] Cookie returned from CoRegisterClassObject(). - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT code. - * - * NOTES - * Must be called from the same apartment that called CoRegisterClassObject(), - * otherwise it will fail with RPC_E_WRONG_THREAD. - * - * SEE ALSO - * CoRegisterClassObject - */ -HRESULT WINAPI CoRevokeClassObject( - DWORD dwRegister) -{ - HRESULT hr = E_INVALIDARG; - RegisteredClass *curClass; - APARTMENT *apt; - - TRACE("(%08x)\n",dwRegister); - - apt = COM_CurrentApt(); - if (!apt) - { - ERR("COM was not initialized\n"); - return CO_E_NOTINITIALIZED; - } - - EnterCriticalSection( &csRegisteredClassList ); - - LIST_FOR_EACH_ENTRY(curClass, &RegisteredClassList, RegisteredClass, entry) - { - /* - * Check if we have a match on the cookie. - */ - if (curClass->dwCookie == dwRegister) - { - if (curClass->apartment_id == apt->oxid) - { - COM_RevokeRegisteredClassObject(curClass); - hr = S_OK; - } - else - { - ERR("called from wrong apartment, should be called from %s\n", - wine_dbgstr_longlong(curClass->apartment_id)); - hr = RPC_E_WRONG_THREAD; - } - break; - } - } - - LeaveCriticalSection( &csRegisteredClassList ); - - return hr; -} - -/*********************************************************************** - * COM_RegReadPath [internal] - * - * Reads a registry value and expands it when necessary - */ -static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen) -{ - DWORD ret; - HKEY key; - DWORD keytype; - WCHAR src[MAX_PATH]; - DWORD dwLength = dstlen * sizeof(WCHAR); - - if((ret = RegOpenKeyExW(hkeyroot, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) { - if( (ret = RegQueryValueExW(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) { - if (keytype == REG_EXPAND_SZ) { - if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) ret = ERROR_MORE_DATA; - } else { - lstrcpynW(dst, src, dstlen); - } - } - RegCloseKey (key); - } - return ret; -} - static void get_threading_model(HKEY key, LPWSTR value, DWORD len) { static const WCHAR wszThreadingModel[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; @@ -2265,7 +2251,7 @@ APARTMENT *apt; BOOL release_apt = FALSE;
- TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); + TRACE("CLSID: %s,IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid));
if (!ppv) return E_INVALIDARG; @@ -2283,8 +2269,8 @@ }
if (pServerInfo) { - FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName)); - FIXME("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo); + FIXME("pServerInfo->name=%s pAuthInfo=%p\n", + debugstr_w(pServerInfo->pwszName), pServerInfo->pAuthInfo); }
/* @@ -3748,6 +3734,7 @@ { const IComThreadingInfoVtbl *lpVtbl; const IContextCallbackVtbl *lpCallbackVtbl; + const IObjContextVtbl *lpContextVtbl; LONG refs; APTTYPE apttype; } Context; @@ -3762,6 +3749,11 @@ return (Context *)((char*)iface - FIELD_OFFSET(Context, lpCallbackVtbl)); }
+static inline Context *impl_from_IObjContext( IObjContext *iface ) +{ + return (Context *)((char*)iface - FIELD_OFFSET(Context, lpContextVtbl)); +} + static HRESULT Context_QueryInterface(Context *iface, REFIID riid, LPVOID *ppv) { *ppv = NULL; @@ -3770,9 +3762,14 @@ IsEqualIID(riid, &IID_IUnknown)) { *ppv = &iface->lpVtbl; - } else if (IsEqualIID(riid, &IID_IContextCallback)) + } + else if (IsEqualIID(riid, &IID_IContextCallback)) { *ppv = &iface->lpCallbackVtbl; + } + else if (IsEqualIID(riid, &IID_IObjContext)) + { + *ppv = &iface->lpContextVtbl; }
if (*ppv) @@ -3903,6 +3900,115 @@ Context_CC_ContextCallback };
+static HRESULT WINAPI Context_OC_QueryInterface(IObjContext *iface, REFIID riid, LPVOID *ppv) +{ + Context *This = impl_from_IObjContext(iface); + return Context_QueryInterface(This, riid, ppv); +} + +static ULONG WINAPI Context_OC_AddRef(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + return Context_AddRef(This); +} + +static ULONG WINAPI Context_OC_Release(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + return Context_Release(This); +} + +static HRESULT WINAPI Context_OC_SetProperty(IObjContext *iface, REFGUID propid, CPFLAGS flags, IUnknown *punk) +{ + Context *This = impl_from_IObjContext(iface); + + FIXME("(%p/%p)->(%s, %x, %p)\n", This, iface, debugstr_guid(propid), flags, punk); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_OC_RemoveProperty(IObjContext *iface, REFGUID propid) +{ + Context *This = impl_from_IObjContext(iface); + + FIXME("(%p/%p)->(%s)\n", This, iface, debugstr_guid(propid)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_OC_GetProperty(IObjContext *iface, REFGUID propid, CPFLAGS *flags, IUnknown **punk) +{ + Context *This = impl_from_IObjContext(iface); + + FIXME("(%p/%p)->(%s, %p, %p)\n", This, iface, debugstr_guid(propid), flags, punk); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_OC_EnumContextProps(IObjContext *iface, IEnumContextProps **props) +{ + Context *This = impl_from_IObjContext(iface); + + FIXME("(%p/%p)->(%p)\n", This, iface, props); + return E_NOTIMPL; +} + +static void WINAPI Context_OC_Reserved1(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static void WINAPI Context_OC_Reserved2(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static void WINAPI Context_OC_Reserved3(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static void WINAPI Context_OC_Reserved4(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static void WINAPI Context_OC_Reserved5(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static void WINAPI Context_OC_Reserved6(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static void WINAPI Context_OC_Reserved7(IObjContext *iface) +{ + Context *This = impl_from_IObjContext(iface); + FIXME("(%p/%p)\n", This, iface); +} + +static const IObjContextVtbl Context_Object_Vtbl = +{ + Context_OC_QueryInterface, + Context_OC_AddRef, + Context_OC_Release, + Context_OC_SetProperty, + Context_OC_RemoveProperty, + Context_OC_GetProperty, + Context_OC_EnumContextProps, + Context_OC_Reserved1, + Context_OC_Reserved2, + Context_OC_Reserved3, + Context_OC_Reserved4, + Context_OC_Reserved5, + Context_OC_Reserved6, + Context_OC_Reserved7 +};
/*********************************************************************** * CoGetObjectContext [OLE32.@] @@ -3928,8 +4034,12 @@ *ppv = NULL; if (!apt) { - ERR("apartment not initialised\n"); - return CO_E_NOTINITIALIZED; + if (!(apt = apartment_find_multi_threaded())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + apartment_release(apt); }
context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context)); @@ -3938,6 +4048,7 @@
context->lpVtbl = &Context_Threading_Vtbl; context->lpCallbackVtbl = &Context_Callback_Vtbl; + context->lpContextVtbl = &Context_Object_Vtbl; context->refs = 1; if (apt->multi_threaded) context->apttype = APTTYPE_MTA; @@ -3959,12 +4070,40 @@ HRESULT WINAPI CoGetContextToken( ULONG_PTR *token ) { struct oletls *info = COM_CurrentInfo(); - static int calls; - if(!(calls++)) FIXME( "stub\n" ); + + TRACE("(%p)\n", token); + if (!info) return E_OUTOFMEMORY; - if (token) *token = info->context_token; - return E_NOTIMPL; + + if (!info->apt) + { + APARTMENT *apt; + if (!(apt = apartment_find_multi_threaded())) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + apartment_release(apt); + } + + if (!token) + return E_POINTER; + + if (!info->context_token) + { + HRESULT hr; + IObjContext *ctx; + + hr = CoGetObjectContext(&IID_IObjContext, (void **)&ctx); + if (FAILED(hr)) return hr; + info->context_token = ctx; + } + + *token = (ULONG_PTR)info->context_token; + TRACE("apt->context_token=%p\n", info->context_token); + + return S_OK; }
Modified: trunk/reactos/dll/win32/ole32/compobj_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/compobj_pri... ============================================================================== --- trunk/reactos/dll/win32/ole32/compobj_private.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/compobj_private.h [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -183,7 +183,7 @@ LONG pending_call_count_client; /* number of client calls pending */ LONG pending_call_count_server; /* number of server calls pending */ DWORD unknown; - ULONG_PTR context_token; /* (+38h on x86) */ + IObjContext *context_token; /* (+38h on x86) */ IUnknown *call_state; /* current call context (+3Ch on x86) */ DWORD unknown2[46]; IUnknown *cancel_object; /* cancel object set by CoSetCancelObject (+F8h on x86) */ @@ -203,7 +203,6 @@
/* Stub Manager */
-ULONG stub_manager_int_addref(struct stub_manager *This); ULONG stub_manager_int_release(struct stub_manager *This); struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object); ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak); @@ -253,7 +252,6 @@
APARTMENT *apartment_findfromoxid(OXID oxid, BOOL ref); APARTMENT *apartment_findfromtid(DWORD tid); -DWORD apartment_addref(struct apartment *apt); DWORD apartment_release(struct apartment *apt); HRESULT apartment_disconnectproxies(struct apartment *apt); void apartment_disconnectobject(struct apartment *apt, void *object);
Modified: trunk/reactos/dll/win32/ole32/defaulthandler.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/defaulthand... ============================================================================== --- trunk/reactos/dll/win32/ole32/defaulthandler.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/defaulthandler.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -137,6 +137,11 @@ /* storage passed to Load or InitNew */ IStorage *storage; enum storage_state storage_state; + + /* optional class factory for object */ + IClassFactory *pCFObject; + /* TRUE if acting as an inproc server instead of an inproc handler */ + BOOL inproc_server; };
typedef struct DefaultHandler DefaultHandler; @@ -222,6 +227,12 @@ HRESULT hr = IUnknown_QueryInterface(This->dataCache, riid, ppvObject); if (FAILED(hr)) FIXME("interface %s not implemented by data cache\n", debugstr_guid(riid)); return hr; + } + else if (This->inproc_server && This->pOleDelegate) + { + HRESULT hr = IUnknown_QueryInterface(This->pOleDelegate, riid, ppvObject); + if (SUCCEEDED(hr)) + return hr; }
/* Check that we obtained an interface. */ @@ -1901,7 +1912,9 @@ */ static DefaultHandler* DefaultHandler_Construct( REFCLSID clsid, - LPUNKNOWN pUnkOuter) + LPUNKNOWN pUnkOuter, + DWORD flags, + IClassFactory *pCF) { DefaultHandler* This = NULL; HRESULT hr; @@ -1917,6 +1930,8 @@ This->lpvtblIRunnableObject = &DefaultHandler_IRunnableObject_VTable; This->lpvtblIAdviseSink = &DefaultHandler_IAdviseSink_VTable; This->lpvtblIPersistStorage = &DefaultHandler_IPersistStorage_VTable; + + This->inproc_server = (flags & EMBDHLP_INPROC_SERVER) ? TRUE : FALSE;
/* * Start with one reference count. The caller of this function @@ -1964,6 +1979,30 @@ This->storage = NULL; This->storage_state = storage_state_uninitialised;
+ if (This->inproc_server && !(flags & EMBDHLP_DELAYCREATE)) + { + HRESULT hr; + This->pCFObject = NULL; + if (pCF) + hr = IClassFactory_CreateInstance(pCF, NULL, &IID_IOleObject, (void **)&This->pOleDelegate); + else + hr = CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IOleObject, (void **)&This->pOleDelegate); + if (SUCCEEDED(hr)) + hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage, (void **)&This->pPSDelegate); + if (SUCCEEDED(hr)) + hr = IOleObject_QueryInterface(This->pOleDelegate, &IID_IDataObject, (void **)&This->pDataDelegate); + if (SUCCEEDED(hr)) + This->object_state = object_state_running; + if (FAILED(hr)) + WARN("object creation failed with error %08x\n", hr); + } + else + { + This->pCFObject = pCF; + if (pCF) IClassFactory_AddRef(pCF); + } + return This; }
@@ -2011,22 +2050,30 @@ This->storage = NULL; }
+ if (This->pCFObject) + { + IClassFactory_Release(This->pCFObject); + This->pCFObject = NULL; + } + HeapFree(GetProcessHeap(), 0, This); }
/****************************************************************************** - * OleCreateDefaultHandler [OLE32.@] - */ -HRESULT WINAPI OleCreateDefaultHandler( + * OleCreateEmbeddingHelper [OLE32.@] + */ +HRESULT WINAPI OleCreateEmbeddingHelper( REFCLSID clsid, LPUNKNOWN pUnkOuter, + DWORD flags, + IClassFactory *pCF, REFIID riid, LPVOID* ppvObj) { DefaultHandler* newHandler = NULL; HRESULT hr = S_OK;
- TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, debugstr_guid(riid), ppvObj); + TRACE("(%s, %p, %08x, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, flags, pCF, debugstr_guid(riid), ppvObj);
if (!ppvObj) return E_POINTER; @@ -2045,7 +2092,7 @@ /* * Try to construct a new instance of the class. */ - newHandler = DefaultHandler_Construct(clsid, pUnkOuter); + newHandler = DefaultHandler_Construct(clsid, pUnkOuter, flags, pCF);
if (!newHandler) return E_OUTOFMEMORY; @@ -2063,3 +2110,15 @@
return hr; } + + +/****************************************************************************** + * OleCreateDefaultHandler [OLE32.@] + */ +HRESULT WINAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter, + REFIID riid, LPVOID* ppvObj) +{ + TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter,debugstr_guid(riid), ppvObj); + return OleCreateEmbeddingHelper(clsid, pUnkOuter, EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, + NULL, riid, ppvObj); +}
Modified: trunk/reactos/dll/win32/ole32/errorinfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/errorinfo.c... ============================================================================== --- trunk/reactos/dll/win32/ole32/errorinfo.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/errorinfo.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -191,7 +191,7 @@ VOID** ppvoid) { ErrorInfoImpl *This = impl_from_IErrorInfo(iface); - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvoid); + TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvoid);
*ppvoid = NULL;
Modified: trunk/reactos/dll/win32/ole32/ftmarshal.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/ftmarshal.c... ============================================================================== --- trunk/reactos/dll/win32/ole32/ftmarshal.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/ftmarshal.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -110,7 +110,7 @@
FTMarshalImpl *This = impl_from_IMarshal(iface);
- TRACE ("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid (riid), ppv); + TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppv); return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv); }
Modified: trunk/reactos/dll/win32/ole32/marshal.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/marshal.c?r... ============================================================================== --- trunk/reactos/dll/win32/ole32/marshal.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/marshal.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -431,7 +431,7 @@
if (SUCCEEDED(hr)) { - TRACE("writing stdobjref:\n\tflags = %04x\n\tcPublicRefs = %d\n\toxid = %s\n\toid = %s\n\tipid = %s\n", + TRACE("writing stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n", stdobjref.flags, stdobjref.cPublicRefs, wine_dbgstr_longlong(stdobjref.oxid), wine_dbgstr_longlong(stdobjref.oid), @@ -1239,7 +1239,7 @@
assert(apt);
- TRACE("stdobjref:\n\tflags = %04x\n\tcPublicRefs = %d\n\toxid = %s\n\toid = %s\n\tipid = %s\n", + TRACE("stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n", stdobjref->flags, stdobjref->cPublicRefs, wine_dbgstr_longlong(stdobjref->oxid), wine_dbgstr_longlong(stdobjref->oid),
Modified: trunk/reactos/dll/win32/ole32/ole2.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/ole2.c?rev=... ============================================================================== --- trunk/reactos/dll/win32/ole32/ole2.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/ole2.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -570,7 +570,7 @@ IDataObject* pSrcDataObject) { FIXME("(%p),stub!\n", pSrcDataObject); - return S_OK; + return S_FALSE; }
/***********************************************************************
Modified: trunk/reactos/dll/win32/ole32/ole32.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/ole32.spec?... ============================================================================== --- trunk/reactos/dll/win32/ole32/ole32.spec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/ole32.spec [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -180,7 +180,7 @@ @ stub OleConvertOLESTREAMToIStorageEx @ stdcall OleCreate(ptr ptr long ptr ptr ptr ptr) @ stdcall OleCreateDefaultHandler(ptr ptr ptr ptr) -@ stub OleCreateEmbeddingHelper +@ stdcall OleCreateEmbeddingHelper(ptr ptr long ptr ptr ptr) @ stub OleCreateEx @ stdcall OleCreateFromData(ptr ptr long ptr ptr ptr ptr) @ stdcall OleCreateFromDataEx(ptr ptr long long long ptr ptr ptr ptr ptr ptr ptr)
Modified: trunk/reactos/dll/win32/ole32/stg_prop.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/stg_prop.c?... ============================================================================== --- trunk/reactos/dll/win32/ole32/stg_prop.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/stg_prop.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -1477,6 +1477,25 @@ offsetof(PROPERTYIDOFFSET, dwOffset), dwOffset); }
+static inline HRESULT PropertStorage_WriteWStringToStream(IStream *stm, + LPCWSTR str, DWORD len, DWORD *written) +{ +#ifdef WORDS_BIGENDIAN + WCHAR *leStr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + HRESULT hr; + + if (!leStr) + return E_OUTOFMEMORY; + memcpy(leStr, str, len * sizeof(WCHAR)); + PropertyStorage_ByteSwapString(leStr, len); + hr = IStream_Write(stm, leStr, len, written); + HeapFree(GetProcessHeap(), 0, leStr); + return hr; +#else + return IStream_Write(stm, str, len, written); +#endif +} + struct DictionaryClosure { HRESULT hr; @@ -1508,15 +1527,11 @@ if (FAILED(c->hr)) goto end; c->bytesWritten += sizeof(DWORD); - /* Rather than allocate a copy, I'll swap the string to little-endian - * in-place, write it, then swap it back. - */ - PropertyStorage_ByteSwapString(key, keyLen); - c->hr = IStream_Write(This->stm, key, keyLen, &count); - PropertyStorage_ByteSwapString(key, keyLen); + c->hr = PropertStorage_WriteWStringToStream(This->stm, key, keyLen, + &count); if (FAILED(c->hr)) goto end; - c->bytesWritten += keyLen; + c->bytesWritten += keyLen * sizeof(WCHAR); if (keyLen % sizeof(DWORD)) { c->hr = IStream_Write(This->stm, &pad,
Modified: trunk/reactos/dll/win32/ole32/stg_stream.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/stg_stream.... ============================================================================== --- trunk/reactos/dll/win32/ole32/stg_stream.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/stg_stream.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -232,6 +232,7 @@ { This->smallBlockChain = SmallBlockChainStream_Construct( This->parentStorage->ancestorStorage, + NULL, This->ownerProperty); } else @@ -536,8 +537,6 @@ * * It will change the size of a stream. * - * TODO: Switch from small blocks to big blocks and vice versa. - * * See the documentation of IStream for more info. */ static HRESULT WINAPI StgStreamImpl_SetSize( @@ -591,6 +590,7 @@ { This->smallBlockChain = SmallBlockChainStream_Construct( This->parentStorage->ancestorStorage, + NULL, This->ownerProperty); } else @@ -622,6 +622,19 @@ This->bigBlockChain = Storage32Impl_SmallBlocksToBigBlocks( This->parentStorage->ancestorStorage, &This->smallBlockChain); + } + } + else if ( (This->bigBlockChain!=0) && + (curProperty.size.u.LowPart >= LIMIT_TO_USE_SMALL_BLOCK) ) + { + if (libNewSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK) + { + /* + * Transform the big block chain into a small block chain + */ + This->smallBlockChain = Storage32Impl_BigBlocksToSmallBlocks( + This->parentStorage->ancestorStorage, + &This->bigBlockChain); } }
Modified: trunk/reactos/dll/win32/ole32/storage32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/storage32.c... ============================================================================== --- trunk/reactos/dll/win32/ole32/storage32.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/storage32.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -104,6 +104,7 @@ static ULONG BlockChainStream_GetCount(BlockChainStream* This);
static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This); +static ULONG SmallBlockChainStream_GetHeadOfChain(SmallBlockChainStream* This); static BOOL StorageImpl_WriteDWordToBigBlock( StorageImpl* This, ULONG blockIndex, ULONG offset, DWORD value); static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This, @@ -3586,9 +3587,13 @@ } while (cbTotalRead.QuadPart < size.QuadPart); HeapFree(GetProcessHeap(),0,buffer);
+ size.u.HighPart = 0; + size.u.LowPart = 0; + if (FAILED(resRead) || FAILED(resWrite)) { ERR("conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite); + BlockChainStream_SetSize(bbTempChain, size); BlockChainStream_Destroy(bbTempChain); return NULL; } @@ -3597,8 +3602,6 @@ * Destroy the small block chain. */ propertyIndex = (*ppsbChain)->ownerPropertyIndex; - size.u.HighPart = 0; - size.u.LowPart = 0; SmallBlockChainStream_SetSize(*ppsbChain, size); SmallBlockChainStream_Destroy(*ppsbChain); *ppsbChain = 0; @@ -3623,6 +3626,86 @@ propertyIndex);
return bigBlockChain; +} + +/****************************************************************************** + * Storage32Impl_BigBlocksToSmallBlocks + * + * This method will convert a big block chain to a small block chain. + * The big block chain will be destroyed on success. + */ +SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks( + StorageImpl* This, + BlockChainStream** ppbbChain) +{ + ULARGE_INTEGER size, offset, cbTotalRead; + ULONG cbRead, cbWritten, propertyIndex, sbHeadOfChain = BLOCK_END_OF_CHAIN; + HRESULT resWrite = S_OK, resRead; + StgProperty chainProperty; + BYTE* buffer; + SmallBlockChainStream* sbTempChain; + + TRACE("%p %p\n", This, ppbbChain); + + sbTempChain = SmallBlockChainStream_Construct(This, &sbHeadOfChain, + PROPERTY_NULL); + + if(!sbTempChain) + return NULL; + + size = BlockChainStream_GetSize(*ppbbChain); + SmallBlockChainStream_SetSize(sbTempChain, size); + + offset.u.HighPart = 0; + offset.u.LowPart = 0; + cbTotalRead.QuadPart = 0; + buffer = HeapAlloc(GetProcessHeap(), 0, This->bigBlockSize); + do + { + resRead = BlockChainStream_ReadAt(*ppbbChain, offset, + This->bigBlockSize, buffer, &cbRead); + + if(FAILED(resRead)) + break; + + if(cbRead > 0) + { + cbTotalRead.QuadPart += cbRead; + + resWrite = SmallBlockChainStream_WriteAt(sbTempChain, offset, + cbRead, buffer, &cbWritten); + + if(FAILED(resWrite)) + break; + + offset.u.LowPart += This->bigBlockSize; + } + }while(cbTotalRead.QuadPart < size.QuadPart); + HeapFree(GetProcessHeap(), 0, buffer); + + size.u.HighPart = 0; + size.u.LowPart = 0; + + if(FAILED(resRead) || FAILED(resWrite)) + { + ERR("conversion failed: resRead = 0x%08x, resWrite = 0x%08x\n", resRead, resWrite); + SmallBlockChainStream_SetSize(sbTempChain, size); + SmallBlockChainStream_Destroy(sbTempChain); + return NULL; + } + + /* destroy the original big block chain */ + propertyIndex = (*ppbbChain)->ownerPropertyIndex; + BlockChainStream_SetSize(*ppbbChain, size); + BlockChainStream_Destroy(*ppbbChain); + *ppbbChain = NULL; + + StorageImpl_ReadProperty(This, propertyIndex, &chainProperty); + chainProperty.startingBlock = sbHeadOfChain; + StorageImpl_WriteProperty(This, propertyIndex, &chainProperty); + + SmallBlockChainStream_Destroy(sbTempChain); + return SmallBlockChainStream_Construct(This, NULL, propertyIndex); }
static void StorageInternalImpl_Destroy( StorageBaseImpl *iface) @@ -4577,7 +4660,6 @@ * BlockChainStream_WriteAt * * Writes the specified number of bytes to this chain at the specified offset. - * bytesWritten may be NULL. * Will fail if not all specified number of bytes have been written. */ HRESULT BlockChainStream_WriteAt(BlockChainStream* This, @@ -4929,6 +5011,7 @@
SmallBlockChainStream* SmallBlockChainStream_Construct( StorageImpl* parentStorage, + ULONG* headOfStreamPlaceHolder, ULONG propertyIndex) { SmallBlockChainStream* newStream; @@ -4936,6 +5019,7 @@ newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(SmallBlockChainStream));
newStream->parentStorage = parentStorage; + newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder; newStream->ownerPropertyIndex = propertyIndex;
return newStream; @@ -4957,6 +5041,9 @@ { StgProperty chainProperty; BOOL readSuccessful; + + if (This->headOfStreamPlaceHolder != NULL) + return *(This->headOfStreamPlaceHolder);
if (This->ownerPropertyIndex) { @@ -5320,7 +5407,6 @@ * SmallBlockChainStream_WriteAt * * Writes the specified number of bytes to this chain at the specified offset. - * bytesWritten may be NULL. * Will fail if not all specified number of bytes have been written. */ HRESULT SmallBlockChainStream_WriteAt( @@ -5360,9 +5446,6 @@
/* * Start writing the buffer. - * - * Here, I'm casting away the constness on the buffer variable - * This is OK since we don't intend to modify that buffer. */ *bytesWritten = 0; bufferWalker = buffer; @@ -5509,61 +5592,67 @@ blockIndex = SmallBlockChainStream_GetHeadOfChain(This);
/* - * Empty chain + * Empty chain. Create the head. */ if (blockIndex == BLOCK_END_OF_CHAIN) { - - StgProperty chainProp; - - StorageImpl_ReadProperty(This->parentStorage, This->ownerPropertyIndex, - &chainProp); - - chainProp.startingBlock = SmallBlockChainStream_GetNextFreeBlock(This); - - StorageImpl_WriteProperty(This->parentStorage, This->ownerPropertyIndex, - &chainProp); - - blockIndex = chainProp.startingBlock; + blockIndex = SmallBlockChainStream_GetNextFreeBlock(This); + SmallBlockChainStream_SetNextBlockInChain( + This, + blockIndex, + BLOCK_END_OF_CHAIN); + + if (This->headOfStreamPlaceHolder != NULL) + { + *(This->headOfStreamPlaceHolder) = blockIndex; + } + else + { + StgProperty chainProp; + + StorageImpl_ReadProperty(This->parentStorage, This->ownerPropertyIndex, + &chainProp); + + chainProp.startingBlock = blockIndex; + + StorageImpl_WriteProperty(This->parentStorage, This->ownerPropertyIndex, + &chainProp); + } + } + + currentBlock = blockIndex; + + /* + * Figure out how many blocks are needed to contain this stream + */ + newNumBlocks = newSize.u.LowPart / This->parentStorage->smallBlockSize; + + if ((newSize.u.LowPart % This->parentStorage->smallBlockSize) != 0) + newNumBlocks++; + + /* + * Go to the current end of chain + */ + while (blockIndex != BLOCK_END_OF_CHAIN) + { + oldNumBlocks++; + currentBlock = blockIndex; + if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, currentBlock, &blockIndex))) + return FALSE; + } + + /* + * Add new blocks to the chain + */ + while (oldNumBlocks < newNumBlocks) + { + blockIndex = SmallBlockChainStream_GetNextFreeBlock(This); + SmallBlockChainStream_SetNextBlockInChain(This, currentBlock, blockIndex); + SmallBlockChainStream_SetNextBlockInChain( This, blockIndex, BLOCK_END_OF_CHAIN); - } - - currentBlock = blockIndex; - - /* - * Figure out how many blocks are needed to contain this stream - */ - newNumBlocks = newSize.u.LowPart / This->parentStorage->smallBlockSize; - - if ((newSize.u.LowPart % This->parentStorage->smallBlockSize) != 0) - newNumBlocks++; - - /* - * Go to the current end of chain - */ - while (blockIndex != BLOCK_END_OF_CHAIN) - { - oldNumBlocks++; - currentBlock = blockIndex; - if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, currentBlock, &blockIndex))) - return FALSE; - } - - /* - * Add new blocks to the chain - */ - while (oldNumBlocks < newNumBlocks) - { - blockIndex = SmallBlockChainStream_GetNextFreeBlock(This); - SmallBlockChainStream_SetNextBlockInChain(This, currentBlock, blockIndex); - - SmallBlockChainStream_SetNextBlockInChain( - This, - blockIndex, - BLOCK_END_OF_CHAIN);
currentBlock = blockIndex; oldNumBlocks++; @@ -5604,6 +5693,32 @@ }
/****************************************************************************** + * SmallBlockChainStream_GetCount + * + * Returns the number of small blocks that comprises this chain. + * This is not the size of the stream as the last block may not be full! + * + */ +static ULONG SmallBlockChainStream_GetCount(SmallBlockChainStream* This) +{ + ULONG blockIndex; + ULONG count = 0; + + blockIndex = SmallBlockChainStream_GetHeadOfChain(This); + + while(blockIndex != BLOCK_END_OF_CHAIN) + { + count++; + + if(FAILED(SmallBlockChainStream_GetNextBlockInChain(This, + blockIndex, &blockIndex))) + return 0; + } + + return count; +} + +/****************************************************************************** * SmallBlockChainStream_GetSize * * Returns the size of this chain. @@ -5611,6 +5726,17 @@ static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This) { StgProperty chainProperty; + + if(This->headOfStreamPlaceHolder != NULL) + { + ULARGE_INTEGER result; + result.u.HighPart = 0; + + result.u.LowPart = SmallBlockChainStream_GetCount(This) * + This->parentStorage->smallBlockSize; + + return result; + }
StorageImpl_ReadProperty( This->parentStorage,
Modified: trunk/reactos/dll/win32/ole32/storage32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/storage32.h... ============================================================================== --- trunk/reactos/dll/win32/ole32/storage32.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/storage32.h [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -306,6 +306,10 @@ StorageImpl* This, SmallBlockChainStream** ppsbChain);
+SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks( + StorageImpl* This, + BlockChainStream** ppbbChain); + /**************************************************************************** * StgStreamImpl definitions. * @@ -464,14 +468,16 @@ { StorageImpl* parentStorage; ULONG ownerPropertyIndex; + ULONG* headOfStreamPlaceHolder; };
/* * Methods of the SmallBlockChainStream class. */ SmallBlockChainStream* SmallBlockChainStream_Construct( - StorageImpl* parentStorage, - ULONG propertyIndex); + StorageImpl* parentStorage, + ULONG* headOfStreamPlaceHolder, + ULONG propertyIndex);
void SmallBlockChainStream_Destroy( SmallBlockChainStream* This);
Modified: trunk/reactos/dll/win32/ole32/stubmanager.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/ole32/stubmanager... ============================================================================== --- trunk/reactos/dll/win32/ole32/stubmanager.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/ole32/stubmanager.c [iso-8859-1] Mon Aug 24 12:51:15 2009 @@ -42,8 +42,129 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
-static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub); -static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid); + +/* generates an ipid in the following format (similar to native version): + * Data1 = apartment-local ipid counter + * Data2 = apartment creator thread ID + * Data3 = process ID + * Data4 = random value + */ +static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid) +{ + HRESULT hr; + hr = UuidCreate(ipid); + if (FAILED(hr)) + { + ERR("couldn't create IPID for stub manager %p\n", m); + UuidCreateNil(ipid); + return hr; + } + + ipid->Data1 = InterlockedIncrement(&m->apt->ipidc); + ipid->Data2 = (USHORT)m->apt->tid; + ipid->Data3 = (USHORT)GetCurrentProcessId(); + return S_OK; +} + +/* registers a new interface stub COM object with the stub manager and returns registration record */ +struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags) +{ + struct ifstub *stub; + HRESULT hr; + + TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n", + wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid)); + + stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub)); + if (!stub) return NULL; + + hr = RPC_CreateServerChannel(&stub->chan); + if (hr != S_OK) + { + HeapFree(GetProcessHeap(), 0, stub); + return NULL; + } + + stub->stubbuffer = sb; + if (sb) IRpcStubBuffer_AddRef(sb); + + IUnknown_AddRef(iptr); + stub->iface = iptr; + stub->flags = flags; + stub->iid = *iid; + + /* FIXME: find a cleaner way of identifying that we are creating an ifstub + * for the remunknown interface */ + if (flags & MSHLFLAGSP_REMUNKNOWN) + stub->ipid = m->oxid_info.ipidRemUnknown; + else + generate_ipid(m, &stub->ipid); + + EnterCriticalSection(&m->lock); + list_add_head(&m->ifstubs, &stub->entry); + /* every normal marshal is counted so we don't allow more than we should */ + if (flags & MSHLFLAGS_NORMAL) m->norm_refs++; + LeaveCriticalSection(&m->lock); + + TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid)); + + return stub; +} + +static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub) +{ + TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid)); + + list_remove(&ifstub->entry); + + RPC_UnregisterInterface(&ifstub->iid); + + if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer); + IUnknown_Release(ifstub->iface); + IRpcChannelBuffer_Release(ifstub->chan); + + HeapFree(GetProcessHeap(), 0, ifstub); +} + +static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid) +{ + struct list *cursor; + struct ifstub *result = NULL; + + EnterCriticalSection(&m->lock); + LIST_FOR_EACH( cursor, &m->ifstubs ) + { + struct ifstub *ifstub = LIST_ENTRY( cursor, struct ifstub, entry ); + + if (IsEqualGUID(ipid, &ifstub->ipid)) + { + result = ifstub; + break; + } + } + LeaveCriticalSection(&m->lock); + + return result; +} + +struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) +{ + struct ifstub *result = NULL; + struct ifstub *ifstub; + + EnterCriticalSection(&m->lock); + LIST_FOR_EACH_ENTRY( ifstub, &m->ifstubs, struct ifstub, entry ) + { + if (IsEqualIID(iid, &ifstub->iid) && (ifstub->flags == flags)) + { + result = ifstub; + break; + } + } + LeaveCriticalSection(&m->lock); + + return result; +}
/* creates a new stub manager and adds it into the apartment. caller must * release stub manager when it is no longer required. the apartment and @@ -129,6 +250,44 @@ HeapFree(GetProcessHeap(), 0, m); }
+/* increments the internal refcount */ +static ULONG stub_manager_int_addref(struct stub_manager *This) +{ + ULONG refs; + + EnterCriticalSection(&This->apt->cs); + refs = ++This->refs; + LeaveCriticalSection(&This->apt->cs); + + TRACE("before %d\n", refs - 1); + + return refs; +} + +/* decrements the internal refcount */ +ULONG stub_manager_int_release(struct stub_manager *This) +{ + ULONG refs; + APARTMENT *apt = This->apt; + + EnterCriticalSection(&apt->cs); + refs = --This->refs; + + TRACE("after %d\n", refs); + + /* remove from apartment so no other thread can access it... */ + if (!refs) + list_remove(&This->entry); + + LeaveCriticalSection(&apt->cs); + + /* ... so now we can delete it without being inside the apartment critsec */ + if (!refs) + stub_manager_delete(This); + + return refs; +} + /* gets the stub manager associated with an object - caller must have * a reference to the apartment while a reference to the stub manager is held. * it must also call release on the stub manager when it is no longer needed */ @@ -214,44 +373,6 @@ return result; }
-/* increments the internal refcount */ -ULONG stub_manager_int_addref(struct stub_manager *This) -{ - ULONG refs; - - EnterCriticalSection(&This->apt->cs); - refs = ++This->refs; - LeaveCriticalSection(&This->apt->cs); - - TRACE("before %d\n", refs - 1); - - return refs; -} - -/* decrements the internal refcount */ -ULONG stub_manager_int_release(struct stub_manager *This) -{ - ULONG refs; - APARTMENT *apt = This->apt; - - EnterCriticalSection(&apt->cs); - refs = --This->refs; - - TRACE("after %d\n", refs); - - /* remove from apartment so no other thread can access it... */ - if (!refs) - list_remove(&This->entry); - - LeaveCriticalSection(&apt->cs); - - /* ... so now we can delete it without being inside the apartment critsec */ - if (!refs) - stub_manager_delete(This); - - return refs; -} - /* add some external references (ie from a client that unmarshaled an ifptr) */ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) { @@ -295,46 +416,6 @@ stub_manager_int_release(m);
return rc; -} - -static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid) -{ - struct list *cursor; - struct ifstub *result = NULL; - - EnterCriticalSection(&m->lock); - LIST_FOR_EACH( cursor, &m->ifstubs ) - { - struct ifstub *ifstub = LIST_ENTRY( cursor, struct ifstub, entry ); - - if (IsEqualGUID(ipid, &ifstub->ipid)) - { - result = ifstub; - break; - } - } - LeaveCriticalSection(&m->lock); - - return result; -} - -struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) -{ - struct ifstub *result = NULL; - struct ifstub *ifstub; - - EnterCriticalSection(&m->lock); - LIST_FOR_EACH_ENTRY( ifstub, &m->ifstubs, struct ifstub, entry ) - { - if (IsEqualIID(iid, &ifstub->iid) && (ifstub->flags == flags)) - { - result = ifstub; - break; - } - } - LeaveCriticalSection(&m->lock); - - return result; }
/* gets the stub manager associated with an ipid - caller must have @@ -424,89 +505,6 @@ apartment_release(apt); return RPC_E_DISCONNECTED; } -} - -/* generates an ipid in the following format (similar to native version): - * Data1 = apartment-local ipid counter - * Data2 = apartment creator thread ID - * Data3 = process ID - * Data4 = random value - */ -static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid) -{ - HRESULT hr; - hr = UuidCreate(ipid); - if (FAILED(hr)) - { - ERR("couldn't create IPID for stub manager %p\n", m); - UuidCreateNil(ipid); - return hr; - } - - ipid->Data1 = InterlockedIncrement(&m->apt->ipidc); - ipid->Data2 = (USHORT)m->apt->tid; - ipid->Data3 = (USHORT)GetCurrentProcessId(); - return S_OK; -} - -/* registers a new interface stub COM object with the stub manager and returns registration record */ -struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, MSHLFLAGS flags) -{ - struct ifstub *stub; - HRESULT hr; - - TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n", - wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid)); - - stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub)); - if (!stub) return NULL; - - hr = RPC_CreateServerChannel(&stub->chan); - if (hr != S_OK) - { - HeapFree(GetProcessHeap(), 0, stub); - return NULL; - } - - stub->stubbuffer = sb; - if (sb) IRpcStubBuffer_AddRef(sb); - - IUnknown_AddRef(iptr); - stub->iface = iptr; - stub->flags = flags; - stub->iid = *iid; - - /* FIXME: find a cleaner way of identifying that we are creating an ifstub - * for the remunknown interface */ - if (flags & MSHLFLAGSP_REMUNKNOWN) - stub->ipid = m->oxid_info.ipidRemUnknown; - else - generate_ipid(m, &stub->ipid); - - EnterCriticalSection(&m->lock); - list_add_head(&m->ifstubs, &stub->entry); - /* every normal marshal is counted so we don't allow more than we should */ - if (flags & MSHLFLAGS_NORMAL) m->norm_refs++; - LeaveCriticalSection(&m->lock); - - TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid)); - - return stub; -} - -static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub) -{ - TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid)); - - list_remove(&ifstub->entry); - - RPC_UnregisterInterface(&ifstub->iid); - - if (ifstub->stubbuffer) IUnknown_Release(ifstub->stubbuffer); - IUnknown_Release(ifstub->iface); - IRpcChannelBuffer_Release(ifstub->chan); - - HeapFree(GetProcessHeap(), 0, ifstub); }
/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */