* Sync with Wine 1.7.1.
CORE-7469

svn path=/trunk/; revision=60354
This commit is contained in:
Amine Khaldi 2013-09-26 13:58:03 +00:00
parent fa44344f03
commit 01f85a4410
16 changed files with 467 additions and 253 deletions

View file

@ -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)

View file

@ -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();

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}
/*

View file

@ -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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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