mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[OLE32]
* Sync with Wine 1.7.1. CORE-7469 svn path=/trunk/; revision=60354
This commit is contained in:
parent
fa44344f03
commit
01f85a4410
16 changed files with 467 additions and 253 deletions
|
@ -1,8 +1,4 @@
|
|||
|
||||
spec2def(ole32.dll ole32.spec ADD_IMPORTLIB)
|
||||
generate_idl_iids(dcom.idl)
|
||||
add_idl_headers(ole32idl dcom.idl irot.idl)
|
||||
|
||||
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||
add_definitions(-D_WIN32_WINNT=0x600)
|
||||
|
||||
|
@ -16,6 +12,9 @@ add_definitions(
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
||||
|
||||
spec2def(ole32.dll ole32.spec ADD_IMPORTLIB)
|
||||
generate_idl_iids(dcom.idl)
|
||||
add_idl_headers(ole32idl dcom.idl irot.idl)
|
||||
add_rpc_files(client irot.idl)
|
||||
|
||||
add_rpcproxy_files(
|
||||
|
@ -60,13 +59,12 @@ list(APPEND SOURCE
|
|||
storage32.c
|
||||
stubmanager.c
|
||||
usrmarshal.c
|
||||
ole32res.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/dcom_i.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/dcom_p.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/irot_c.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ole32_unknwn_p.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ole32_objidl_p.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ole32_oleidl_p.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ole32_unknwn_p.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ole32_stubs.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ole32.def)
|
||||
|
@ -78,7 +76,7 @@ if(MSVC)
|
|||
set_source_files_properties(stg_prop.c PROPERTIES COMPILE_FLAGS "/FImsvc.h")
|
||||
endif()
|
||||
|
||||
add_library(ole32 SHARED ${SOURCE})
|
||||
add_library(ole32 SHARED ${SOURCE} ole32res.rc)
|
||||
set_module_type(ole32 win32dll)
|
||||
target_link_libraries(ole32 wine uuid ${PSEH_LIB})
|
||||
add_importlibs(ole32 advapi32 user32 gdi32 rpcrt4 msvcrt kernel32 ntdll)
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <ole2ver.h>
|
||||
#include <ctxtcall.h>
|
||||
#include <dde.h>
|
||||
#include <servprov.h>
|
||||
|
||||
#include <initguid.h>
|
||||
#include "compobj_private.h"
|
||||
|
@ -97,6 +98,20 @@ struct registered_psclsid
|
|||
CLSID clsid;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a marshallable object exposing registered local servers.
|
||||
* IServiceProvider is used only because it happens meet requirements
|
||||
* and already has proxy/stub code. If more functionality is needed,
|
||||
* a custom interface may be used instead.
|
||||
*/
|
||||
struct LocalServer
|
||||
{
|
||||
IServiceProvider IServiceProvider_iface;
|
||||
LONG ref;
|
||||
APARTMENT *apt;
|
||||
IStream *marshal_stream;
|
||||
};
|
||||
|
||||
/*
|
||||
* This lock count counts the number of times CoInitialize is called. It is
|
||||
* decreased every time CoUninitialize is called. When it hits 0, the COM
|
||||
|
@ -123,7 +138,6 @@ typedef struct tagRegisteredClass
|
|||
DWORD runContext;
|
||||
DWORD connectFlags;
|
||||
DWORD dwCookie;
|
||||
LPSTREAM pMarshaledData; /* FIXME: only really need to store OXID and IPID */
|
||||
void *RpcRegistration;
|
||||
} RegisteredClass;
|
||||
|
||||
|
@ -384,6 +398,7 @@ static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
|
|||
entry->DllCanUnloadNow = DllCanUnloadNow;
|
||||
entry->DllGetClassObject = DllGetClassObject;
|
||||
list_add_tail(&openDllList, &entry->entry);
|
||||
*ret = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -391,7 +406,6 @@ static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
|
|||
hr = E_OUTOFMEMORY;
|
||||
FreeLibrary(hLibrary);
|
||||
}
|
||||
*ret = entry;
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &csOpenDllList );
|
||||
|
@ -549,20 +563,7 @@ static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass)
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -730,6 +731,130 @@ static HRESULT ManualResetEvent_Construct(IUnknown *punkouter, REFIID iid, void
|
|||
return hr;
|
||||
}
|
||||
|
||||
static inline LocalServer *impl_from_IServiceProvider(IServiceProvider *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, LocalServer, IServiceProvider_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI LocalServer_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
LocalServer *This = impl_from_IServiceProvider(iface);
|
||||
|
||||
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
|
||||
|
||||
if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) {
|
||||
*ppv = &This->IServiceProvider_iface;
|
||||
}else {
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IUnknown_AddRef((IUnknown*)*ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI LocalServer_AddRef(IServiceProvider *iface)
|
||||
{
|
||||
LocalServer *This = impl_from_IServiceProvider(iface);
|
||||
LONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI LocalServer_Release(IServiceProvider *iface)
|
||||
{
|
||||
LocalServer *This = impl_from_IServiceProvider(iface);
|
||||
LONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
if(!ref) {
|
||||
assert(!This->apt);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI LocalServer_QueryService(IServiceProvider *iface, REFGUID guid, REFIID riid, void **ppv)
|
||||
{
|
||||
LocalServer *This = impl_from_IServiceProvider(iface);
|
||||
APARTMENT *apt = COM_CurrentApt();
|
||||
RegisteredClass *iter;
|
||||
HRESULT hres = E_FAIL;
|
||||
|
||||
TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guid), debugstr_guid(riid), ppv);
|
||||
|
||||
if(!This->apt)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
EnterCriticalSection(&csRegisteredClassList);
|
||||
|
||||
LIST_FOR_EACH_ENTRY(iter, &RegisteredClassList, RegisteredClass, entry) {
|
||||
if(iter->apartment_id == apt->oxid
|
||||
&& (iter->runContext & CLSCTX_LOCAL_SERVER)
|
||||
&& IsEqualGUID(&iter->classIdentifier, guid)) {
|
||||
hres = IUnknown_QueryInterface(iter->classObject, riid, ppv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &csRegisteredClassList );
|
||||
|
||||
return hres;
|
||||
}
|
||||
|
||||
static const IServiceProviderVtbl LocalServerVtbl = {
|
||||
LocalServer_QueryInterface,
|
||||
LocalServer_AddRef,
|
||||
LocalServer_Release,
|
||||
LocalServer_QueryService
|
||||
};
|
||||
|
||||
static HRESULT get_local_server_stream(APARTMENT *apt, IStream **ret)
|
||||
{
|
||||
HRESULT hres = S_OK;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
|
||||
if(!apt->local_server) {
|
||||
LocalServer *obj;
|
||||
|
||||
obj = heap_alloc(sizeof(*obj));
|
||||
if(obj) {
|
||||
obj->IServiceProvider_iface.lpVtbl = &LocalServerVtbl;
|
||||
obj->ref = 1;
|
||||
obj->apt = apt;
|
||||
|
||||
hres = CreateStreamOnHGlobal(0, TRUE, &obj->marshal_stream);
|
||||
if(SUCCEEDED(hres)) {
|
||||
hres = CoMarshalInterface(obj->marshal_stream, &IID_IServiceProvider, (IUnknown*)&obj->IServiceProvider_iface,
|
||||
MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
|
||||
if(FAILED(hres))
|
||||
IStream_Release(obj->marshal_stream);
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
apt->local_server = obj;
|
||||
else
|
||||
heap_free(obj);
|
||||
}else {
|
||||
hres = E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
hres = IStream_Clone(apt->local_server->marshal_stream, ret);
|
||||
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
if(FAILED(hres))
|
||||
ERR("Failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CoRevokeClassObject [OLE32.@]
|
||||
*
|
||||
|
@ -860,6 +985,21 @@ DWORD apartment_release(struct apartment *apt)
|
|||
|
||||
TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));
|
||||
|
||||
if(apt->local_server) {
|
||||
LocalServer *local_server = apt->local_server;
|
||||
LARGE_INTEGER zero;
|
||||
|
||||
memset(&zero, 0, sizeof(zero));
|
||||
IStream_Seek(local_server->marshal_stream, zero, STREAM_SEEK_SET, NULL);
|
||||
CoReleaseMarshalData(local_server->marshal_stream);
|
||||
IStream_Release(local_server->marshal_stream);
|
||||
local_server->marshal_stream = NULL;
|
||||
|
||||
apt->local_server = NULL;
|
||||
local_server->apt = NULL;
|
||||
IServiceProvider_Release(&local_server->IServiceProvider_iface);
|
||||
}
|
||||
|
||||
/* Release the references to the registered class objects */
|
||||
COM_RevokeAllClasses(apt);
|
||||
|
||||
|
@ -2103,6 +2243,15 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
|
|||
return __CLSIDFromString(buf2,clsid);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CLSIDFromProgIDEx [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI CLSIDFromProgIDEx(LPCOLESTR progid, LPCLSID clsid)
|
||||
{
|
||||
FIXME("%s,%p: semi-stub\n", debugstr_w(progid), clsid);
|
||||
|
||||
return CLSIDFromProgID(progid, clsid);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CoGetPSClsid [OLE32.@]
|
||||
|
@ -2407,7 +2556,6 @@ HRESULT WINAPI CoRegisterClassObject(
|
|||
newClass->apartment_id = apt->oxid;
|
||||
newClass->runContext = dwClsContext;
|
||||
newClass->connectFlags = flags;
|
||||
newClass->pMarshaledData = NULL;
|
||||
newClass->RpcRegistration = NULL;
|
||||
|
||||
if (!(newClass->dwCookie = InterlockedIncrement( &next_cookie )))
|
||||
|
@ -2427,23 +2575,17 @@ HRESULT WINAPI CoRegisterClassObject(
|
|||
*lpdwRegister = newClass->dwCookie;
|
||||
|
||||
if (dwClsContext & CLSCTX_LOCAL_SERVER) {
|
||||
hr = CreateStreamOnHGlobal(0, TRUE, &newClass->pMarshaledData);
|
||||
if (hr) {
|
||||
FIXME("Failed to create stream on hglobal, %x\n", hr);
|
||||
IStream *marshal_stream;
|
||||
|
||||
hr = get_local_server_stream(apt, &marshal_stream);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
hr = CoMarshalInterface(newClass->pMarshaledData, &IID_IUnknown,
|
||||
newClass->classObject, MSHCTX_LOCAL, NULL,
|
||||
MSHLFLAGS_TABLESTRONG);
|
||||
if (hr) {
|
||||
FIXME("CoMarshalInterface failed, %x!\n",hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = RPC_StartLocalServer(&newClass->classIdentifier,
|
||||
newClass->pMarshaledData,
|
||||
marshal_stream,
|
||||
flags & (REGCLS_MULTIPLEUSE|REGCLS_MULTI_SEPARATE),
|
||||
&newClass->RpcRegistration);
|
||||
IStream_Release(marshal_stream);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -2768,16 +2910,12 @@ HRESULT WINAPI CoCreateInstance(
|
|||
|
||||
/*
|
||||
* The Standard Global Interface Table (GIT) object is a process-wide singleton.
|
||||
* Rather than create a class factory, we can just check for it here
|
||||
*/
|
||||
if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable))
|
||||
{
|
||||
if (StdGlobalInterfaceTableInstance == NULL)
|
||||
StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct();
|
||||
hres = IGlobalInterfaceTable_QueryInterface((IGlobalInterfaceTable*)StdGlobalInterfaceTableInstance,
|
||||
iid,
|
||||
ppv);
|
||||
if (hres) return hres;
|
||||
IGlobalInterfaceTable *git = get_std_git();
|
||||
hres = IGlobalInterfaceTable_QueryInterface(git, iid, ppv);
|
||||
if (hres != S_OK) return hres;
|
||||
|
||||
TRACE("Retrieved GIT (%p)\n", *ppv);
|
||||
return S_OK;
|
||||
|
@ -2859,7 +2997,7 @@ HRESULT WINAPI CoCreateInstanceEx(
|
|||
&IID_IUnknown,
|
||||
(VOID**)&pUnk);
|
||||
|
||||
if (hr)
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
|
||||
/*
|
||||
|
@ -4445,9 +4583,9 @@ HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
|||
/***********************************************************************
|
||||
* DllMain (OLE32.@)
|
||||
*/
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID reserved)
|
||||
{
|
||||
TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
|
||||
TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, reserved);
|
||||
|
||||
switch(fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
@ -4456,6 +4594,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
if (reserved) break;
|
||||
release_std_git();
|
||||
COMPOBJ_UninitProcess();
|
||||
RPC_UnregisterAllChannelHooks();
|
||||
COMPOBJ_DllList_Free();
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
struct apartment;
|
||||
typedef struct apartment APARTMENT;
|
||||
typedef struct LocalServer LocalServer;
|
||||
|
||||
DEFINE_OLEGUID( CLSID_DfMarshal, 0x0000030b, 0, 0 );
|
||||
|
||||
|
@ -97,6 +98,8 @@ struct stub_manager
|
|||
ULONG next_ipid; /* currently unused (LOCK) */
|
||||
OXID_INFO oxid_info; /* string binding, ipid of rem unknown and other information (RO) */
|
||||
|
||||
IExternalConnection *extern_conn;
|
||||
|
||||
/* We need to keep a count of the outstanding marshals, so we can enforce the
|
||||
* marshalling rules (ie, you can only unmarshal normal marshals once). Note
|
||||
* that these counts do NOT include unmarshalled interfaces, once a stream is
|
||||
|
@ -137,6 +140,7 @@ struct apartment
|
|||
struct list loaded_dlls; /* list of dlls loaded by this apartment (CS cs) */
|
||||
DWORD host_apt_tid; /* thread ID of apartment hosting objects of differing threading model (CS cs) */
|
||||
HWND host_apt_hwnd; /* handle to apartment window of host apartment (CS cs) */
|
||||
LocalServer *local_server; /* A marshallable object exposing local servers (CS cs) */
|
||||
|
||||
/* FIXME: OIDs should be given out by RPCSS */
|
||||
OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */
|
||||
|
@ -169,10 +173,9 @@ struct oletls
|
|||
|
||||
|
||||
/* Global Interface Table Functions */
|
||||
|
||||
extern void* StdGlobalInterfaceTable_Construct(void) DECLSPEC_HIDDEN;
|
||||
extern IGlobalInterfaceTable *get_std_git(void) DECLSPEC_HIDDEN;
|
||||
extern void release_std_git(void) DECLSPEC_HIDDEN;
|
||||
extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv) DECLSPEC_HIDDEN;
|
||||
extern void* StdGlobalInterfaceTableInstance DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *key) DECLSPEC_HIDDEN;
|
||||
HRESULT COM_OpenKeyForAppIdFromCLSID(REFCLSID clsid, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN;
|
||||
|
@ -312,4 +315,14 @@ extern UINT ole_private_data_clipboard_format DECLSPEC_HIDDEN;
|
|||
extern LSTATUS create_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HIDDEN;
|
||||
extern LSTATUS open_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline void *heap_alloc(size_t len)
|
||||
{
|
||||
return HeapAlloc(GetProcessHeap(), 0, len);
|
||||
}
|
||||
|
||||
static inline BOOL heap_free(void *mem)
|
||||
{
|
||||
return HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
|
||||
#endif /* __WINE_OLE_COMPOBJ_H */
|
||||
|
|
|
@ -239,7 +239,7 @@ CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
|
|||
if (++This->tabLastIndex==This->tabSize){
|
||||
|
||||
This->tabSize+=BLOCK_TAB_SIZE;
|
||||
This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
|
||||
This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
|
||||
|
||||
if (This->tabMoniker==NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -1446,7 +1446,7 @@ static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal *i
|
|||
if (This->tabLastIndex + 2 > This->tabSize)
|
||||
{
|
||||
This->tabSize += max(BLOCK_TAB_SIZE, 2);
|
||||
This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
|
||||
This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
|
||||
|
||||
if (This->tabMoniker==NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -1661,7 +1661,7 @@ EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
|
|||
newEnumMoniker->tabSize=tabSize;
|
||||
newEnumMoniker->currentPos=currentPos;
|
||||
|
||||
newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
|
||||
newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(newEnumMoniker->tabMoniker[0]));
|
||||
|
||||
if (newEnumMoniker->tabMoniker==NULL) {
|
||||
HeapFree(GetProcessHeap(), 0, newEnumMoniker);
|
||||
|
@ -1768,7 +1768,7 @@ CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMonike
|
|||
This->tabSize=BLOCK_TAB_SIZE;
|
||||
This->tabLastIndex=0;
|
||||
|
||||
This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
|
||||
This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(This->tabMoniker[0]));
|
||||
if (This->tabMoniker==NULL) {
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -1896,7 +1896,7 @@ CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMonike
|
|||
|
||||
This->tabSize+=BLOCK_TAB_SIZE;
|
||||
|
||||
This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
|
||||
This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
|
||||
|
||||
if (This->tabMoniker==NULL){
|
||||
HeapFree(GetProcessHeap(), 0, tab_moniker);
|
||||
|
|
|
@ -44,16 +44,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
static inline void *heap_alloc(size_t len)
|
||||
{
|
||||
return HeapAlloc(GetProcessHeap(), 0, len);
|
||||
}
|
||||
|
||||
static inline BOOL heap_free(void *mem)
|
||||
{
|
||||
return HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
|
||||
static inline WCHAR *heap_strdupW(const WCHAR *str)
|
||||
{
|
||||
WCHAR *ret = NULL;
|
||||
|
|
|
@ -69,13 +69,12 @@ typedef struct StdGlobalInterfaceTableImpl
|
|||
{
|
||||
IGlobalInterfaceTable IGlobalInterfaceTable_iface;
|
||||
|
||||
ULONG ref;
|
||||
struct list list;
|
||||
ULONG nextCookie;
|
||||
|
||||
} StdGlobalInterfaceTableImpl;
|
||||
|
||||
void* StdGlobalInterfaceTableInstance;
|
||||
static IGlobalInterfaceTable *std_git;
|
||||
|
||||
static CRITICAL_SECTION git_section;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
|
@ -92,16 +91,6 @@ static inline StdGlobalInterfaceTableImpl *impl_from_IGlobalInterfaceTable(IGlob
|
|||
return CONTAINING_RECORD(iface, StdGlobalInterfaceTableImpl, IGlobalInterfaceTable_iface);
|
||||
}
|
||||
|
||||
/** This destroys it again. It should revoke all the held interfaces first **/
|
||||
static void StdGlobalInterfaceTable_Destroy(void* This)
|
||||
{
|
||||
TRACE("(%p)\n", This);
|
||||
FIXME("Revoke held interfaces here\n");
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
StdGlobalInterfaceTableInstance = NULL;
|
||||
}
|
||||
|
||||
/***
|
||||
* A helper function to traverse the list and find the entry that matches the cookie.
|
||||
* Returns NULL if not found. Must be called inside git_section critical section.
|
||||
|
@ -150,25 +139,13 @@ StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface,
|
|||
static ULONG WINAPI
|
||||
StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface)
|
||||
{
|
||||
StdGlobalInterfaceTableImpl* const This = impl_from_IGlobalInterfaceTable(iface);
|
||||
|
||||
/* InterlockedIncrement(&This->ref); */
|
||||
return This->ref;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface)
|
||||
{
|
||||
StdGlobalInterfaceTableImpl* const This = impl_from_IGlobalInterfaceTable(iface);
|
||||
|
||||
/* InterlockedDecrement(&This->ref); */
|
||||
if (This->ref == 0) {
|
||||
/* Hey ho, it's time to go, so long again 'till next weeks show! */
|
||||
StdGlobalInterfaceTable_Destroy(This);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return This->ref;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -206,7 +183,12 @@ StdGlobalInterfaceTable_RegisterInterfaceInGlobal(
|
|||
IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
|
||||
|
||||
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
|
||||
if (entry == NULL) return E_OUTOFMEMORY;
|
||||
if (!entry)
|
||||
{
|
||||
CoReleaseMarshalData(stream);
|
||||
IStream_Release(stream);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&git_section);
|
||||
|
||||
|
@ -299,7 +281,7 @@ StdGlobalInterfaceTable_GetInterfaceFromGlobal(
|
|||
hres = CoUnmarshalInterface(stream, riid, ppv);
|
||||
IStream_Release(stream);
|
||||
|
||||
if (hres) {
|
||||
if (hres != S_OK) {
|
||||
WARN("Failed to unmarshal stream\n");
|
||||
return hres;
|
||||
}
|
||||
|
@ -314,8 +296,8 @@ static HRESULT WINAPI
|
|||
GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(riid,&IID_IUnknown) ||
|
||||
IsEqualIID(riid,&IID_IGlobalInterfaceTable))
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IClassFactory))
|
||||
{
|
||||
*ppv = iface;
|
||||
return S_OK;
|
||||
|
@ -338,9 +320,8 @@ GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,
|
|||
REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
if (IsEqualIID(riid,&IID_IGlobalInterfaceTable)) {
|
||||
if (StdGlobalInterfaceTableInstance == NULL)
|
||||
StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct();
|
||||
return IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, riid, ppv);
|
||||
IGlobalInterfaceTable *git = get_std_git();
|
||||
return IGlobalInterfaceTable_QueryInterface(git, riid, ppv);
|
||||
}
|
||||
|
||||
FIXME("(%s), not supported.\n",debugstr_guid(riid));
|
||||
|
@ -361,11 +342,11 @@ static const IClassFactoryVtbl GITClassFactoryVtbl = {
|
|||
GITCF_LockServer
|
||||
};
|
||||
|
||||
static const IClassFactoryVtbl *PGITClassFactoryVtbl = &GITClassFactoryVtbl;
|
||||
static IClassFactory git_classfactory = { &GITClassFactoryVtbl };
|
||||
|
||||
HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv)
|
||||
{
|
||||
*ppv = &PGITClassFactoryVtbl;
|
||||
*ppv = &git_classfactory;
|
||||
TRACE("Returning GIT classfactory\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -381,19 +362,46 @@ static const IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl =
|
|||
StdGlobalInterfaceTable_GetInterfaceFromGlobal
|
||||
};
|
||||
|
||||
/** This function constructs the GIT. It should only be called once **/
|
||||
void* StdGlobalInterfaceTable_Construct(void)
|
||||
IGlobalInterfaceTable* get_std_git(void)
|
||||
{
|
||||
StdGlobalInterfaceTableImpl* newGIT;
|
||||
if (!std_git)
|
||||
{
|
||||
StdGlobalInterfaceTableImpl* newGIT;
|
||||
|
||||
newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
|
||||
if (newGIT == 0) return newGIT;
|
||||
newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));
|
||||
if (!newGIT) return NULL;
|
||||
|
||||
newGIT->IGlobalInterfaceTable_iface.lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;
|
||||
newGIT->ref = 1; /* Initialise the reference count */
|
||||
list_init(&newGIT->list);
|
||||
newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */
|
||||
TRACE("Created the GIT at %p\n", newGIT);
|
||||
newGIT->IGlobalInterfaceTable_iface.lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;
|
||||
list_init(&newGIT->list);
|
||||
newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */
|
||||
|
||||
return (void*)newGIT;
|
||||
if (InterlockedCompareExchangePointer((void**)&std_git, &newGIT->IGlobalInterfaceTable_iface, NULL))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, newGIT);
|
||||
}
|
||||
else
|
||||
TRACE("Created the GIT at %p\n", newGIT);
|
||||
}
|
||||
|
||||
return std_git;
|
||||
}
|
||||
|
||||
void release_std_git(void)
|
||||
{
|
||||
StdGlobalInterfaceTableImpl *git;
|
||||
StdGITEntry *entry, *entry2;
|
||||
|
||||
if (!std_git) return;
|
||||
|
||||
git = impl_from_IGlobalInterfaceTable(std_git);
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &git->list, StdGITEntry, entry)
|
||||
{
|
||||
list_remove(&entry->entry);
|
||||
|
||||
CoReleaseMarshalData(entry->stream);
|
||||
IStream_Release(entry->stream);
|
||||
HeapFree(GetProcessHeap(), 0, entry);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, git);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ static int SetSpyedBlockTableLength ( DWORD NewLength )
|
|||
LPVOID *NewSpyedBlocks;
|
||||
|
||||
if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(LMEM_ZEROINIT, NewLength * sizeof(PVOID));
|
||||
else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT);
|
||||
else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT | LMEM_MOVEABLE);
|
||||
if (NewSpyedBlocks) {
|
||||
Malloc32.SpyedBlocks = NewSpyedBlocks;
|
||||
Malloc32.SpyedBlockTableLength = NewLength;
|
||||
|
@ -220,13 +220,16 @@ static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
|
|||
IMallocSpy_Release(Malloc32.pSpy);
|
||||
Malloc32.SpyReleasePending = FALSE;
|
||||
Malloc32.pSpy = NULL;
|
||||
LeaveCriticalSection(&IMalloc32_SpyCS);
|
||||
}
|
||||
|
||||
if (0==cb) {
|
||||
/* PreRealloc can force Realloc to fail */
|
||||
LeaveCriticalSection(&IMalloc32_SpyCS);
|
||||
/* PreRealloc can force Realloc to fail */
|
||||
if (Malloc32.pSpy)
|
||||
LeaveCriticalSection(&IMalloc32_SpyCS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pv = pRealMemory;
|
||||
}
|
||||
|
||||
|
|
|
@ -1440,6 +1440,7 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
|
|||
|
||||
if (!(stubmgr = get_stub_manager(apt, stdobjref.oid)))
|
||||
{
|
||||
apartment_release(apt);
|
||||
ERR("could not map object ID to stub manager, oxid=%s, oid=%s\n",
|
||||
wine_dbgstr_longlong(stdobjref.oxid), wine_dbgstr_longlong(stdobjref.oid));
|
||||
return RPC_E_INVALID_OBJREF;
|
||||
|
|
|
@ -884,11 +884,6 @@ HRESULT WINAPI OleRegGetMiscStatus(
|
|||
HKEY aspectKey;
|
||||
LONG result;
|
||||
|
||||
/*
|
||||
* Initialize the out parameter.
|
||||
*/
|
||||
*pdwStatus = 0;
|
||||
|
||||
/*
|
||||
* Build the key name we're looking for
|
||||
*/
|
||||
|
@ -899,6 +894,10 @@ HRESULT WINAPI OleRegGetMiscStatus(
|
|||
|
||||
TRACE("(%s, %d, %p)\n", debugstr_w(keyName), dwAspect, pdwStatus);
|
||||
|
||||
if (!pdwStatus) return E_INVALIDARG;
|
||||
|
||||
*pdwStatus = 0;
|
||||
|
||||
/*
|
||||
* Open the class id Key
|
||||
*/
|
||||
|
@ -913,7 +912,7 @@ HRESULT WINAPI OleRegGetMiscStatus(
|
|||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(clsidKey);
|
||||
return REGDB_E_READREGDB;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
@ stdcall CLIPFORMAT_UserSize(ptr long ptr)
|
||||
@ stdcall CLIPFORMAT_UserUnmarshal(ptr ptr ptr)
|
||||
@ stdcall CLSIDFromProgID(wstr ptr)
|
||||
@ stdcall CLSIDFromProgIDEx(wstr ptr)
|
||||
@ stdcall CLSIDFromString(wstr ptr)
|
||||
@ stdcall CoAddRefServerProcess()
|
||||
@ stdcall CoAllowSetForegroundWindow(ptr ptr)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
//#include "rpc.h"
|
||||
//#include "winerror.h"
|
||||
//#include "winreg.h"
|
||||
#include <servprov.h>
|
||||
#include <wine/unicode.h>
|
||||
|
||||
#include "compobj_private.h"
|
||||
|
@ -1521,7 +1522,7 @@ static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
|
|||
|
||||
/* if IRpcStubBuffer_Invoke fails, we should raise an exception to tell
|
||||
* the RPC runtime that the call failed */
|
||||
if (hr) RpcRaiseException(hr);
|
||||
if (hr != S_OK) RpcRaiseException(hr);
|
||||
}
|
||||
|
||||
/* stub registration */
|
||||
|
@ -1658,6 +1659,7 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process)
|
|||
DWORD size = (MAX_PATH+1) * sizeof(WCHAR);
|
||||
STARTUPINFOW sinfo;
|
||||
PROCESS_INFORMATION pinfo;
|
||||
LONG ret;
|
||||
|
||||
hres = COM_OpenKeyForCLSID(rclsid, wszLocalServer32, KEY_READ, &key);
|
||||
if (FAILED(hres)) {
|
||||
|
@ -1665,9 +1667,9 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process)
|
|||
return hres;
|
||||
}
|
||||
|
||||
hres = RegQueryValueExW(key, NULL, NULL, NULL, (LPBYTE)command, &size);
|
||||
ret = RegQueryValueExW(key, NULL, NULL, NULL, (LPBYTE)command, &size);
|
||||
RegCloseKey(key);
|
||||
if (hres) {
|
||||
if (ret) {
|
||||
WARN("No default value for LocalServer32 key\n");
|
||||
return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
|
||||
}
|
||||
|
@ -1809,6 +1811,7 @@ HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
|
|||
LARGE_INTEGER seekto;
|
||||
ULARGE_INTEGER newpos;
|
||||
int tries = 0;
|
||||
IServiceProvider *local_server;
|
||||
|
||||
static const int MAXTRIES = 30; /* 30 seconds */
|
||||
|
||||
|
@ -1862,14 +1865,17 @@ HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
|
|||
return E_NOINTERFACE;
|
||||
|
||||
hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
|
||||
if (hres) return hres;
|
||||
if (hres != S_OK) return hres;
|
||||
hres = IStream_Write(pStm,marshalbuffer,bufferlen,&res);
|
||||
if (hres) goto out;
|
||||
if (hres != S_OK) goto out;
|
||||
seekto.u.LowPart = 0;seekto.u.HighPart = 0;
|
||||
hres = IStream_Seek(pStm,seekto,STREAM_SEEK_SET,&newpos);
|
||||
|
||||
TRACE("unmarshalling classfactory\n");
|
||||
hres = CoUnmarshalInterface(pStm,&IID_IClassFactory,ppv);
|
||||
TRACE("unmarshalling local server\n");
|
||||
hres = CoUnmarshalInterface(pStm, &IID_IServiceProvider, (void**)&local_server);
|
||||
if(SUCCEEDED(hres))
|
||||
hres = IServiceProvider_QueryService(local_server, rclsid, iid, ppv);
|
||||
IServiceProvider_Release(local_server);
|
||||
out:
|
||||
IStream_Release(pStm);
|
||||
return hres;
|
||||
|
@ -1920,50 +1926,38 @@ static DWORD WINAPI local_server_thread(LPVOID param)
|
|||
DWORD ret;
|
||||
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
if (ret != WAIT_OBJECT_0)
|
||||
{
|
||||
CloseHandle(hPipe);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* client already connected isn't an error */
|
||||
else if (error != ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
ERR("ConnectNamedPipe failed with error %d\n", GetLastError());
|
||||
CloseHandle(hPipe);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("marshalling IClassFactory to client\n");
|
||||
TRACE("marshalling LocalServer to client\n");
|
||||
|
||||
hres = IStream_Stat(pStm,&ststg,STATFLAG_NONAME);
|
||||
if (hres)
|
||||
{
|
||||
CloseHandle(hPipe);
|
||||
CloseHandle(pipe_event);
|
||||
return hres;
|
||||
}
|
||||
if (hres != S_OK)
|
||||
break;
|
||||
|
||||
seekto.u.LowPart = 0;
|
||||
seekto.u.HighPart = 0;
|
||||
hres = IStream_Seek(pStm,seekto,STREAM_SEEK_SET,&newpos);
|
||||
if (hres) {
|
||||
if (hres != S_OK) {
|
||||
FIXME("IStream_Seek failed, %x\n",hres);
|
||||
CloseHandle(hPipe);
|
||||
CloseHandle(pipe_event);
|
||||
return hres;
|
||||
break;
|
||||
}
|
||||
|
||||
buflen = ststg.cbSize.u.LowPart;
|
||||
buffer = HeapAlloc(GetProcessHeap(),0,buflen);
|
||||
|
||||
hres = IStream_Read(pStm,buffer,buflen,&res);
|
||||
if (hres) {
|
||||
if (hres != S_OK) {
|
||||
FIXME("Stream Read failed, %x\n",hres);
|
||||
CloseHandle(hPipe);
|
||||
CloseHandle(pipe_event);
|
||||
HeapFree(GetProcessHeap(),0,buffer);
|
||||
return hres;
|
||||
break;
|
||||
}
|
||||
|
||||
WriteFile(hPipe,buffer,buflen,&res,&ovl);
|
||||
|
@ -1972,27 +1966,27 @@ static DWORD WINAPI local_server_thread(LPVOID param)
|
|||
|
||||
FlushFileBuffers(hPipe);
|
||||
DisconnectNamedPipe(hPipe);
|
||||
TRACE("done marshalling IClassFactory\n");
|
||||
TRACE("done marshalling LocalServer\n");
|
||||
|
||||
if (!multi_use)
|
||||
{
|
||||
TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
|
||||
CloseHandle(hPipe);
|
||||
break;
|
||||
}
|
||||
new_pipe = CreateNamedPipeW( pipefn, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
|
||||
4096, 4096, 500 /* 0.5 second timeout */, NULL );
|
||||
CloseHandle(hPipe);
|
||||
if (new_pipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
|
||||
CloseHandle(pipe_event);
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
CloseHandle(hPipe);
|
||||
hPipe = new_pipe;
|
||||
}
|
||||
|
||||
CloseHandle(pipe_event);
|
||||
CloseHandle(hPipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,40 +43,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(storage);
|
||||
|
||||
|
||||
/***
|
||||
* This is the destructor of the StgStreamImpl class.
|
||||
*
|
||||
* This method will clean-up all the resources used-up by the given StgStreamImpl
|
||||
* class. The pointer passed-in to this function will be freed and will not
|
||||
* be valid anymore.
|
||||
*/
|
||||
static void StgStreamImpl_Destroy(StgStreamImpl* This)
|
||||
{
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
/*
|
||||
* Release the reference we are holding on the parent storage.
|
||||
* IStorage_Release(&This->parentStorage->IStorage_iface);
|
||||
*
|
||||
* No, don't do this. Some apps call IStorage_Release without
|
||||
* calling IStream_Release first. If we grab a reference the
|
||||
* file is not closed, and the app fails when it tries to
|
||||
* reopen the file (Easy-PC, for example). Just inform the
|
||||
* storage that we have closed the stream
|
||||
*/
|
||||
|
||||
if(This->parentStorage) {
|
||||
|
||||
StorageBaseImpl_RemoveStream(This->parentStorage, This);
|
||||
|
||||
}
|
||||
|
||||
This->parentStorage = 0;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
/***
|
||||
* This implements the IUnknown method QueryInterface for this
|
||||
* class
|
||||
|
@ -126,17 +92,27 @@ static ULONG WINAPI StgStreamImpl_Release(
|
|||
IStream* iface)
|
||||
{
|
||||
StgStreamImpl* This = impl_from_IStream(iface);
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
ULONG ref;
|
||||
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
/*
|
||||
* If the reference count goes down to 0, perform suicide.
|
||||
*/
|
||||
if (ref==0)
|
||||
if (!ref)
|
||||
{
|
||||
StgStreamImpl_Destroy(This);
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
/*
|
||||
* Release the reference we are holding on the parent storage.
|
||||
* IStorage_Release(&This->parentStorage->IStorage_iface);
|
||||
*
|
||||
* No, don't do this. Some apps call IStorage_Release without
|
||||
* calling IStream_Release first. If we grab a reference the
|
||||
* file is not closed, and the app fails when it tries to
|
||||
* reopen the file (Easy-PC, for example). Just inform the
|
||||
* storage that we have closed the stream
|
||||
*/
|
||||
|
||||
if (This->parentStorage)
|
||||
StorageBaseImpl_RemoveStream(This->parentStorage, This);
|
||||
This->parentStorage = 0;
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
|
|
|
@ -71,6 +71,11 @@ static inline StorageBaseImpl *impl_from_IStorage( IStorage *iface )
|
|||
return CONTAINING_RECORD(iface, StorageBaseImpl, IStorage_iface);
|
||||
}
|
||||
|
||||
static inline StorageBaseImpl *impl_from_IDirectWriterLock( IDirectWriterLock *iface )
|
||||
{
|
||||
return CONTAINING_RECORD(iface, StorageBaseImpl, IDirectWriterLock_iface);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Storage32InternalImpl definitions.
|
||||
*
|
||||
|
@ -100,7 +105,7 @@ static StorageInternalImpl* StorageInternalImpl_Construct(StorageBaseImpl* paren
|
|||
static void StorageImpl_Destroy(StorageBaseImpl* iface);
|
||||
static void StorageImpl_Invalidate(StorageBaseImpl* iface);
|
||||
static HRESULT StorageImpl_Flush(StorageBaseImpl* iface);
|
||||
static BOOL StorageImpl_ReadBigBlock(StorageImpl* This, ULONG blockIndex, void* buffer);
|
||||
static HRESULT StorageImpl_ReadBigBlock(StorageImpl* This, ULONG blockIndex, void* buffer, ULONG *read );
|
||||
static BOOL StorageImpl_WriteBigBlock(StorageImpl* This, ULONG blockIndex, const void* buffer);
|
||||
static void StorageImpl_SetNextBlockInChain(StorageImpl* This, ULONG blockIndex, ULONG nextBlock);
|
||||
static HRESULT StorageImpl_LoadFileHeader(StorageImpl* This);
|
||||
|
@ -380,6 +385,11 @@ static HRESULT WINAPI StorageBaseImpl_QueryInterface(
|
|||
{
|
||||
*ppvObject = &This->IPropertySetStorage_iface;
|
||||
}
|
||||
/* locking interface is reported for writer only */
|
||||
else if (IsEqualGUID(&IID_IDirectWriterLock, riid) && This->lockingrole == SWMR_Writer)
|
||||
{
|
||||
*ppvObject = &This->IDirectWriterLock_iface;
|
||||
}
|
||||
else
|
||||
return E_NOINTERFACE;
|
||||
|
||||
|
@ -722,9 +732,6 @@ static HRESULT WINAPI StorageBaseImpl_EnumElements(
|
|||
if (newEnum)
|
||||
{
|
||||
*ppenum = &newEnum->IEnumSTATSTG_iface;
|
||||
|
||||
IEnumSTATSTG_AddRef(*ppenum);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -2605,9 +2612,7 @@ static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index,
|
|||
stream = *StorageImpl_GetCachedBlockChainStream(This, index);
|
||||
if (!stream) return E_OUTOFMEMORY;
|
||||
|
||||
hr = BlockChainStream_WriteAt(stream, offset, size, buffer, bytesWritten);
|
||||
|
||||
return hr;
|
||||
return BlockChainStream_WriteAt(stream, offset, size, buffer, bytesWritten);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2648,6 +2653,55 @@ static HRESULT StorageImpl_GetFilename(StorageBaseImpl* iface, LPWSTR *result)
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI directwriterlock_QueryInterface(IDirectWriterLock *iface, REFIID riid, void **obj)
|
||||
{
|
||||
StorageBaseImpl *This = impl_from_IDirectWriterLock(iface);
|
||||
return IStorage_QueryInterface(&This->IStorage_iface, riid, obj);
|
||||
}
|
||||
|
||||
static ULONG WINAPI directwriterlock_AddRef(IDirectWriterLock *iface)
|
||||
{
|
||||
StorageBaseImpl *This = impl_from_IDirectWriterLock(iface);
|
||||
return IStorage_AddRef(&This->IStorage_iface);
|
||||
}
|
||||
|
||||
static ULONG WINAPI directwriterlock_Release(IDirectWriterLock *iface)
|
||||
{
|
||||
StorageBaseImpl *This = impl_from_IDirectWriterLock(iface);
|
||||
return IStorage_Release(&This->IStorage_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI directwriterlock_WaitForWriteAccess(IDirectWriterLock *iface, DWORD timeout)
|
||||
{
|
||||
StorageBaseImpl *This = impl_from_IDirectWriterLock(iface);
|
||||
FIXME("(%p)->(%d): stub\n", This, timeout);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI directwriterlock_ReleaseWriteAccess(IDirectWriterLock *iface)
|
||||
{
|
||||
StorageBaseImpl *This = impl_from_IDirectWriterLock(iface);
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI directwriterlock_HaveWriteAccess(IDirectWriterLock *iface)
|
||||
{
|
||||
StorageBaseImpl *This = impl_from_IDirectWriterLock(iface);
|
||||
FIXME("(%p): stub\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const IDirectWriterLockVtbl DirectWriterLockVtbl =
|
||||
{
|
||||
directwriterlock_QueryInterface,
|
||||
directwriterlock_AddRef,
|
||||
directwriterlock_Release,
|
||||
directwriterlock_WaitForWriteAccess,
|
||||
directwriterlock_ReleaseWriteAccess,
|
||||
directwriterlock_HaveWriteAccess
|
||||
};
|
||||
|
||||
/*
|
||||
* Virtual function table for the IStorage32Impl class.
|
||||
*/
|
||||
|
@ -2719,11 +2773,19 @@ static HRESULT StorageImpl_Construct(
|
|||
|
||||
This->base.IStorage_iface.lpVtbl = &Storage32Impl_Vtbl;
|
||||
This->base.IPropertySetStorage_iface.lpVtbl = &IPropertySetStorage_Vtbl;
|
||||
This->base.IDirectWriterLock_iface.lpVtbl = &DirectWriterLockVtbl;
|
||||
This->base.baseVtbl = &StorageImpl_BaseVtbl;
|
||||
This->base.openFlags = (openFlags & ~STGM_CREATE);
|
||||
This->base.ref = 1;
|
||||
This->base.create = create;
|
||||
|
||||
if (openFlags == (STGM_DIRECT_SWMR|STGM_READWRITE|STGM_SHARE_DENY_WRITE))
|
||||
This->base.lockingrole = SWMR_Writer;
|
||||
else if (openFlags == (STGM_DIRECT_SWMR|STGM_READ|STGM_SHARE_DENY_NONE))
|
||||
This->base.lockingrole = SWMR_Reader;
|
||||
else
|
||||
This->base.lockingrole = SWMR_None;
|
||||
|
||||
This->base.reverted = 0;
|
||||
|
||||
/*
|
||||
|
@ -2941,7 +3003,7 @@ end:
|
|||
}
|
||||
else
|
||||
{
|
||||
StorageImpl_Flush((StorageBaseImpl*)This);
|
||||
StorageImpl_Flush(&This->base);
|
||||
*result = This;
|
||||
}
|
||||
|
||||
|
@ -2981,9 +3043,9 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface)
|
|||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
static HRESULT StorageImpl_Flush(StorageBaseImpl* iface)
|
||||
static HRESULT StorageImpl_Flush(StorageBaseImpl *storage)
|
||||
{
|
||||
StorageImpl *This = (StorageImpl*) iface;
|
||||
StorageImpl *This = (StorageImpl*)storage;
|
||||
int i;
|
||||
HRESULT hr;
|
||||
TRACE("(%p)\n", This);
|
||||
|
@ -3018,12 +3080,12 @@ static ULONG StorageImpl_GetNextFreeBigBlock(
|
|||
{
|
||||
ULONG depotBlockIndexPos;
|
||||
BYTE depotBuffer[MAX_BIG_BLOCK_SIZE];
|
||||
BOOL success;
|
||||
ULONG depotBlockOffset;
|
||||
ULONG blocksPerDepot = This->bigBlockSize / sizeof(ULONG);
|
||||
ULONG nextBlockIndex = BLOCK_SPECIAL;
|
||||
int depotIndex = 0;
|
||||
ULONG freeBlock = BLOCK_UNUSED;
|
||||
ULONG read;
|
||||
ULARGE_INTEGER neededSize;
|
||||
STATSTG statstg;
|
||||
|
||||
|
@ -3113,9 +3175,9 @@ static ULONG StorageImpl_GetNextFreeBigBlock(
|
|||
}
|
||||
}
|
||||
|
||||
success = StorageImpl_ReadBigBlock(This, depotBlockIndexPos, depotBuffer);
|
||||
StorageImpl_ReadBigBlock(This, depotBlockIndexPos, depotBuffer, &read);
|
||||
|
||||
if (success)
|
||||
if (read)
|
||||
{
|
||||
while ( ( (depotBlockOffset/sizeof(ULONG) ) < blocksPerDepot) &&
|
||||
( nextBlockIndex != BLOCK_UNUSED))
|
||||
|
@ -3195,7 +3257,7 @@ static ULONG Storage32Impl_GetExtDepotBlock(StorageImpl* This, ULONG depotIndex)
|
|||
{
|
||||
extBlockIndex = This->extBigBlockDepotLocations[extBlockCount];
|
||||
|
||||
StorageImpl_ReadBigBlock(This, extBlockIndex, depotBuffer);
|
||||
StorageImpl_ReadBigBlock(This, extBlockIndex, depotBuffer, NULL);
|
||||
|
||||
num_blocks = This->bigBlockSize / 4;
|
||||
|
||||
|
@ -3357,7 +3419,7 @@ static HRESULT StorageImpl_GetNextBlockInChain(
|
|||
ULONG depotBlockCount = offsetInDepot / This->bigBlockSize;
|
||||
ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize;
|
||||
BYTE depotBuffer[MAX_BIG_BLOCK_SIZE];
|
||||
BOOL success;
|
||||
ULONG read;
|
||||
ULONG depotBlockIndexPos;
|
||||
int index, num_blocks;
|
||||
|
||||
|
@ -3389,9 +3451,9 @@ static HRESULT StorageImpl_GetNextBlockInChain(
|
|||
depotBlockIndexPos = Storage32Impl_GetExtDepotBlock(This, depotBlockCount);
|
||||
}
|
||||
|
||||
success = StorageImpl_ReadBigBlock(This, depotBlockIndexPos, depotBuffer);
|
||||
StorageImpl_ReadBigBlock(This, depotBlockIndexPos, depotBuffer, &read);
|
||||
|
||||
if (!success)
|
||||
if (!read)
|
||||
return STG_E_READFAULT;
|
||||
|
||||
num_blocks = This->bigBlockSize / 4;
|
||||
|
@ -3784,20 +3846,17 @@ HRESULT StorageImpl_ReadRawDirEntry(StorageImpl *This, ULONG index, BYTE *buffer
|
|||
HRESULT StorageImpl_WriteRawDirEntry(StorageImpl *This, ULONG index, const BYTE *buffer)
|
||||
{
|
||||
ULARGE_INTEGER offset;
|
||||
HRESULT hr;
|
||||
ULONG bytesRead;
|
||||
|
||||
offset.u.HighPart = 0;
|
||||
offset.u.LowPart = index * RAW_DIRENTRY_SIZE;
|
||||
|
||||
hr = BlockChainStream_WriteAt(
|
||||
return BlockChainStream_WriteAt(
|
||||
This->rootBlockChain,
|
||||
offset,
|
||||
RAW_DIRENTRY_SIZE,
|
||||
buffer,
|
||||
&bytesRead);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -3969,35 +4028,37 @@ HRESULT StorageImpl_WriteDirEntry(
|
|||
DirRef index,
|
||||
const DirEntry* buffer)
|
||||
{
|
||||
BYTE currentEntry[RAW_DIRENTRY_SIZE];
|
||||
HRESULT writeRes;
|
||||
BYTE currentEntry[RAW_DIRENTRY_SIZE];
|
||||
|
||||
UpdateRawDirEntry(currentEntry, buffer);
|
||||
|
||||
writeRes = StorageImpl_WriteRawDirEntry(This, index, currentEntry);
|
||||
return writeRes;
|
||||
return StorageImpl_WriteRawDirEntry(This, index, currentEntry);
|
||||
}
|
||||
|
||||
static BOOL StorageImpl_ReadBigBlock(
|
||||
static HRESULT StorageImpl_ReadBigBlock(
|
||||
StorageImpl* This,
|
||||
ULONG blockIndex,
|
||||
void* buffer)
|
||||
void* buffer,
|
||||
ULONG* out_read)
|
||||
{
|
||||
ULARGE_INTEGER ulOffset;
|
||||
DWORD read=0;
|
||||
HRESULT hr;
|
||||
|
||||
ulOffset.u.HighPart = 0;
|
||||
ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex);
|
||||
|
||||
StorageImpl_ReadAt(This, ulOffset, buffer, This->bigBlockSize, &read);
|
||||
hr = StorageImpl_ReadAt(This, ulOffset, buffer, This->bigBlockSize, &read);
|
||||
|
||||
if (read && read < This->bigBlockSize)
|
||||
if (SUCCEEDED(hr) && read < This->bigBlockSize)
|
||||
{
|
||||
/* File ends during this block; fill the rest with 0's. */
|
||||
memset((LPBYTE)buffer+read, 0, This->bigBlockSize-read);
|
||||
}
|
||||
|
||||
return (read != 0);
|
||||
if (out_read) *out_read = read;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static BOOL StorageImpl_ReadDWordFromBigBlock(
|
||||
|
@ -5120,7 +5181,7 @@ static HRESULT TransactedSnapshotImpl_Construct(StorageBaseImpl *parentStorage,
|
|||
/* parentStorage already has 1 reference, which we take over here. */
|
||||
(*result)->transactedParent = parentStorage;
|
||||
|
||||
parentStorage->transactedChild = (StorageBaseImpl*)*result;
|
||||
parentStorage->transactedChild = &(*result)->base;
|
||||
|
||||
(*result)->base.storageDirEntry = TransactedSnapshotImpl_CreateStubEntry(*result, parentStorage->storageDirEntry);
|
||||
}
|
||||
|
@ -5132,7 +5193,7 @@ static HRESULT TransactedSnapshotImpl_Construct(StorageBaseImpl *parentStorage,
|
|||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr)) HeapFree(GetProcessHeap(), 0, (*result));
|
||||
if (FAILED(hr)) HeapFree(GetProcessHeap(), 0, *result);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -5539,36 +5600,30 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Clone(
|
|||
IEnumSTATSTG** ppenum)
|
||||
{
|
||||
IEnumSTATSTGImpl* const This = impl_from_IEnumSTATSTG(iface);
|
||||
|
||||
IEnumSTATSTGImpl* newClone;
|
||||
|
||||
if (This->parentStorage->reverted)
|
||||
return STG_E_REVERTED;
|
||||
|
||||
/*
|
||||
* Perform a sanity check on the parameters.
|
||||
*/
|
||||
if (ppenum==0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
newClone = IEnumSTATSTGImpl_Construct(This->parentStorage,
|
||||
This->storageDirEntry);
|
||||
|
||||
if (!newClone)
|
||||
{
|
||||
*ppenum = NULL;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* The new clone enumeration must point to the same current node as
|
||||
* the ole one.
|
||||
* the old one.
|
||||
*/
|
||||
memcpy(newClone->name, This->name, sizeof(newClone->name));
|
||||
|
||||
*ppenum = &newClone->IEnumSTATSTG_iface;
|
||||
|
||||
/*
|
||||
* Don't forget to nail down a reference to the clone before
|
||||
* returning it.
|
||||
*/
|
||||
IEnumSTATSTGImpl_AddRef(*ppenum);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -5598,13 +5653,11 @@ static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
|
|||
|
||||
newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl));
|
||||
|
||||
if (newEnumeration!=0)
|
||||
if (newEnumeration)
|
||||
{
|
||||
/*
|
||||
* Set-up the virtual function table and reference count.
|
||||
*/
|
||||
newEnumeration->IEnumSTATSTG_iface.lpVtbl = &IEnumSTATSTGImpl_Vtbl;
|
||||
newEnumeration->ref = 0;
|
||||
newEnumeration->ref = 1;
|
||||
newEnumeration->name[0] = 0;
|
||||
|
||||
/*
|
||||
* We want to nail-down the reference to the storage in case the
|
||||
|
@ -5613,12 +5666,7 @@ static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
|
|||
newEnumeration->parentStorage = parentStorage;
|
||||
IStorage_AddRef(&newEnumeration->parentStorage->IStorage_iface);
|
||||
|
||||
newEnumeration->storageDirEntry = storageDirEntry;
|
||||
|
||||
/*
|
||||
* Make sure the current node of the iterator is the first one.
|
||||
*/
|
||||
IEnumSTATSTGImpl_Reset(&newEnumeration->IEnumSTATSTG_iface);
|
||||
newEnumeration->storageDirEntry = storageDirEntry;
|
||||
}
|
||||
|
||||
return newEnumeration;
|
||||
|
@ -6178,7 +6226,8 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This,
|
|||
{
|
||||
if (!cachedBlock->read)
|
||||
{
|
||||
if (!StorageImpl_ReadBigBlock(This->parentStorage, cachedBlock->sector, cachedBlock->data))
|
||||
ULONG read;
|
||||
if (FAILED(StorageImpl_ReadBigBlock(This->parentStorage, cachedBlock->sector, cachedBlock->data, &read)) && !read)
|
||||
return STG_E_READFAULT;
|
||||
|
||||
cachedBlock->read = 1;
|
||||
|
@ -6262,7 +6311,8 @@ HRESULT BlockChainStream_WriteAt(BlockChainStream* This,
|
|||
{
|
||||
if (!cachedBlock->read && bytesToWrite != This->parentStorage->bigBlockSize)
|
||||
{
|
||||
if (!StorageImpl_ReadBigBlock(This->parentStorage, cachedBlock->sector, cachedBlock->data))
|
||||
ULONG read;
|
||||
if (FAILED(StorageImpl_ReadBigBlock(This->parentStorage, cachedBlock->sector, cachedBlock->data, &read)) && !read)
|
||||
return STG_E_READFAULT;
|
||||
}
|
||||
|
||||
|
@ -7604,7 +7654,16 @@ HRESULT WINAPI StgOpenStorage(
|
|||
/*
|
||||
* Validate the sharing mode
|
||||
*/
|
||||
if (!(grfMode & (STGM_TRANSACTED|STGM_PRIORITY)))
|
||||
if (grfMode & STGM_DIRECT_SWMR)
|
||||
{
|
||||
if ((STGM_SHARE_MODE(grfMode) != STGM_SHARE_DENY_WRITE) &&
|
||||
(STGM_SHARE_MODE(grfMode) != STGM_SHARE_DENY_NONE))
|
||||
{
|
||||
hr = STG_E_INVALIDFLAG;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (!(grfMode & (STGM_TRANSACTED|STGM_PRIORITY)))
|
||||
switch(STGM_SHARE_MODE(grfMode))
|
||||
{
|
||||
case STGM_SHARE_EXCLUSIVE:
|
||||
|
@ -7622,10 +7681,10 @@ HRESULT WINAPI StgOpenStorage(
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* shared reading requires transacted mode */
|
||||
/* shared reading requires transacted or single writer mode */
|
||||
if( STGM_SHARE_MODE(grfMode) == STGM_SHARE_DENY_WRITE &&
|
||||
STGM_ACCESS_MODE(grfMode) == STGM_READWRITE &&
|
||||
!(grfMode&STGM_TRANSACTED) )
|
||||
!(grfMode & STGM_TRANSACTED) && !(grfMode & STGM_DIRECT_SWMR))
|
||||
{
|
||||
hr = STG_E_INVALIDFLAG;
|
||||
goto end;
|
||||
|
|
|
@ -166,6 +166,12 @@ HRESULT FileLockBytesImpl_Construct(HANDLE hFile, DWORD openFlags, LPCWSTR pwcsN
|
|||
HRESULT STORAGE_CreateOleStream(IStorage*, DWORD) DECLSPEC_HIDDEN;
|
||||
HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName) DECLSPEC_HIDDEN;
|
||||
|
||||
enum swmr_mode
|
||||
{
|
||||
SWMR_None,
|
||||
SWMR_Writer,
|
||||
SWMR_Reader
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* StorageBaseImpl definitions.
|
||||
|
@ -180,6 +186,7 @@ struct StorageBaseImpl
|
|||
{
|
||||
IStorage IStorage_iface;
|
||||
IPropertySetStorage IPropertySetStorage_iface; /* interface for adding a properties stream */
|
||||
IDirectWriterLock IDirectWriterLock_iface;
|
||||
LONG ref;
|
||||
|
||||
/*
|
||||
|
@ -225,6 +232,7 @@ struct StorageBaseImpl
|
|||
* the transacted snapshot or cache.
|
||||
*/
|
||||
StorageBaseImpl *transactedChild;
|
||||
enum swmr_mode lockingrole;
|
||||
};
|
||||
|
||||
/* virtual methods for StorageBaseImpl objects */
|
||||
|
|
|
@ -176,6 +176,7 @@ struct ifstub *stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHL
|
|||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
|
||||
{
|
||||
struct stub_manager *sm;
|
||||
HRESULT hres;
|
||||
|
||||
assert( apt );
|
||||
|
||||
|
@ -221,6 +222,10 @@ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
|
|||
*/
|
||||
sm->extrefs = 0;
|
||||
|
||||
hres = IUnknown_QueryInterface(object, &IID_IExternalConnection, (void**)&sm->extern_conn);
|
||||
if(FAILED(hres))
|
||||
sm->extern_conn = NULL;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
sm->oid = apt->oidc++;
|
||||
list_add_head(&apt->stubmgrs, &sm->entry);
|
||||
|
@ -245,6 +250,9 @@ static void stub_manager_delete(struct stub_manager *m)
|
|||
stub_manager_delete_ifstub(m, ifstub);
|
||||
}
|
||||
|
||||
if(m->extern_conn)
|
||||
IExternalConnection_Release(m->extern_conn);
|
||||
|
||||
CoTaskMemFree(m->oxid_info.psa);
|
||||
IUnknown_Release(m->object);
|
||||
|
||||
|
@ -380,10 +388,13 @@ struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid)
|
|||
/* 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)
|
||||
{
|
||||
BOOL first_extern_ref;
|
||||
ULONG rc;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
||||
first_extern_ref = refs && !m->extrefs;
|
||||
|
||||
/* make sure we don't overflow extrefs */
|
||||
refs = min(refs, (ULONG_MAX-1 - m->extrefs));
|
||||
rc = (m->extrefs += refs);
|
||||
|
@ -395,12 +406,20 @@ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak
|
|||
|
||||
TRACE("added %u refs to %p (oid %s), rc is now %u\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
|
||||
|
||||
/*
|
||||
* NOTE: According to tests, creating a stub causes two AddConnection calls followed by
|
||||
* one ReleaseConnection call (with fLastReleaseCloses=FALSE).
|
||||
*/
|
||||
if(first_extern_ref && m->extern_conn)
|
||||
IExternalConnection_AddConnection(m->extern_conn, EXTCONN_STRONG, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* remove some external references */
|
||||
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases)
|
||||
{
|
||||
BOOL last_extern_ref;
|
||||
ULONG rc;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
@ -414,10 +433,15 @@ ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tablewea
|
|||
if (!last_unlock_releases)
|
||||
rc += m->weakrefs;
|
||||
|
||||
last_extern_ref = refs && !m->extrefs;
|
||||
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("removed %u refs from %p (oid %s), rc is now %u\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
|
||||
|
||||
if (last_extern_ref && m->extern_conn)
|
||||
IExternalConnection_ReleaseConnection(m->extern_conn, EXTCONN_STRONG, 0, TRUE /* FIXME: Use last_unlock releases? */);
|
||||
|
||||
if (rc == 0)
|
||||
stub_manager_int_release(m);
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ reactos/dll/win32/ntprint # Synced to Wine-1.7.1
|
|||
reactos/dll/win32/objsel # Synced to Wine-1.5.19
|
||||
reactos/dll/win32/odbc32 # Out of sync. Depends on port of Linux ODBC.
|
||||
reactos/dll/win32/odbccp32 # Synced to Wine-1.5.19
|
||||
reactos/dll/win32/ole32 # Synced to Wine-1.5.26
|
||||
reactos/dll/win32/ole32 # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/oleacc # Autosync
|
||||
reactos/dll/win32/oleaut32 # Synced to Wine-1.5.26
|
||||
reactos/dll/win32/olecli32 # Synced to Wine-1.5.19
|
||||
|
|
Loading…
Reference in a new issue