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.…
==============================================================================
--- 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?r…
==============================================================================
--- 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?…
==============================================================================
--- 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_pr…
==============================================================================
--- 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/defaulthan…
==============================================================================
--- 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.…
==============================================================================
--- 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.…
==============================================================================
--- 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?…
==============================================================================
--- 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.…
==============================================================================
--- 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.…
==============================================================================
--- 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/stubmanage…
==============================================================================
--- 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. */