mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Sync to Wine-20050310:
Jon Griffiths <jon_p_griffiths@yahoo.com> - Documentation spelling fixes. Mike McCormack <mike@codeweavers.com> - Implement and test IPropertySetStorage. - Fix more incorrect uses of STGM_ enumerations. - Add struct StorageBaseImpl at the start of derived structures instead of trying to keep the first members the same. - StgOpenStorage shouldn't open zero length storage files. - Shared reading of storage files requires STGM_TRANSACTED. - Test and fix grfMode handling in StgOpenDocfile. - Implement StgSetTimes. Robert Shearman <rob@codeweavers.com> - Better tracing. - Small cleanup of creation functions. - Rename apartment functions to become more object-oriented. - Rename register_ifstub to marshal_object to more accurately describe what it does. - Add new function, apartment_getoxid, to prepare for a possible future patch where remoting is started on demand. - Move marshaling state machine into stub manager from ifstub. - Add additional needed states for table-weak marshaling, as shown by tests. - Protect external reference count from underflows/overflows. - Make COM use the RPC runtime as the backend for RPC calls. Based on a patch by Ove Ksven. - Invoke objects in STA's in the correct thread by sending messages to the hidden apartment window. - Use I_RpcGetBuffer, instead of our own buffer routines to fix an occasional test crash caused by heap corruption. - Zero the memory block passed to RpcServerRegisterIfEx so we don't pass garbage in some of the fields we don't fill in. - Return the correct error code from create_server and fix two handle leaks. - TODO update. - Remove cruft left over from previous RPC backend implementation in the apartment structure. - Don't pass an IPID by value for proxy_manager_create_ifproxy. - Disable more of RPC_UnregisterInterface to prevent the RPC runtime using freed memory. - Rename various external RPC backend functions so that they all have the same "RPC_" prefix. - Reduce the timeout of the function that connects to a local server to 30s, like native. - Make each ifproxy have its own channel buffer to fix a bug where a proxy with multiple interfaces could invoke the wrong stub buffer on the server. - The Global Interface Table should do table-strong marshaling instead of normal marshaling so that an interface can be retrieved more than one time. Mike Hearn <mh@codeweavers.com> - Avoid infinite loop when doing a typelib marshalled IUnknown::QueryInterface by only doing an extra QI if requested IID is not equal to marshalled IID. Rob Shearman <rob@codeweavers.com> Mike Hearn <mh@codeweavers.com> - Add re-entrancy tests to the test suite. - Run RPCs on a new thread client side so we can pump the message loop. Juan Lang <juan_lang@yahoo.com> - Fix the calling convention of DllCanUnloadNow. - Move vtbl to end of file and get rid of unnecessary prototypes. - Implement StgCreatePropSetStg. Joris Huizer <jorishuizer@planet.nl> - A few memory checks avoiding memory leaks. Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Paul Vriens <Paul.Vriens@xs4all.nl> - Added some TRACE statements. svn path=/trunk/; revision=14083
This commit is contained in:
parent
8c43665c8d
commit
9a10a39940
19 changed files with 1483 additions and 1060 deletions
|
@ -34,6 +34,7 @@ C_SRCS = \
|
|||
regsvr.c \
|
||||
rpc.c \
|
||||
stg_bigblockfile.c \
|
||||
stg_prop.c \
|
||||
stg_stream.c \
|
||||
storage32.c \
|
||||
stubmanager.c
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
|
||||
/* For CoGetMalloc (MEMCTX_TASK is currently ignored) */
|
||||
#ifndef MEMCTX_TASK
|
||||
#define MEMCTX_TASK -1
|
||||
# define MEMCTX_TASK -1
|
||||
#endif
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
@ -799,7 +799,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
|
|||
* (Recall that in OleSetClipboard, we used SetClipboardData to
|
||||
* make all HGLOBAL formats supported by the source IDataObject
|
||||
* available using delayed rendering)
|
||||
* On receiving this mesage we must actually render the data in the
|
||||
* On receiving this message we must actually render the data in the
|
||||
* specified format and place it on the clipboard by calling the
|
||||
* SetClipboardData function.
|
||||
*/
|
||||
|
|
|
@ -30,12 +30,11 @@
|
|||
*
|
||||
* - Implement the service control manager (in rpcss) to keep track
|
||||
* of registered class objects: ISCM::ServerRegisterClsid et al
|
||||
* - Implement the OXID resolver so we don't need magic pipe names for
|
||||
* - Implement the OXID resolver so we don't need magic endpoint names for
|
||||
* clients and servers to meet up
|
||||
* - Flip our marshalling on top of the RPC runtime transport API,
|
||||
* so we no longer use named pipes to communicate
|
||||
* - Implement RPC thread affinity (should fix InstallShield painting
|
||||
* problems)
|
||||
*
|
||||
* - Pump the message loop during RPC calls.
|
||||
* - Call IMessageFilter functions.
|
||||
*
|
||||
* - Make all ole interface marshaling use NDR to be wire compatible with
|
||||
* native DCOM
|
||||
|
@ -163,7 +162,7 @@ static CRITICAL_SECTION_DEBUG dll_cs_debug =
|
|||
};
|
||||
static CRITICAL_SECTION csOpenDllList = { &dll_cs_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static const char aptWinClass[] = "WINE_OLE32_APT_CLASS";
|
||||
static const WCHAR wszAptWinClass[] = {'W','I','N','E','_','O','L','E','3','2','_','A','P','T','_','C','L','A','S','S',0};
|
||||
static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static void COMPOBJ_DLLList_Add(HANDLE hLibrary);
|
||||
|
@ -171,7 +170,7 @@ static void COMPOBJ_DllList_FreeUnused(int Timeout);
|
|||
|
||||
void COMPOBJ_InitProcess( void )
|
||||
{
|
||||
WNDCLASSA wclass;
|
||||
WNDCLASSW wclass;
|
||||
|
||||
/* Dispatching to the correct thread in an apartment is done through
|
||||
* window messages rather than RPC transports. When an interface is
|
||||
|
@ -183,15 +182,15 @@ void COMPOBJ_InitProcess( void )
|
|||
* was unmarshalled.
|
||||
*/
|
||||
memset(&wclass, 0, sizeof(wclass));
|
||||
wclass.lpfnWndProc = &COM_AptWndProc;
|
||||
wclass.lpfnWndProc = COM_AptWndProc;
|
||||
wclass.hInstance = OLE32_hInstance;
|
||||
wclass.lpszClassName = aptWinClass;
|
||||
RegisterClassA(&wclass);
|
||||
wclass.lpszClassName = wszAptWinClass;
|
||||
RegisterClassW(&wclass);
|
||||
}
|
||||
|
||||
void COMPOBJ_UninitProcess( void )
|
||||
{
|
||||
UnregisterClassA(aptWinClass, OLE32_hInstance);
|
||||
UnregisterClassW(wszAptWinClass, OLE32_hInstance);
|
||||
}
|
||||
|
||||
void COM_TlsDestroy()
|
||||
|
@ -239,7 +238,7 @@ static APARTMENT *apartment_construct(DWORD model)
|
|||
{
|
||||
/* FIXME: should be randomly generated by in an RPC call to rpcss */
|
||||
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId();
|
||||
apt->win = CreateWindowA(aptWinClass, NULL, 0,
|
||||
apt->win = CreateWindowW(wszAptWinClass, NULL, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, OLE32_hInstance, NULL);
|
||||
}
|
||||
|
@ -249,8 +248,6 @@ static APARTMENT *apartment_construct(DWORD model)
|
|||
apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe;
|
||||
}
|
||||
|
||||
apt->shutdown_event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
|
||||
|
||||
/* the locking here is not currently needed for the MTA case, but it
|
||||
|
@ -354,8 +351,6 @@ DWORD COM_ApartmentRelease(struct apartment *apt)
|
|||
if (apt->filter) IUnknown_Release(apt->filter);
|
||||
|
||||
DeleteCriticalSection(&apt->cs);
|
||||
SetEvent(apt->shutdown_event);
|
||||
CloseHandle(apt->shutdown_event);
|
||||
CloseHandle(apt->thread);
|
||||
HeapFree(GetProcessHeap(), 0, apt);
|
||||
}
|
||||
|
@ -425,10 +420,15 @@ HWND COM_GetApartmentWin(OXID oxid, BOOL ref)
|
|||
return apt->win;
|
||||
}
|
||||
|
||||
/* Currently inter-thread marshalling is not fully implemented, so this does nothing */
|
||||
static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||
switch (msg)
|
||||
{
|
||||
case DM_EXECUTERPC:
|
||||
return RPC_ExecuteCall((RPCOLEMESSAGE *)wParam, (IRpcStubBuffer *)lParam);
|
||||
default:
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -473,7 +473,7 @@ static void COMPOBJ_DLLList_Add(HANDLE hLibrary)
|
|||
static void COMPOBJ_DllList_FreeUnused(int Timeout)
|
||||
{
|
||||
OpenDll *curr, *next, *prev = NULL;
|
||||
typedef HRESULT(*DllCanUnloadNowFunc)(void);
|
||||
typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
|
||||
DllCanUnloadNowFunc DllCanUnloadNow;
|
||||
|
||||
TRACE("\n");
|
||||
|
@ -1629,7 +1629,7 @@ HRESULT WINAPI CoGetClassObject(
|
|||
/* Next try out of process */
|
||||
if (CLSCTX_LOCAL_SERVER & dwClsContext)
|
||||
{
|
||||
return create_marshalled_proxy(rclsid,iid,ppv);
|
||||
return RPC_GetLocalClassObject(rclsid,iid,ppv);
|
||||
}
|
||||
|
||||
/* Finally try remote: this requires networked DCOM (a lot of work) */
|
||||
|
|
|
@ -53,10 +53,12 @@ typedef struct apartment APARTMENT;
|
|||
|
||||
typedef enum ifstub_state
|
||||
{
|
||||
IFSTUB_STATE_NORMAL_MARSHALED,
|
||||
IFSTUB_STATE_NORMAL_UNMARSHALED,
|
||||
IFSTUB_STATE_TABLE_MARSHALED
|
||||
} IFSTUB_STATE;
|
||||
STUBSTATE_NORMAL_MARSHALED,
|
||||
STUBSTATE_NORMAL_UNMARSHALED,
|
||||
STUBSTATE_TABLE_WEAK_MARSHALED,
|
||||
STUBSTATE_TABLE_WEAK_UNMARSHALED,
|
||||
STUBSTATE_TABLE_STRONG,
|
||||
} STUB_STATE;
|
||||
|
||||
/* an interface stub */
|
||||
struct ifstub
|
||||
|
@ -66,7 +68,6 @@ struct ifstub
|
|||
IID iid; /* RO */
|
||||
IPID ipid; /* RO */
|
||||
IUnknown *iface; /* RO */
|
||||
IFSTUB_STATE state; /* CS stub_manager->lock */
|
||||
};
|
||||
|
||||
|
||||
|
@ -78,11 +79,12 @@ struct stub_manager
|
|||
CRITICAL_SECTION lock;
|
||||
APARTMENT *apt; /* owning apt (RO) */
|
||||
|
||||
ULONG extrefs; /* number of 'external' references (LOCK) */
|
||||
ULONG extrefs; /* number of 'external' references (CS lock) */
|
||||
ULONG refs; /* internal reference count (CS apt->cs) */
|
||||
OID oid; /* apartment-scoped unique identifier (RO) */
|
||||
IUnknown *object; /* the object we are managing the stub for (RO) */
|
||||
ULONG next_ipid; /* currently unused (LOCK) */
|
||||
STUB_STATE state; /* state machine (CS lock) */
|
||||
};
|
||||
|
||||
/* imported interface proxy */
|
||||
|
@ -95,6 +97,7 @@ struct ifproxy
|
|||
IPID ipid; /* imported interface ID (RO) */
|
||||
LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */
|
||||
DWORD refs; /* imported (public) references (CS parent->cs) */
|
||||
IRpcChannelBuffer *chan; /* channel to object (CS parent->cs) */
|
||||
};
|
||||
|
||||
/* imported object / proxy manager */
|
||||
|
@ -103,7 +106,6 @@ struct proxy_manager
|
|||
const IMultiQIVtbl *lpVtbl;
|
||||
struct apartment *parent; /* owning apartment (RO) */
|
||||
struct list entry; /* entry in apartment (CS parent->cs) */
|
||||
LPRPCCHANNELBUFFER chan; /* channel to object (CS cs) */
|
||||
OXID oxid; /* object exported ID (RO) */
|
||||
OID oid; /* object ID (RO) */
|
||||
struct list interfaces; /* imported interfaces (CS cs) */
|
||||
|
@ -130,11 +132,10 @@ struct apartment
|
|||
struct list proxies; /* imported objects (CS cs) */
|
||||
struct list stubmgrs; /* stub managers for exported objects (CS cs) */
|
||||
BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */
|
||||
LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */
|
||||
|
||||
/* FIXME: These should all be removed long term as they leak information that should be encapsulated */
|
||||
/* FIXME: OID's should be given out by RPCSS */
|
||||
OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */
|
||||
DWORD listenertid; /* id of apartment_listener_thread */
|
||||
HANDLE shutdown_event; /* event used to tell the client_dispatch_thread to shut down */
|
||||
};
|
||||
|
||||
/* this is what is stored in TEB->ReservedForOle */
|
||||
|
@ -146,59 +147,49 @@ struct oletls
|
|||
DWORD inits; /* number of times CoInitializeEx called */
|
||||
};
|
||||
|
||||
|
||||
/* Global Interface Table Functions */
|
||||
|
||||
extern void* StdGlobalInterfaceTable_Construct(void);
|
||||
extern void StdGlobalInterfaceTable_Destroy(void* self);
|
||||
extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv);
|
||||
extern void* StdGlobalInterfaceTableInstance;
|
||||
|
||||
/* FIXME: these shouldn't be needed, except for 16-bit functions */
|
||||
extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr);
|
||||
HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id);
|
||||
|
||||
extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
|
||||
|
||||
extern void* StdGlobalInterfaceTableInstance;
|
||||
|
||||
/* Standard Marshalling definitions */
|
||||
typedef struct _wine_marshal_id {
|
||||
OXID oxid; /* id of apartment */
|
||||
OID oid; /* id of stub manager */
|
||||
IPID ipid; /* id of interface pointer */
|
||||
} wine_marshal_id;
|
||||
|
||||
inline static BOOL
|
||||
MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) {
|
||||
return
|
||||
(mid1->oxid == mid2->oxid) &&
|
||||
(mid1->oid == mid2->oid) &&
|
||||
IsEqualGUID(&(mid1->ipid),&(mid2->ipid))
|
||||
;
|
||||
}
|
||||
|
||||
HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt);
|
||||
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
|
||||
|
||||
/* Stub Manager */
|
||||
|
||||
ULONG stub_manager_int_addref(struct stub_manager *This);
|
||||
ULONG stub_manager_int_release(struct stub_manager *This);
|
||||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object);
|
||||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object, MSHLFLAGS mshlflags);
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs);
|
||||
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs);
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal);
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid);
|
||||
struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid);
|
||||
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object);
|
||||
void apartment_disconnect_object(APARTMENT *apt, void *object);
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid);
|
||||
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid);
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m);
|
||||
BOOL stub_manager_is_table_marshaled(struct stub_manager *m);
|
||||
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs);
|
||||
HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags);
|
||||
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret);
|
||||
IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid);
|
||||
IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt);
|
||||
HRESULT start_apartment_remote_unknown(void);
|
||||
|
||||
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
|
||||
/* RPC Backend */
|
||||
|
||||
void start_apartment_listener_thread(void);
|
||||
|
||||
extern HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf);
|
||||
void RPC_StartLocalServer(REFCLSID clsid, IStream *stream);
|
||||
void RPC_StartRemoting(struct apartment *apt);
|
||||
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf);
|
||||
HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub);
|
||||
HRESULT RPC_RegisterInterface(REFIID riid);
|
||||
void RPC_UnregisterInterface(REFIID riid);
|
||||
void RPC_StartLocalServer(REFCLSID clsid, IStream *stream);
|
||||
HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
|
||||
|
||||
/* This function initialize the Running Object Table */
|
||||
HRESULT WINAPI RunningObjectTableImpl_Initialize(void);
|
||||
|
@ -209,12 +200,17 @@ HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void);
|
|||
/* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */
|
||||
int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable);
|
||||
|
||||
/* compobj.c */
|
||||
|
||||
/* Apartment Functions */
|
||||
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref);
|
||||
APARTMENT *COM_ApartmentFromTID(DWORD tid);
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt);
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt);
|
||||
|
||||
/* messages used by the apartment window (not compatible with native) */
|
||||
#define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = (RPCOLEMESSAGE *), LPARAM = (IRpcStubBuffer *) */
|
||||
|
||||
/*
|
||||
* Per-thread values are stored in the TEB on offset 0xF80,
|
||||
* see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
|
||||
|
|
|
@ -386,11 +386,10 @@ static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpFile(
|
|||
LPOLESTR szHelpFile)
|
||||
{
|
||||
_ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
|
||||
TRACE("(%p)\n",This);
|
||||
TRACE("(%p,%s)\n",This,debugstr_w(szHelpFile));
|
||||
if (This->bstrHelpFile != NULL)
|
||||
ERRORINFO_SysFreeString(This->bstrHelpFile);
|
||||
This->bstrHelpFile = ERRORINFO_SysAllocString(szHelpFile);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -399,9 +398,8 @@ static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpContext(
|
|||
DWORD dwHelpContext)
|
||||
{
|
||||
_ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
|
||||
TRACE("(%p)\n",This);
|
||||
TRACE("(%p,%ld)\n",This,dwHelpContext);
|
||||
This->m_dwHelpContext = dwHelpContext;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void**
|
|||
{
|
||||
FileMonikerImpl *This = (FileMonikerImpl *)iface;
|
||||
|
||||
TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
|
||||
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
|
||||
|
||||
/* Perform a sanity check on the parameters.*/
|
||||
if ( (This==0) || (ppvObject==0) )
|
||||
|
@ -223,7 +223,7 @@ ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)
|
|||
HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface,
|
||||
CLSID *pClassID)/* Pointer to CLSID of object */
|
||||
{
|
||||
TRACE("(%p,%p),stub!\n",iface,pClassID);
|
||||
TRACE("(%p,%p)\n",iface,pClassID);
|
||||
|
||||
if (pClassID==NULL)
|
||||
return E_POINTER;
|
||||
|
@ -473,7 +473,7 @@ HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPa
|
|||
static const WCHAR bkSlash[]={'\\',0};
|
||||
BYTE addBkSlash;
|
||||
|
||||
TRACE("(%p,%p)\n",This,lpszPathName);
|
||||
TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));
|
||||
|
||||
/* Initialize the virtual fgunction table. */
|
||||
This->lpvtbl1 = &VT_FileMonikerImpl;
|
||||
|
@ -566,7 +566,7 @@ HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,
|
|||
|
||||
*ppvResult=0;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
|
||||
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
||||
|
||||
if(pmkToLeft==NULL){
|
||||
|
||||
|
@ -673,7 +673,7 @@ HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
|
|||
IStorage *pstg=0;
|
||||
HRESULT res;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
|
||||
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
|
||||
|
||||
if (pmkToLeft==NULL){
|
||||
|
||||
|
@ -708,7 +708,7 @@ HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
|
|||
}
|
||||
else {
|
||||
|
||||
FIXME("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
|
||||
FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
@ -1243,6 +1243,8 @@ HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
|
|||
|
||||
strcpyW(*ppszDisplayName,This->filePathName);
|
||||
|
||||
TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -1283,7 +1285,7 @@ HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid
|
|||
|
||||
ICOM_THIS_From_IROTData(IMoniker, iface);
|
||||
|
||||
TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
|
||||
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
|
||||
|
||||
return FileMonikerImpl_QueryInterface(This, riid, ppvObject);
|
||||
}
|
||||
|
@ -1329,29 +1331,28 @@ HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
|
|||
******************************************************************************/
|
||||
HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
|
||||
{
|
||||
FileMonikerImpl* newFileMoniker = 0;
|
||||
HRESULT hr = E_FAIL;
|
||||
IID riid=IID_IMoniker;
|
||||
FileMonikerImpl* newFileMoniker;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p,%p)\n",lpszPathName,ppmk);
|
||||
TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk);
|
||||
|
||||
if (ppmk==NULL)
|
||||
if (!ppmk)
|
||||
return E_POINTER;
|
||||
|
||||
if(lpszPathName==NULL)
|
||||
if(!lpszPathName)
|
||||
return MK_E_SYNTAX;
|
||||
|
||||
*ppmk=0;
|
||||
*ppmk=NULL;
|
||||
|
||||
newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
|
||||
|
||||
if (newFileMoniker == 0)
|
||||
if (!newFileMoniker)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk);
|
||||
hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&IID_IMoniker,(void**)ppmk);
|
||||
else
|
||||
HeapFree(GetProcessHeap(),0,newFileMoniker);
|
||||
|
||||
|
|
|
@ -223,6 +223,7 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
|
|||
IStream* stream = NULL;
|
||||
HRESULT hres;
|
||||
StdGITEntry* entry;
|
||||
static const LARGE_INTEGER zero;
|
||||
|
||||
TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie);
|
||||
|
||||
|
@ -230,8 +231,18 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
|
|||
|
||||
/* marshal the interface */
|
||||
TRACE("About to marshal the interface\n");
|
||||
hres = CoMarshalInterThreadInterfaceInStream(riid, pUnk, &stream);
|
||||
|
||||
hres = CreateStreamOnHGlobal(0, TRUE, &stream);
|
||||
if (hres) return hres;
|
||||
hres = CoMarshalInterface(stream, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
|
||||
if (hres)
|
||||
{
|
||||
IStream_Release(stream);
|
||||
return hres;
|
||||
}
|
||||
|
||||
IStream_Seek(stream, zero, SEEK_SET, NULL);
|
||||
|
||||
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));
|
||||
if (entry == NULL) return E_OUTOFMEMORY;
|
||||
|
||||
|
@ -261,6 +272,7 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
|
|||
HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie) {
|
||||
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;
|
||||
StdGITEntry* entry;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("iface=%p, dwCookie=0x%x\n", iface, (UINT)dwCookie);
|
||||
|
||||
|
@ -271,6 +283,12 @@ HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfac
|
|||
}
|
||||
|
||||
/* Free the stream */
|
||||
hr = CoReleaseMarshalData(entry->stream);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
WARN("Failed to release marshal data, hr = 0x%08lx\n", hr);
|
||||
return hr;
|
||||
}
|
||||
IStream_Release(entry->stream);
|
||||
|
||||
/* chop entry out of the list, and free the memory */
|
||||
|
|
|
@ -156,7 +156,7 @@ HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void**
|
|||
{
|
||||
ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
|
||||
|
||||
TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
|
||||
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
|
||||
|
||||
/* Perform a sanity check on the parameters.*/
|
||||
if ( (This==0) || (ppvObject==0) )
|
||||
|
@ -221,7 +221,7 @@ ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
|
|||
******************************************************************************/
|
||||
HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
|
||||
{
|
||||
TRACE("(%p,%p),stub!\n",iface,pClassID);
|
||||
TRACE("(%p,%p)\n",iface,pClassID);
|
||||
|
||||
if (pClassID==NULL)
|
||||
return E_POINTER;
|
||||
|
@ -257,6 +257,8 @@ HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
|
|||
CHAR *itemNameA,*itemDelimiterA;
|
||||
ULONG bread;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
/* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
|
||||
|
||||
/* read item delimiter string length + 1 */
|
||||
|
@ -335,6 +337,8 @@ HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
|
|||
WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);
|
||||
WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);
|
||||
|
||||
TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE");
|
||||
|
||||
res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
|
||||
res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
|
||||
res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
|
||||
|
@ -381,7 +385,7 @@ HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDe
|
|||
static const OLECHAR emptystr[1];
|
||||
LPCOLESTR delim;
|
||||
|
||||
TRACE("(%p,%p)\n",This,lpszItem);
|
||||
TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem));
|
||||
|
||||
/* Initialize the virtual fgunction table. */
|
||||
This->lpvtbl1 = &VT_ItemMonikerImpl;
|
||||
|
@ -437,7 +441,7 @@ HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
|
|||
IID refid=IID_IOleItemContainer;
|
||||
IOleItemContainer *poic=0;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
|
||||
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
||||
|
||||
if(ppvResult ==NULL)
|
||||
return E_POINTER;
|
||||
|
@ -473,7 +477,7 @@ HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
|
|||
HRESULT res;
|
||||
IOleItemContainer *poic=0;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
|
||||
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
||||
|
||||
*ppvResult=0;
|
||||
|
||||
|
@ -781,6 +785,9 @@ HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
|
|||
HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
|
||||
{
|
||||
DWORD mkSys;
|
||||
|
||||
TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);
|
||||
|
||||
IMoniker_IsSystemMoniker(pmkOther,&mkSys);
|
||||
/* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
|
||||
/* to this moniker and returns MK_S_US */
|
||||
|
@ -841,6 +848,8 @@ HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
|
|||
lstrcpyW(*ppszDisplayName,This->itemDelimiter);
|
||||
lstrcatW(*ppszDisplayName,This->itemName);
|
||||
|
||||
TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -860,6 +869,8 @@ HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
|
|||
HRESULT res;
|
||||
ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
|
||||
|
||||
TRACE("%s\n", debugstr_w(pszDisplayName));
|
||||
|
||||
/* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
|
||||
if (pmkToLeft==NULL)
|
||||
|
||||
|
@ -955,15 +966,14 @@ HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
|
|||
******************************************************************************/
|
||||
HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
|
||||
{
|
||||
ItemMonikerImpl* newItemMoniker = 0;
|
||||
HRESULT hr = S_OK;
|
||||
IID riid=IID_IMoniker;
|
||||
ItemMonikerImpl* newItemMoniker;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
|
||||
TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);
|
||||
|
||||
newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
|
||||
|
||||
if (newItemMoniker == 0)
|
||||
if (!newItemMoniker)
|
||||
return STG_E_INSUFFICIENTMEMORY;
|
||||
|
||||
hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
|
||||
|
@ -974,5 +984,5 @@ HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONI
|
|||
return hr;
|
||||
}
|
||||
|
||||
return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);
|
||||
return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk);
|
||||
}
|
||||
|
|
|
@ -117,13 +117,15 @@ HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkn
|
|||
|
||||
stdobjref->oxid = apt->oxid;
|
||||
|
||||
/* FIXME: what happens if we register an interface twice with different
|
||||
* marshaling flags? */
|
||||
if ((manager = get_stub_manager_from_object(apt, obj)))
|
||||
TRACE("registering new ifstub on pre-existing manager\n");
|
||||
else
|
||||
{
|
||||
TRACE("constructing new stub manager\n");
|
||||
|
||||
manager = new_stub_manager(apt, obj);
|
||||
manager = new_stub_manager(apt, obj, mshlflags);
|
||||
if (!manager)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
@ -131,7 +133,7 @@ HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkn
|
|||
|
||||
tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK));
|
||||
|
||||
ifstub = stub_manager_new_ifstub(manager, stub, obj, riid, tablemarshal);
|
||||
ifstub = stub_manager_new_ifstub(manager, stub, obj, riid);
|
||||
if (!ifstub)
|
||||
{
|
||||
IRpcStubBuffer_Release(stub);
|
||||
|
@ -153,6 +155,9 @@ HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkn
|
|||
stub_manager_ext_addref(manager, 1);
|
||||
}
|
||||
|
||||
/* FIXME: check return value */
|
||||
RPC_RegisterInterface(riid);
|
||||
|
||||
stdobjref->ipid = ifstub->ipid;
|
||||
|
||||
stub_manager_int_release(manager);
|
||||
|
@ -372,12 +377,17 @@ static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
|
|||
return hr;
|
||||
}
|
||||
|
||||
/* should be called inside This->parent->cs critical section */
|
||||
static void ifproxy_disconnect(struct ifproxy * This)
|
||||
{
|
||||
ifproxy_release_public_refs(This);
|
||||
if (This->proxy) IRpcProxyBuffer_Disconnect(This->proxy);
|
||||
|
||||
IRpcChannelBuffer_Release(This->chan);
|
||||
This->chan = NULL;
|
||||
}
|
||||
|
||||
/* should be called in This->parent->cs critical section if it is an entry in parent's list */
|
||||
static void ifproxy_destroy(struct ifproxy * This)
|
||||
{
|
||||
TRACE("%p\n", This);
|
||||
|
@ -388,6 +398,12 @@ static void ifproxy_destroy(struct ifproxy * This)
|
|||
|
||||
list_remove(&This->entry);
|
||||
|
||||
if (This->chan)
|
||||
{
|
||||
IRpcChannelBuffer_Release(This->chan);
|
||||
This->chan = NULL;
|
||||
}
|
||||
|
||||
/* note: we don't call Release for This->proxy because its lifetime is
|
||||
* controlled by the return value from ClientIdentity_Release, which this
|
||||
* function is always called from */
|
||||
|
@ -397,7 +413,7 @@ static void ifproxy_destroy(struct ifproxy * This)
|
|||
|
||||
static HRESULT proxy_manager_construct(
|
||||
APARTMENT * apt, ULONG sorflags, OXID oxid, OID oid,
|
||||
IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager)
|
||||
struct proxy_manager ** proxy_manager)
|
||||
{
|
||||
struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||
if (!This) return E_OUTOFMEMORY;
|
||||
|
@ -423,9 +439,6 @@ static HRESULT proxy_manager_construct(
|
|||
* should store the STDOBJREF flags in the proxy manager. */
|
||||
This->sorflags = sorflags;
|
||||
|
||||
assert(channel);
|
||||
This->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
|
||||
|
||||
/* we create the IRemUnknown proxy on demand */
|
||||
This->remunk = NULL;
|
||||
|
||||
|
@ -473,8 +486,8 @@ static HRESULT proxy_manager_query_local_interface(struct proxy_manager * This,
|
|||
}
|
||||
|
||||
static HRESULT proxy_manager_create_ifproxy(
|
||||
struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs,
|
||||
struct ifproxy ** iif_out)
|
||||
struct proxy_manager * This, const IPID *ipid, REFIID riid, ULONG cPublicRefs,
|
||||
IRpcChannelBuffer * channel, struct ifproxy ** iif_out)
|
||||
{
|
||||
HRESULT hr;
|
||||
IPSFactoryBuffer * psfb;
|
||||
|
@ -484,11 +497,14 @@ static HRESULT proxy_manager_create_ifproxy(
|
|||
list_init(&ifproxy->entry);
|
||||
|
||||
ifproxy->parent = This;
|
||||
ifproxy->ipid = ipid;
|
||||
ifproxy->ipid = *ipid;
|
||||
ifproxy->iid = *riid;
|
||||
ifproxy->refs = cPublicRefs;
|
||||
ifproxy->proxy = NULL;
|
||||
|
||||
assert(channel);
|
||||
ifproxy->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
|
||||
|
||||
/* the IUnknown interface is special because it does not have a
|
||||
* proxy associated with the ifproxy as we handle IUnknown ourselves */
|
||||
if (IsEqualIID(riid, &IID_IUnknown))
|
||||
|
@ -517,7 +533,7 @@ static HRESULT proxy_manager_create_ifproxy(
|
|||
debugstr_guid(riid), hr);
|
||||
|
||||
if (hr == S_OK)
|
||||
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->chan);
|
||||
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, ifproxy->chan);
|
||||
}
|
||||
|
||||
/* get at least one external reference to the object to keep it alive */
|
||||
|
@ -532,7 +548,7 @@ static HRESULT proxy_manager_create_ifproxy(
|
|||
|
||||
*iif_out = ifproxy;
|
||||
TRACE("ifproxy %p created for IPID %s, interface %s with %lu public refs\n",
|
||||
ifproxy, debugstr_guid(&ipid), debugstr_guid(riid), cPublicRefs);
|
||||
ifproxy, debugstr_guid(ipid), debugstr_guid(riid), cPublicRefs);
|
||||
}
|
||||
else
|
||||
ifproxy_destroy(ifproxy);
|
||||
|
@ -579,11 +595,6 @@ static void proxy_manager_disconnect(struct proxy_manager * This)
|
|||
/* apartment is being destroyed so don't keep a pointer around to it */
|
||||
This->parent = NULL;
|
||||
|
||||
/* FIXME: will this still be necessary if/when we use a real RPC
|
||||
* channel? */
|
||||
IRpcChannelBuffer_Release(This->chan);
|
||||
This->chan = NULL;
|
||||
|
||||
LeaveCriticalSection(&This->cs);
|
||||
}
|
||||
|
||||
|
@ -671,7 +682,6 @@ static void proxy_manager_destroy(struct proxy_manager * This)
|
|||
}
|
||||
|
||||
if (This->remunk) IRemUnknown_Release(This->remunk);
|
||||
if (This->chan) IRpcChannelBuffer_Release(This->chan);
|
||||
|
||||
DeleteCriticalSection(&This->cs);
|
||||
|
||||
|
@ -792,8 +802,8 @@ StdMarshalImpl_MarshalInterface(
|
|||
return CO_E_NOTINITIALIZED;
|
||||
}
|
||||
|
||||
start_apartment_listener_thread(); /* just to be sure we have one running. */
|
||||
start_apartment_remote_unknown();
|
||||
/* make sure this apartment can be reached from other threads / processes */
|
||||
RPC_StartRemoting(apt);
|
||||
|
||||
hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk);
|
||||
if (hres != S_OK)
|
||||
|
@ -839,18 +849,9 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
|||
* object */
|
||||
if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
|
||||
{
|
||||
IRpcChannelBuffer *chanbuf;
|
||||
wine_marshal_id mid;
|
||||
|
||||
mid.oxid = stdobjref->oxid;
|
||||
mid.oid = stdobjref->oid;
|
||||
mid.ipid = stdobjref->ipid;
|
||||
|
||||
hr = PIPE_GetNewPipeBuf(&mid,&chanbuf);
|
||||
if (hr == S_OK)
|
||||
hr = proxy_manager_construct(apt, stdobjref->flags,
|
||||
stdobjref->oxid, stdobjref->oid,
|
||||
chanbuf, &proxy_manager);
|
||||
hr = proxy_manager_construct(apt, stdobjref->flags,
|
||||
stdobjref->oxid, stdobjref->oid,
|
||||
&proxy_manager);
|
||||
}
|
||||
else
|
||||
TRACE("proxy manager already created, using\n");
|
||||
|
@ -860,9 +861,14 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
|||
struct ifproxy * ifproxy;
|
||||
hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
|
||||
if (hr == E_NOINTERFACE)
|
||||
hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref->ipid,
|
||||
riid, stdobjref->cPublicRefs,
|
||||
&ifproxy);
|
||||
{
|
||||
IRpcChannelBuffer *chanbuf;
|
||||
hr = RPC_CreateClientChannel(&stdobjref->oxid, &stdobjref->ipid, &chanbuf);
|
||||
if (hr == S_OK)
|
||||
hr = proxy_manager_create_ifproxy(proxy_manager, &stdobjref->ipid,
|
||||
riid, stdobjref->cPublicRefs,
|
||||
chanbuf, &ifproxy);
|
||||
}
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
|
@ -911,7 +917,7 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
|
|||
hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv);
|
||||
|
||||
/* unref the ifstub. FIXME: only do this on success? */
|
||||
if (!stub_manager_is_table_marshaled(stubmgr, &stdobjref.ipid))
|
||||
if (!stub_manager_is_table_marshaled(stubmgr))
|
||||
stub_manager_ext_release(stubmgr, 1);
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
|
@ -927,7 +933,7 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
|
|||
{
|
||||
if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid)))
|
||||
{
|
||||
if (!stub_manager_notify_unmarshal(stubmgr, &stdobjref.ipid))
|
||||
if (!stub_manager_notify_unmarshal(stubmgr))
|
||||
hres = CO_E_OBJNOTCONNECTED;
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
|
@ -982,9 +988,7 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
|
|||
return RPC_E_INVALID_OBJREF;
|
||||
}
|
||||
|
||||
/* FIXME: don't release if table-weak and already unmarshaled an object */
|
||||
/* FIXME: this should also depend on stdobjref.cPublicRefs */
|
||||
stub_manager_ext_release(stubmgr, 1);
|
||||
stub_manager_release_marshal_data(stubmgr, stdobjref.cPublicRefs);
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
COM_ApartmentRelease(apt);
|
||||
|
@ -1418,11 +1422,19 @@ HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
|
|||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
hr = IUnknown_QueryInterface(object, &iid, ppv);
|
||||
if (hr)
|
||||
ERR("Couldn't query for interface %s, hr = 0x%08lx\n",
|
||||
debugstr_guid(riid), hr);
|
||||
IUnknown_Release(object);
|
||||
if (!IsEqualIID(riid, &iid))
|
||||
{
|
||||
TRACE("requested interface != marshalled interface, additional QI needed\n");
|
||||
hr = IUnknown_QueryInterface(object, &iid, ppv);
|
||||
if (hr)
|
||||
ERR("Couldn't query for interface %s, hr = 0x%08lx\n",
|
||||
debugstr_guid(riid), hr);
|
||||
IUnknown_Release(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppv = object;
|
||||
}
|
||||
}
|
||||
|
||||
IMarshal_Release(pMarshal);
|
||||
|
|
|
@ -1036,7 +1036,7 @@ static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *
|
|||
* All menu messages from these groups should be routed to the server.
|
||||
*
|
||||
* RETURNS: TRUE if the popup menu is part of a server owned group
|
||||
* FASE if the popup menu is part of a container owned group
|
||||
* FALSE if the popup menu is part of a container owned group
|
||||
*/
|
||||
BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
|
||||
{
|
||||
|
|
|
@ -233,6 +233,7 @@
|
|||
@ stub SNB_UserUnmarshal
|
||||
@ stdcall StgCreateDocfile(wstr long long ptr)
|
||||
@ stdcall StgCreateDocfileOnILockBytes(ptr long long ptr)
|
||||
@ stdcall StgCreatePropSetStg(ptr long ptr)
|
||||
@ stdcall StgCreateStorageEx(wstr long long long ptr ptr ptr ptr)
|
||||
@ stub StgGetIFillLockBytesOnFile
|
||||
@ stub StgGetIFillLockBytesOnILockBytes
|
||||
|
|
|
@ -191,10 +191,8 @@ CFStub_Invoke(
|
|||
|
||||
msg->cbBuffer = ststg.cbSize.u.LowPart;
|
||||
|
||||
if (msg->Buffer)
|
||||
msg->Buffer = HeapReAlloc(GetProcessHeap(),0,msg->Buffer,ststg.cbSize.u.LowPart);
|
||||
else
|
||||
msg->Buffer = HeapAlloc(GetProcessHeap(),0,ststg.cbSize.u.LowPart);
|
||||
I_RpcGetBuffer((RPC_MESSAGE *)msg);
|
||||
if (hres) return hres;
|
||||
|
||||
seekto.u.LowPart = 0;seekto.u.HighPart = 0;
|
||||
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
|
||||
|
@ -547,10 +545,10 @@ static HRESULT WINAPI RemUnkStub_Invoke(LPRPCSTUBBUFFER iface,
|
|||
|
||||
/* out */
|
||||
pMsg->cbBuffer = cIids * sizeof(REMQIRESULT);
|
||||
if (pMsg->Buffer)
|
||||
pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer);
|
||||
else
|
||||
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer);
|
||||
|
||||
I_RpcGetBuffer((RPC_MESSAGE *)pMsg);
|
||||
if (hr) return hr;
|
||||
|
||||
buf = pMsg->Buffer;
|
||||
/* FIXME: pQIResults is a unique pointer so pQIResults can be NULL! */
|
||||
memcpy(buf, pQIResults, cIids * sizeof(REMQIRESULT));
|
||||
|
@ -574,12 +572,13 @@ static HRESULT WINAPI RemUnkStub_Invoke(LPRPCSTUBBUFFER iface,
|
|||
|
||||
/* out */
|
||||
pMsg->cbBuffer = cIids * sizeof(HRESULT);
|
||||
if (pMsg->Buffer)
|
||||
pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer);
|
||||
else
|
||||
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer);
|
||||
buf = pMsg->Buffer;
|
||||
memcpy(buf, pResults, cIids * sizeof(HRESULT));
|
||||
|
||||
I_RpcGetBuffer((RPC_MESSAGE *)pMsg);
|
||||
if (!hr)
|
||||
{
|
||||
buf = pMsg->Buffer;
|
||||
memcpy(buf, pResults, cIids * sizeof(HRESULT));
|
||||
}
|
||||
|
||||
CoTaskMemFree(pResults);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -866,8 +866,11 @@ static void BIGBLOCKFILE_RemapAllMappedPages(LPBIGBLOCKFILE This)
|
|||
*/
|
||||
static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags)
|
||||
{
|
||||
if (openFlags & (STGM_WRITE | STGM_READWRITE))
|
||||
return PAGE_READWRITE;
|
||||
else
|
||||
return PAGE_READONLY;
|
||||
switch(STGM_ACCESS_MODE(openFlags))
|
||||
{
|
||||
case STGM_WRITE:
|
||||
case STGM_READWRITE:
|
||||
return PAGE_READWRITE;
|
||||
}
|
||||
return PAGE_READONLY;
|
||||
}
|
||||
|
|
479
reactos/lib/ole32/stg_prop.c
Normal file
479
reactos/lib/ole32/stg_prop.c
Normal file
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* Compound Storage (32 bit version)
|
||||
* Storage implementation
|
||||
*
|
||||
* This file contains the compound file implementation
|
||||
* of the storage interface.
|
||||
*
|
||||
* Copyright 1999 Francis Beaudet
|
||||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 1999 Thuy Nguyen
|
||||
* Copyright 2005 Mike McCormack
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
#include "winuser.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "storage32.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(storage);
|
||||
|
||||
#define _IPropertySetStorage_Offset ((int)(&(((StorageImpl*)0)->base.pssVtbl)))
|
||||
#define _ICOM_THIS_From_IPropertySetStorage(class, name) \
|
||||
class* This = (class*)(((char*)name)-_IPropertySetStorage_Offset)
|
||||
|
||||
static IPropertyStorageVtbl IPropertyStorage_Vtbl;
|
||||
|
||||
/***********************************************************************
|
||||
* Implementation of IPropertyStorage
|
||||
*/
|
||||
typedef struct tagPropertyStorage_impl
|
||||
{
|
||||
IPropertyStorageVtbl *vtbl;
|
||||
DWORD ref;
|
||||
IStream *stm;
|
||||
} PropertyStorage_impl;
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnQueryInterface (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnQueryInterface(
|
||||
IPropertyStorage *iface,
|
||||
REFIID riid,
|
||||
void** ppvObject)
|
||||
{
|
||||
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
|
||||
|
||||
if ( (This==0) || (ppvObject==0) )
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObject = 0;
|
||||
|
||||
if (IsEqualGUID(&IID_IUnknown, riid) ||
|
||||
IsEqualGUID(&IID_IPropertyStorage, riid))
|
||||
{
|
||||
IPropertyStorage_AddRef(iface);
|
||||
*ppvObject = (IPropertyStorage*)iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnAddRef (IPropertyStorage)
|
||||
*/
|
||||
static ULONG WINAPI IPropertyStorage_fnAddRef(
|
||||
IPropertyStorage *iface)
|
||||
{
|
||||
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnRelease (IPropertyStorage)
|
||||
*/
|
||||
static ULONG WINAPI IPropertyStorage_fnRelease(
|
||||
IPropertyStorage *iface)
|
||||
{
|
||||
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
|
||||
ULONG ref;
|
||||
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
if (ref == 0)
|
||||
{
|
||||
TRACE("Destroying %p\n", This);
|
||||
IStream_Release(This->stm);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnReadMultiple (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnReadMultiple(
|
||||
IPropertyStorage* iface,
|
||||
ULONG cpspec,
|
||||
const PROPSPEC rgpspec[],
|
||||
PROPVARIANT rgpropvar[])
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnWriteMultiple (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
|
||||
IPropertyStorage* iface,
|
||||
ULONG cpspec,
|
||||
const PROPSPEC rgpspec[],
|
||||
const PROPVARIANT rgpropvar[],
|
||||
PROPID propidNameFirst)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnDeleteMultiple (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnDeleteMultiple(
|
||||
IPropertyStorage* iface,
|
||||
ULONG cpspec,
|
||||
const PROPSPEC rgpspec[])
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnReadPropertyNames (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnReadPropertyNames(
|
||||
IPropertyStorage* iface,
|
||||
ULONG cpropid,
|
||||
const PROPID rgpropid[],
|
||||
LPOLESTR rglpwstrName[])
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnWritePropertyNames (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames(
|
||||
IPropertyStorage* iface,
|
||||
ULONG cpropid,
|
||||
const PROPID rgpropid[],
|
||||
const LPOLESTR rglpwstrName[])
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnDeletePropertyNames (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnDeletePropertyNames(
|
||||
IPropertyStorage* iface,
|
||||
ULONG cpropid,
|
||||
const PROPID rgpropid[])
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnCommit (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnCommit(
|
||||
IPropertyStorage* iface,
|
||||
DWORD grfCommitFlags)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnRevert (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnRevert(
|
||||
IPropertyStorage* iface)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnEnum (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnEnum(
|
||||
IPropertyStorage* iface,
|
||||
IEnumSTATPROPSTG** ppenum)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnSetTimes (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnSetTimes(
|
||||
IPropertyStorage* iface,
|
||||
const FILETIME* pctime,
|
||||
const FILETIME* patime,
|
||||
const FILETIME* pmtime)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnSetClass (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnSetClass(
|
||||
IPropertyStorage* iface,
|
||||
REFCLSID clsid)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertyStorage_fnStat (IPropertyStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertyStorage_fnStat(
|
||||
IPropertyStorage* iface,
|
||||
STATPROPSETSTG* statpsstg)
|
||||
{
|
||||
FIXME("\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PropertyStorage_Contruct
|
||||
*/
|
||||
static HRESULT PropertyStorage_Contruct(IStream *stm, IPropertyStorage** pps)
|
||||
{
|
||||
PropertyStorage_impl *ps;
|
||||
|
||||
ps = HeapAlloc(GetProcessHeap(), 0, sizeof *ps);
|
||||
if (!ps)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
ps->vtbl = &IPropertyStorage_Vtbl;
|
||||
ps->ref = 1;
|
||||
ps->stm = stm;
|
||||
|
||||
*pps = (IPropertyStorage*)ps;
|
||||
|
||||
TRACE("PropertyStorage %p constructed\n", ps);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Implementation of IPropertySetStorage
|
||||
*/
|
||||
|
||||
static LPCWSTR format_id_to_name(REFFMTID rfmtid)
|
||||
{
|
||||
static const WCHAR szSummaryInfo[] = { 5,'S','u','m','m','a','r','y',
|
||||
'I','n','f','o','r','m','a','t','i','o','n',0 };
|
||||
|
||||
if (IsEqualGUID(&FMTID_SummaryInformation, rfmtid))
|
||||
return szSummaryInfo;
|
||||
ERR("Unknown format id %s\n", debugstr_guid(rfmtid));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnQueryInterface (IUnknown)
|
||||
*
|
||||
* This method forwards to the common QueryInterface implementation
|
||||
*/
|
||||
static HRESULT WINAPI IPropertySetStorage_fnQueryInterface(
|
||||
IPropertySetStorage *ppstg,
|
||||
REFIID riid,
|
||||
void** ppvObject)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
return StorageBaseImpl_QueryInterface( (IStorage*)This, riid, ppvObject );
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnAddRef (IUnknown)
|
||||
*
|
||||
* This method forwards to the common AddRef implementation
|
||||
*/
|
||||
static ULONG WINAPI IPropertySetStorage_fnAddRef(
|
||||
IPropertySetStorage *ppstg)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
return StorageBaseImpl_AddRef( (IStorage*)This );
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnRelease (IUnknown)
|
||||
*
|
||||
* This method forwards to the common Release implementation
|
||||
*/
|
||||
static ULONG WINAPI IPropertySetStorage_fnRelease(
|
||||
IPropertySetStorage *ppstg)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
return StorageBaseImpl_Release( (IStorage*)This );
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnCreate (IPropertySetStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertySetStorage_fnCreate(
|
||||
IPropertySetStorage *ppstg,
|
||||
REFFMTID rfmtid,
|
||||
const CLSID* pclsid,
|
||||
DWORD grfFlags,
|
||||
DWORD grfMode,
|
||||
IPropertyStorage** ppprstg)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
LPCWSTR name = NULL;
|
||||
IStream *stm = NULL;
|
||||
HRESULT r;
|
||||
|
||||
TRACE("%p %s %08lx %p\n", This, debugstr_guid(rfmtid), grfMode, ppprstg);
|
||||
|
||||
/* be picky */
|
||||
if (grfMode != (STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
if (!rfmtid)
|
||||
return E_INVALIDARG;
|
||||
|
||||
name = format_id_to_name(rfmtid);
|
||||
if (!name)
|
||||
return STG_E_FILENOTFOUND;
|
||||
|
||||
r = IStorage_CreateStream( (IStorage*)This, name, grfMode, 0, 0, &stm );
|
||||
if (FAILED(r))
|
||||
return r;
|
||||
|
||||
return PropertyStorage_Contruct(stm, ppprstg);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnOpen (IPropertySetStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertySetStorage_fnOpen(
|
||||
IPropertySetStorage *ppstg,
|
||||
REFFMTID rfmtid,
|
||||
DWORD grfMode,
|
||||
IPropertyStorage** ppprstg)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
IStream *stm = NULL;
|
||||
LPCWSTR name = NULL;
|
||||
HRESULT r;
|
||||
|
||||
TRACE("%p %s %08lx %p\n", This, debugstr_guid(rfmtid), grfMode, ppprstg);
|
||||
|
||||
/* be picky */
|
||||
if (grfMode != (STGM_READWRITE|STGM_SHARE_EXCLUSIVE) &&
|
||||
grfMode != (STGM_READ|STGM_SHARE_EXCLUSIVE))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
if (!rfmtid)
|
||||
return E_INVALIDARG;
|
||||
|
||||
name = format_id_to_name(rfmtid);
|
||||
if (!name)
|
||||
return STG_E_FILENOTFOUND;
|
||||
|
||||
r = IStorage_OpenStream((IStorage*) This, name, 0, grfMode, 0, &stm );
|
||||
if (FAILED(r))
|
||||
return r;
|
||||
|
||||
return PropertyStorage_Contruct(stm, ppprstg);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnDelete (IPropertySetStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertySetStorage_fnDelete(
|
||||
IPropertySetStorage *ppstg,
|
||||
REFFMTID rfmtid)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
IStorage *stg = NULL;
|
||||
LPCWSTR name = NULL;
|
||||
|
||||
TRACE("%p %s\n", This, debugstr_guid(rfmtid));
|
||||
|
||||
if (!rfmtid)
|
||||
return E_INVALIDARG;
|
||||
|
||||
name = format_id_to_name(rfmtid);
|
||||
if (!name)
|
||||
return STG_E_FILENOTFOUND;
|
||||
|
||||
stg = (IStorage*) This;
|
||||
return IStorage_DestroyElement(stg, name);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* IPropertySetStorage_fnEnum (IPropertySetStorage)
|
||||
*/
|
||||
static HRESULT WINAPI IPropertySetStorage_fnEnum(
|
||||
IPropertySetStorage *ppstg,
|
||||
IEnumSTATPROPSETSTG** ppenum)
|
||||
{
|
||||
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
|
||||
FIXME("%p\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* vtables
|
||||
*/
|
||||
IPropertySetStorageVtbl IPropertySetStorage_Vtbl =
|
||||
{
|
||||
IPropertySetStorage_fnQueryInterface,
|
||||
IPropertySetStorage_fnAddRef,
|
||||
IPropertySetStorage_fnRelease,
|
||||
IPropertySetStorage_fnCreate,
|
||||
IPropertySetStorage_fnOpen,
|
||||
IPropertySetStorage_fnDelete,
|
||||
IPropertySetStorage_fnEnum
|
||||
};
|
||||
|
||||
static IPropertyStorageVtbl IPropertyStorage_Vtbl =
|
||||
{
|
||||
IPropertyStorage_fnQueryInterface,
|
||||
IPropertyStorage_fnAddRef,
|
||||
IPropertyStorage_fnRelease,
|
||||
IPropertyStorage_fnReadMultiple,
|
||||
IPropertyStorage_fnWriteMultiple,
|
||||
IPropertyStorage_fnDeleteMultiple,
|
||||
IPropertyStorage_fnReadPropertyNames,
|
||||
IPropertyStorage_fnWritePropertyNames,
|
||||
IPropertyStorage_fnDeletePropertyNames,
|
||||
IPropertyStorage_fnCommit,
|
||||
IPropertyStorage_fnRevert,
|
||||
IPropertyStorage_fnEnum,
|
||||
IPropertyStorage_fnSetTimes,
|
||||
IPropertyStorage_fnSetClass,
|
||||
IPropertyStorage_fnStat,
|
||||
};
|
|
@ -443,7 +443,12 @@ HRESULT WINAPI StgStreamImpl_Write(
|
|||
/*
|
||||
* Do we have permission to write to this stream?
|
||||
*/
|
||||
if (!(This->grfMode & (STGM_WRITE | STGM_READWRITE))) {
|
||||
switch(STGM_ACCESS_MODE(This->grfMode))
|
||||
{
|
||||
case STGM_WRITE:
|
||||
case STGM_READWRITE:
|
||||
break;
|
||||
default:
|
||||
return STG_E_ACCESSDENIED;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright 1999 Francis Beaudet
|
||||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 1999 Thuy Nguyen
|
||||
* Copyright 2005 Mike McCormack
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -51,8 +52,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(storage);
|
|||
|
||||
#define FILE_BEGIN 0
|
||||
|
||||
#define STGM_SHARE_MODE(stgm) ((stgm)&0xf0)
|
||||
|
||||
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
|
||||
#define OLESTREAM_ID 0x501
|
||||
#define OLESTREAM_MAX_STR_LEN 255
|
||||
|
@ -222,7 +221,7 @@ static IEnumSTATSTGVtbl IEnumSTATSTGImpl_Vtbl =
|
|||
IEnumSTATSTGImpl_Clone
|
||||
};
|
||||
|
||||
|
||||
extern IPropertySetStorageVtbl IPropertySetStorage_Vtbl;
|
||||
|
||||
|
||||
|
||||
|
@ -266,6 +265,10 @@ HRESULT WINAPI StorageBaseImpl_QueryInterface(
|
|||
{
|
||||
*ppvObject = (IStorage*)This;
|
||||
}
|
||||
else if (memcmp(&IID_IPropertySetStorage, riid, sizeof(IID_IPropertySetStorage)) == 0)
|
||||
{
|
||||
*ppvObject = (IStorage*)&This->pssVtbl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that we obtained an interface.
|
||||
|
@ -294,7 +297,11 @@ ULONG WINAPI StorageBaseImpl_AddRef(
|
|||
IStorage* iface)
|
||||
{
|
||||
StorageBaseImpl *This = (StorageBaseImpl *)iface;
|
||||
return InterlockedIncrement(&This->ref);
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE("(%p) AddRef to %ld\n", This, ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -314,6 +321,8 @@ ULONG WINAPI StorageBaseImpl_Release(
|
|||
*/
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE("(%p) ReleaseRef to %ld\n", This, ref);
|
||||
|
||||
/*
|
||||
* If the reference count goes down to 0, perform suicide.
|
||||
*/
|
||||
|
@ -381,7 +390,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
|
|||
/*
|
||||
* As documented.
|
||||
*/
|
||||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
|
||||
if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE ||
|
||||
(grfMode & STGM_DELETEONRELEASE) ||
|
||||
(grfMode & STGM_TRANSACTED) )
|
||||
{
|
||||
|
@ -500,7 +509,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
|
|||
/*
|
||||
* As documented.
|
||||
*/
|
||||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
|
||||
if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE ||
|
||||
(grfMode & STGM_DELETEONRELEASE) ||
|
||||
(grfMode & STGM_PRIORITY) )
|
||||
{
|
||||
|
@ -882,7 +891,7 @@ HRESULT WINAPI StorageBaseImpl_CreateStream(
|
|||
if ( FAILED( validateSTGM(grfMode) ))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) )
|
||||
if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE)
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
/*
|
||||
|
@ -914,7 +923,7 @@ HRESULT WINAPI StorageBaseImpl_CreateStream(
|
|||
/*
|
||||
* An element with this name already exists
|
||||
*/
|
||||
if (grfMode & STGM_CREATE)
|
||||
if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
|
||||
{
|
||||
IStorage_DestroyElement(iface, pwcsName);
|
||||
}
|
||||
|
@ -1089,8 +1098,8 @@ HRESULT WINAPI StorageImpl_CreateStorage(
|
|||
/*
|
||||
* Create a property enumeration and search the properties
|
||||
*/
|
||||
propertyEnumeration = IEnumSTATSTGImpl_Construct( This->ancestorStorage,
|
||||
This->rootPropertySetIndex);
|
||||
propertyEnumeration = IEnumSTATSTGImpl_Construct( This->base.ancestorStorage,
|
||||
This->base.rootPropertySetIndex);
|
||||
|
||||
foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
|
||||
pwcsName,
|
||||
|
@ -1102,7 +1111,7 @@ HRESULT WINAPI StorageImpl_CreateStorage(
|
|||
/*
|
||||
* An element with this name already exists
|
||||
*/
|
||||
if (grfMode & STGM_CREATE)
|
||||
if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
|
||||
IStorage_DestroyElement(iface, pwcsName);
|
||||
else
|
||||
return STG_E_FILEALREADYEXISTS;
|
||||
|
@ -1141,13 +1150,13 @@ HRESULT WINAPI StorageImpl_CreateStorage(
|
|||
/*
|
||||
* Obtain a free property in the property chain
|
||||
*/
|
||||
newPropertyIndex = getFreeProperty(This->ancestorStorage);
|
||||
newPropertyIndex = getFreeProperty(This->base.ancestorStorage);
|
||||
|
||||
/*
|
||||
* Save the new property into the new property spot
|
||||
*/
|
||||
StorageImpl_WriteProperty(
|
||||
This->ancestorStorage,
|
||||
This->base.ancestorStorage,
|
||||
newPropertyIndex,
|
||||
&newProperty);
|
||||
|
||||
|
@ -1200,7 +1209,7 @@ static ULONG getFreeProperty(
|
|||
/*
|
||||
* Start by reading the root property
|
||||
*/
|
||||
readSuccessful = StorageImpl_ReadProperty(storage->ancestorStorage,
|
||||
readSuccessful = StorageImpl_ReadProperty(storage->base.ancestorStorage,
|
||||
currentPropertyIndex,
|
||||
¤tProperty);
|
||||
if (readSuccessful)
|
||||
|
@ -1239,7 +1248,7 @@ static ULONG getFreeProperty(
|
|||
* obtain the new count of property blocks
|
||||
*/
|
||||
blockCount = BlockChainStream_GetCount(
|
||||
storage->ancestorStorage->rootBlockChain)+1;
|
||||
storage->base.ancestorStorage->rootBlockChain)+1;
|
||||
|
||||
/*
|
||||
* initialize the size used by the property stream
|
||||
|
@ -1250,7 +1259,7 @@ static ULONG getFreeProperty(
|
|||
/*
|
||||
* add a property block to the property chain
|
||||
*/
|
||||
BlockChainStream_SetSize(storage->ancestorStorage->rootBlockChain, newSize);
|
||||
BlockChainStream_SetSize(storage->base.ancestorStorage->rootBlockChain, newSize);
|
||||
|
||||
/*
|
||||
* memset the empty property in order to initialize the unused newly
|
||||
|
@ -1269,7 +1278,7 @@ static ULONG getFreeProperty(
|
|||
propertyIndex++)
|
||||
{
|
||||
StorageImpl_WriteProperty(
|
||||
storage->ancestorStorage,
|
||||
storage->base.ancestorStorage,
|
||||
propertyIndex,
|
||||
&emptyProperty);
|
||||
}
|
||||
|
@ -1322,8 +1331,8 @@ static void updatePropertyChain(
|
|||
/*
|
||||
* Read the root property
|
||||
*/
|
||||
StorageImpl_ReadProperty(storage->ancestorStorage,
|
||||
storage->rootPropertySetIndex,
|
||||
StorageImpl_ReadProperty(storage->base.ancestorStorage,
|
||||
storage->base.rootPropertySetIndex,
|
||||
¤tProperty);
|
||||
|
||||
if (currentProperty.dirProperty != PROPERTY_NULL)
|
||||
|
@ -1343,7 +1352,7 @@ static void updatePropertyChain(
|
|||
/*
|
||||
* Read
|
||||
*/
|
||||
StorageImpl_ReadProperty(storage->ancestorStorage,
|
||||
StorageImpl_ReadProperty(storage->base.ancestorStorage,
|
||||
currentProperty.dirProperty,
|
||||
¤tProperty);
|
||||
|
||||
|
@ -1359,7 +1368,7 @@ static void updatePropertyChain(
|
|||
{
|
||||
if (previous != PROPERTY_NULL)
|
||||
{
|
||||
StorageImpl_ReadProperty(storage->ancestorStorage,
|
||||
StorageImpl_ReadProperty(storage->base.ancestorStorage,
|
||||
previous,
|
||||
¤tProperty);
|
||||
current = previous;
|
||||
|
@ -1367,7 +1376,7 @@ static void updatePropertyChain(
|
|||
else
|
||||
{
|
||||
currentProperty.previousProperty = newPropertyIndex;
|
||||
StorageImpl_WriteProperty(storage->ancestorStorage,
|
||||
StorageImpl_WriteProperty(storage->base.ancestorStorage,
|
||||
current,
|
||||
¤tProperty);
|
||||
found = 1;
|
||||
|
@ -1377,7 +1386,7 @@ static void updatePropertyChain(
|
|||
{
|
||||
if (next != PROPERTY_NULL)
|
||||
{
|
||||
StorageImpl_ReadProperty(storage->ancestorStorage,
|
||||
StorageImpl_ReadProperty(storage->base.ancestorStorage,
|
||||
next,
|
||||
¤tProperty);
|
||||
current = next;
|
||||
|
@ -1385,7 +1394,7 @@ static void updatePropertyChain(
|
|||
else
|
||||
{
|
||||
currentProperty.nextProperty = newPropertyIndex;
|
||||
StorageImpl_WriteProperty(storage->ancestorStorage,
|
||||
StorageImpl_WriteProperty(storage->base.ancestorStorage,
|
||||
current,
|
||||
¤tProperty);
|
||||
found = 1;
|
||||
|
@ -1410,8 +1419,8 @@ static void updatePropertyChain(
|
|||
* The root storage is empty, link the new property to it's dir property
|
||||
*/
|
||||
currentProperty.dirProperty = newPropertyIndex;
|
||||
StorageImpl_WriteProperty(storage->ancestorStorage,
|
||||
storage->rootPropertySetIndex,
|
||||
StorageImpl_WriteProperty(storage->base.ancestorStorage,
|
||||
storage->base.rootPropertySetIndex,
|
||||
¤tProperty);
|
||||
}
|
||||
}
|
||||
|
@ -1657,8 +1666,8 @@ HRESULT WINAPI StorageImpl_DestroyElement(
|
|||
* Create a property enumeration to search the property with the given name
|
||||
*/
|
||||
propertyEnumeration = IEnumSTATSTGImpl_Construct(
|
||||
This->ancestorStorage,
|
||||
This->rootPropertySetIndex);
|
||||
This->base.ancestorStorage,
|
||||
This->base.rootPropertySetIndex);
|
||||
|
||||
foundPropertyIndexToDelete = IEnumSTATSTGImpl_FindProperty(
|
||||
propertyEnumeration,
|
||||
|
@ -1682,8 +1691,8 @@ HRESULT WINAPI StorageImpl_DestroyElement(
|
|||
* First, read This's StgProperty..
|
||||
*/
|
||||
res = StorageImpl_ReadProperty(
|
||||
This->ancestorStorage,
|
||||
This->rootPropertySetIndex,
|
||||
This->base.ancestorStorage,
|
||||
This->base.rootPropertySetIndex,
|
||||
&parentProperty);
|
||||
|
||||
assert(res);
|
||||
|
@ -1698,7 +1707,7 @@ HRESULT WINAPI StorageImpl_DestroyElement(
|
|||
* Set data as it would have been done in the else part...
|
||||
*/
|
||||
typeOfRelation = PROPERTY_RELATION_DIR;
|
||||
parentPropertyId = This->rootPropertySetIndex;
|
||||
parentPropertyId = This->base.rootPropertySetIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1709,8 +1718,8 @@ HRESULT WINAPI StorageImpl_DestroyElement(
|
|||
IEnumSTATSTGImpl* propertyEnumeration2;
|
||||
|
||||
propertyEnumeration2 = IEnumSTATSTGImpl_Construct(
|
||||
This->ancestorStorage,
|
||||
This->rootPropertySetIndex);
|
||||
This->base.ancestorStorage,
|
||||
This->base.rootPropertySetIndex);
|
||||
|
||||
typeOfRelation = IEnumSTATSTGImpl_FindParentProperty(
|
||||
propertyEnumeration2,
|
||||
|
@ -1847,7 +1856,7 @@ static HRESULT deleteStorageProperty(
|
|||
*/
|
||||
propertyToDelete.sizeOfNameString = 0;
|
||||
|
||||
StorageImpl_WriteProperty(parentStorage->ancestorStorage,
|
||||
StorageImpl_WriteProperty(parentStorage->base.ancestorStorage,
|
||||
indexOfPropertyToDelete,
|
||||
&propertyToDelete);
|
||||
|
||||
|
@ -1914,7 +1923,7 @@ static HRESULT deleteStreamProperty(
|
|||
* but since we are here to zap it, I don't do it...
|
||||
*/
|
||||
StorageImpl_WriteProperty(
|
||||
parentStorage->ancestorStorage,
|
||||
parentStorage->base.ancestorStorage,
|
||||
indexOfPropertyToDelete,
|
||||
&propertyToDelete);
|
||||
|
||||
|
@ -1942,7 +1951,7 @@ static HRESULT findPlaceholder(
|
|||
* Read the storage property
|
||||
*/
|
||||
res = StorageImpl_ReadProperty(
|
||||
storage->ancestorStorage,
|
||||
storage->base.ancestorStorage,
|
||||
storePropertyIndex,
|
||||
&storeProperty);
|
||||
|
||||
|
@ -1998,7 +2007,7 @@ static HRESULT findPlaceholder(
|
|||
}
|
||||
|
||||
hr = StorageImpl_WriteProperty(
|
||||
storage->ancestorStorage,
|
||||
storage->base.ancestorStorage,
|
||||
storePropertyIndex,
|
||||
&storeProperty);
|
||||
|
||||
|
@ -2140,7 +2149,7 @@ static HRESULT adjustPropertyChain(
|
|||
* Write back the parent property
|
||||
*/
|
||||
res = StorageImpl_WriteProperty(
|
||||
This->ancestorStorage,
|
||||
This->base.ancestorStorage,
|
||||
parentPropertyId,
|
||||
&parentProperty);
|
||||
if(! res)
|
||||
|
@ -2213,14 +2222,15 @@ HRESULT StorageImpl_Construct(
|
|||
/*
|
||||
* Initialize the virtual function table.
|
||||
*/
|
||||
This->lpVtbl = &Storage32Impl_Vtbl;
|
||||
This->v_destructor = &StorageImpl_Destroy;
|
||||
This->base.lpVtbl = &Storage32Impl_Vtbl;
|
||||
This->base.pssVtbl = &IPropertySetStorage_Vtbl;
|
||||
This->base.v_destructor = &StorageImpl_Destroy;
|
||||
|
||||
/*
|
||||
* This is the top-level storage so initialize the ancestor pointer
|
||||
* to this.
|
||||
*/
|
||||
This->ancestorStorage = This;
|
||||
This->base.ancestorStorage = This;
|
||||
|
||||
/*
|
||||
* Initialize the physical support of the storage.
|
||||
|
@ -2372,13 +2382,13 @@ HRESULT StorageImpl_Construct(
|
|||
if ( (currentProperty.sizeOfNameString != 0 ) &&
|
||||
(currentProperty.propertyType == PROPTYPE_ROOT) )
|
||||
{
|
||||
This->rootPropertySetIndex = currentPropertyIndex;
|
||||
This->base.rootPropertySetIndex = currentPropertyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
currentPropertyIndex++;
|
||||
|
||||
} while (readSuccessful && (This->rootPropertySetIndex == PROPERTY_NULL) );
|
||||
} while (readSuccessful && (This->base.rootPropertySetIndex == PROPERTY_NULL) );
|
||||
|
||||
if (!readSuccessful)
|
||||
{
|
||||
|
@ -2390,15 +2400,15 @@ HRESULT StorageImpl_Construct(
|
|||
* Create the block chain abstraction for the small block root chain.
|
||||
*/
|
||||
if(!(This->smallBlockRootChain =
|
||||
BlockChainStream_Construct(This, NULL, This->rootPropertySetIndex)))
|
||||
BlockChainStream_Construct(This, NULL, This->base.rootPropertySetIndex)))
|
||||
return STG_E_READFAULT;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void StorageImpl_Destroy(
|
||||
StorageImpl* This)
|
||||
void StorageImpl_Destroy(StorageBaseImpl* iface)
|
||||
{
|
||||
StorageImpl *This = (StorageImpl*) iface;
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->pwcsName);
|
||||
|
@ -3138,7 +3148,7 @@ BOOL StorageImpl_ReadProperty(
|
|||
if (readSuccessful)
|
||||
{
|
||||
/* replace the name of root entry (often "Root Entry") by the file name */
|
||||
WCHAR *propName = (index == This->rootPropertySetIndex) ?
|
||||
WCHAR *propName = (index == This->base.rootPropertySetIndex) ?
|
||||
This->filename : (WCHAR *)currentProperty+OFFSET_PS_NAME;
|
||||
|
||||
memset(buffer->name, 0, sizeof(buffer->name));
|
||||
|
@ -3484,19 +3494,19 @@ StorageInternalImpl* StorageInternalImpl_Construct(
|
|||
/*
|
||||
* Initialize the virtual function table.
|
||||
*/
|
||||
newStorage->lpVtbl = &Storage32InternalImpl_Vtbl;
|
||||
newStorage->v_destructor = &StorageInternalImpl_Destroy;
|
||||
newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;
|
||||
newStorage->base.v_destructor = &StorageInternalImpl_Destroy;
|
||||
|
||||
/*
|
||||
* Keep the ancestor storage pointer and nail a reference to it.
|
||||
*/
|
||||
newStorage->ancestorStorage = ancestorStorage;
|
||||
StorageBaseImpl_AddRef((IStorage*)(newStorage->ancestorStorage));
|
||||
newStorage->base.ancestorStorage = ancestorStorage;
|
||||
StorageBaseImpl_AddRef((IStorage*)(newStorage->base.ancestorStorage));
|
||||
|
||||
/*
|
||||
* Keep the index of the root property set for this storage,
|
||||
*/
|
||||
newStorage->rootPropertySetIndex = rootPropertyIndex;
|
||||
newStorage->base.rootPropertySetIndex = rootPropertyIndex;
|
||||
|
||||
return newStorage;
|
||||
}
|
||||
|
@ -3504,10 +3514,11 @@ StorageInternalImpl* StorageInternalImpl_Construct(
|
|||
return 0;
|
||||
}
|
||||
|
||||
void StorageInternalImpl_Destroy(
|
||||
StorageInternalImpl* This)
|
||||
void StorageInternalImpl_Destroy( StorageBaseImpl *iface)
|
||||
{
|
||||
StorageBaseImpl_Release((IStorage*)This->ancestorStorage);
|
||||
StorageInternalImpl* This = (StorageInternalImpl*) iface;
|
||||
|
||||
StorageBaseImpl_Release((IStorage*)This->base.ancestorStorage);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
|
@ -4938,7 +4949,7 @@ ULONG SmallBlockChainStream_GetNextFreeBlock(
|
|||
|
||||
StorageImpl_ReadProperty(
|
||||
This->parentStorage,
|
||||
This->parentStorage->rootPropertySetIndex,
|
||||
This->parentStorage->base.rootPropertySetIndex,
|
||||
&rootProp);
|
||||
|
||||
rootProp.startingBlock = sbStartIndex;
|
||||
|
@ -4947,7 +4958,7 @@ ULONG SmallBlockChainStream_GetNextFreeBlock(
|
|||
|
||||
StorageImpl_WriteProperty(
|
||||
This->parentStorage,
|
||||
This->parentStorage->rootPropertySetIndex,
|
||||
This->parentStorage->base.rootPropertySetIndex,
|
||||
&rootProp);
|
||||
}
|
||||
}
|
||||
|
@ -4966,7 +4977,7 @@ ULONG SmallBlockChainStream_GetNextFreeBlock(
|
|||
|
||||
StorageImpl_ReadProperty(
|
||||
This->parentStorage,
|
||||
This->parentStorage->rootPropertySetIndex,
|
||||
This->parentStorage->base.rootPropertySetIndex,
|
||||
&rootProp);
|
||||
|
||||
if (rootProp.size.u.LowPart <
|
||||
|
@ -4980,7 +4991,7 @@ ULONG SmallBlockChainStream_GetNextFreeBlock(
|
|||
|
||||
StorageImpl_WriteProperty(
|
||||
This->parentStorage,
|
||||
This->parentStorage->rootPropertySetIndex,
|
||||
This->parentStorage->base.rootPropertySetIndex,
|
||||
&rootProp);
|
||||
}
|
||||
}
|
||||
|
@ -5415,7 +5426,7 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
{
|
||||
StorageImpl* newStorage = 0;
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT hr = STG_E_INVALIDFLAG;
|
||||
DWORD shareMode;
|
||||
DWORD accessMode;
|
||||
DWORD creationMode;
|
||||
|
@ -5438,16 +5449,33 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
* Validate the STGM flags
|
||||
*/
|
||||
if ( FAILED( validateSTGM(grfMode) ))
|
||||
return STG_E_INVALIDFLAG;
|
||||
goto end;
|
||||
|
||||
/* StgCreateDocFile always opens for write */
|
||||
if (!(grfMode & (STGM_WRITE|STGM_READWRITE)))
|
||||
return STG_E_INVALIDFLAG;
|
||||
switch(STGM_ACCESS_MODE(grfMode))
|
||||
{
|
||||
case STGM_WRITE:
|
||||
case STGM_READWRITE:
|
||||
break;
|
||||
default:
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* can't share write */
|
||||
switch(STGM_SHARE_MODE(grfMode))
|
||||
{
|
||||
case STGM_SHARE_EXCLUSIVE:
|
||||
case STGM_SHARE_DENY_WRITE:
|
||||
break;
|
||||
default:
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* shared reading requires transacted mode */
|
||||
if( STGM_SHARE_MODE(grfMode) == STGM_SHARE_DENY_WRITE &&
|
||||
!(grfMode&STGM_TRANSACTED) )
|
||||
goto end;
|
||||
|
||||
/* always opens non-shared */
|
||||
if (!(grfMode & STGM_SHARE_EXCLUSIVE))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
/*
|
||||
* Generate a unique name.
|
||||
*/
|
||||
|
@ -5456,10 +5484,8 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
WCHAR tempPath[MAX_PATH];
|
||||
static const WCHAR prefix[] = { 'S', 'T', 'O', 0 };
|
||||
|
||||
if (!(grfMode & STGM_SHARE_EXCLUSIVE))
|
||||
return STG_E_INVALIDFLAG;
|
||||
if (!(grfMode & (STGM_WRITE|STGM_READWRITE)))
|
||||
return STG_E_INVALIDFLAG;
|
||||
if (STGM_SHARE_MODE(grfMode) == STGM_SHARE_EXCLUSIVE)
|
||||
goto end;
|
||||
|
||||
memset(tempPath, 0, sizeof(tempPath));
|
||||
memset(tempFileName, 0, sizeof(tempFileName));
|
||||
|
@ -5470,7 +5496,10 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
if (GetTempFileNameW(tempPath, prefix, 0, tempFileName) != 0)
|
||||
pwcsName = tempFileName;
|
||||
else
|
||||
return STG_E_INSUFFICIENTMEMORY;
|
||||
{
|
||||
hr = STG_E_INSUFFICIENTMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
creationMode = TRUNCATE_EXISTING;
|
||||
}
|
||||
|
@ -5501,16 +5530,18 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
hFile = CreateFileW(pwcsName,
|
||||
accessMode,
|
||||
shareMode,
|
||||
NULL,
|
||||
NULL,
|
||||
creationMode,
|
||||
fileAttributes,
|
||||
0);
|
||||
0);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if(GetLastError() == ERROR_FILE_EXISTS)
|
||||
return STG_E_FILEALREADYEXISTS;
|
||||
return E_FAIL;
|
||||
hr = STG_E_FILEALREADYEXISTS;
|
||||
else
|
||||
hr = E_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5519,7 +5550,10 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl));
|
||||
|
||||
if (newStorage == 0)
|
||||
return STG_E_INSUFFICIENTMEMORY;
|
||||
{
|
||||
hr = STG_E_INSUFFICIENTMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
hr = StorageImpl_Construct(
|
||||
newStorage,
|
||||
|
@ -5533,7 +5567,7 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
if (FAILED(hr))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, newStorage);
|
||||
return hr;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5543,6 +5577,8 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
(IStorage*)newStorage,
|
||||
(REFIID)&IID_IStorage,
|
||||
(void**)ppstgOpen);
|
||||
end:
|
||||
TRACE("<-- %p r = %08lx\n", *ppstgOpen, hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -5557,6 +5593,23 @@ HRESULT WINAPI StgCreateStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD st
|
|||
return STG_E_UNIMPLEMENTEDFUNCTION;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* StgCreatePropSetStg [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI StgCreatePropSetStg(IStorage *pstg, DWORD reserved,
|
||||
IPropertySetStorage **ppPropSetStg)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p, 0x%lx, %p): stub\n", pstg, reserved, ppPropSetStg);
|
||||
if (reserved)
|
||||
hr = STG_E_INVALIDPARAMETER;
|
||||
else
|
||||
hr = StorageBaseImpl_QueryInterface(pstg, &IID_IPropertySetStorage,
|
||||
(void**)ppPropSetStg);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* StgOpenStorage [OLE32.@]
|
||||
*/
|
||||
|
@ -5850,11 +5903,23 @@ HRESULT WINAPI StgOpenStorageOnILockBytes(
|
|||
*
|
||||
*
|
||||
*/
|
||||
HRESULT WINAPI StgSetTimes(OLECHAR const *str, FILETIME const *a,
|
||||
FILETIME const *b, FILETIME const *c )
|
||||
HRESULT WINAPI StgSetTimes(OLECHAR const *str, FILETIME const *pctime,
|
||||
FILETIME const *patime, FILETIME const *pmtime)
|
||||
{
|
||||
FIXME("(%s, %p, %p, %p),stub!\n", debugstr_w(str), a, b, c);
|
||||
return S_OK;
|
||||
IStorage *stg = NULL;
|
||||
HRESULT r;
|
||||
|
||||
TRACE("%s %p %p %p\n", debugstr_w(str), pctime, patime, pmtime);
|
||||
|
||||
r = StgOpenStorage(str, NULL, STGM_READWRITE | STGM_SHARE_DENY_WRITE,
|
||||
0, 0, &stg);
|
||||
if( SUCCEEDED(r) )
|
||||
{
|
||||
r = IStorage_SetElementTimes(stg, NULL, pctime, patime, pmtime);
|
||||
IStorage_Release(stg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -5985,6 +6050,9 @@ HRESULT WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm)
|
|||
/****************************************************************************
|
||||
* This method validate a STGM parameter that can contain the values below
|
||||
*
|
||||
* The stgm modes in 0x0000ffff are not bit masks, but distinct 4 bit values.
|
||||
* The stgm values contained in 0xffff0000 are bitmasks.
|
||||
*
|
||||
* STGM_DIRECT 0x00000000
|
||||
* STGM_TRANSACTED 0x00010000
|
||||
* STGM_SIMPLE 0x08000000
|
||||
|
@ -6010,79 +6078,74 @@ HRESULT WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm)
|
|||
*/
|
||||
static HRESULT validateSTGM(DWORD stgm)
|
||||
{
|
||||
BOOL bSTGM_TRANSACTED = ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED);
|
||||
BOOL bSTGM_SIMPLE = ((stgm & STGM_SIMPLE) == STGM_SIMPLE);
|
||||
BOOL bSTGM_DIRECT = ! (bSTGM_TRANSACTED || bSTGM_SIMPLE);
|
||||
DWORD access = STGM_ACCESS_MODE(stgm);
|
||||
DWORD share = STGM_SHARE_MODE(stgm);
|
||||
DWORD create = STGM_CREATE_MODE(stgm);
|
||||
|
||||
BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE);
|
||||
BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE);
|
||||
BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE);
|
||||
if (stgm&~STGM_KNOWN_FLAGS)
|
||||
{
|
||||
ERR("unknown flags %08lx\n", stgm);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BOOL bSTGM_SHARE_DENY_NONE =
|
||||
((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE);
|
||||
switch (access)
|
||||
{
|
||||
case STGM_READ:
|
||||
case STGM_WRITE:
|
||||
case STGM_READWRITE:
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BOOL bSTGM_SHARE_DENY_READ =
|
||||
((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ);
|
||||
switch (share)
|
||||
{
|
||||
case STGM_SHARE_DENY_NONE:
|
||||
case STGM_SHARE_DENY_READ:
|
||||
case STGM_SHARE_DENY_WRITE:
|
||||
case STGM_SHARE_EXCLUSIVE:
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BOOL bSTGM_SHARE_DENY_WRITE =
|
||||
((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE);
|
||||
|
||||
BOOL bSTGM_SHARE_EXCLUSIVE =
|
||||
((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE);
|
||||
|
||||
BOOL bSTGM_CREATE = ((stgm & STGM_CREATE) == STGM_CREATE);
|
||||
BOOL bSTGM_CONVERT = ((stgm & STGM_CONVERT) == STGM_CONVERT);
|
||||
|
||||
BOOL bSTGM_NOSCRATCH = ((stgm & STGM_NOSCRATCH) == STGM_NOSCRATCH);
|
||||
BOOL bSTGM_NOSNAPSHOT = ((stgm & STGM_NOSNAPSHOT) == STGM_NOSNAPSHOT);
|
||||
switch (create)
|
||||
{
|
||||
case STGM_CREATE:
|
||||
case STGM_FAILIFTHERE:
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* STGM_DIRECT | STGM_TRANSACTED | STGM_SIMPLE
|
||||
*/
|
||||
if ( ! bSTGM_DIRECT )
|
||||
if( bSTGM_TRANSACTED && bSTGM_SIMPLE )
|
||||
return E_FAIL;
|
||||
|
||||
/*
|
||||
* STGM_WRITE | STGM_READWRITE | STGM_READ
|
||||
*/
|
||||
if ( ! bSTGM_READ )
|
||||
if( bSTGM_WRITE && bSTGM_READWRITE )
|
||||
return E_FAIL;
|
||||
|
||||
/*
|
||||
* STGM_SHARE_DENY_NONE | others
|
||||
* (I assume here that DENY_READ implies DENY_WRITE)
|
||||
*/
|
||||
if ( bSTGM_SHARE_DENY_NONE )
|
||||
if ( bSTGM_SHARE_DENY_READ ||
|
||||
bSTGM_SHARE_DENY_WRITE ||
|
||||
bSTGM_SHARE_EXCLUSIVE)
|
||||
if ( (stgm & STGM_TRANSACTED) && (stgm & STGM_SIMPLE) )
|
||||
return E_FAIL;
|
||||
|
||||
/*
|
||||
* STGM_CREATE | STGM_CONVERT
|
||||
* if both are false, STGM_FAILIFTHERE is set to TRUE
|
||||
*/
|
||||
if ( bSTGM_CREATE && bSTGM_CONVERT )
|
||||
if ( create == STGM_CREATE && (stgm & STGM_CONVERT) )
|
||||
return E_FAIL;
|
||||
|
||||
/*
|
||||
* STGM_NOSCRATCH requires STGM_TRANSACTED
|
||||
*/
|
||||
if ( bSTGM_NOSCRATCH && ! bSTGM_TRANSACTED )
|
||||
if ( (stgm & STGM_NOSCRATCH) && (stgm & STGM_TRANSACTED) )
|
||||
return E_FAIL;
|
||||
|
||||
/*
|
||||
* STGM_NOSNAPSHOT requires STGM_TRANSACTED and
|
||||
* not STGM_SHARE_EXCLUSIVE or STGM_SHARE_DENY_WRITE`
|
||||
*/
|
||||
if (bSTGM_NOSNAPSHOT)
|
||||
{
|
||||
if ( ! ( bSTGM_TRANSACTED &&
|
||||
!(bSTGM_SHARE_EXCLUSIVE || bSTGM_SHARE_DENY_WRITE)) )
|
||||
if ( (stgm & STGM_NOSNAPSHOT) &&
|
||||
(!(stgm & STGM_TRANSACTED) ||
|
||||
share == STGM_SHARE_EXCLUSIVE ||
|
||||
share == STGM_SHARE_DENY_WRITE) )
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -6095,29 +6158,20 @@ static HRESULT validateSTGM(DWORD stgm)
|
|||
*/
|
||||
static DWORD GetShareModeFromSTGM(DWORD stgm)
|
||||
{
|
||||
DWORD dwShareMode = 0;
|
||||
BOOL bSTGM_SHARE_DENY_NONE =
|
||||
((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE);
|
||||
|
||||
BOOL bSTGM_SHARE_DENY_READ =
|
||||
((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ);
|
||||
|
||||
BOOL bSTGM_SHARE_DENY_WRITE =
|
||||
((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE);
|
||||
|
||||
BOOL bSTGM_SHARE_EXCLUSIVE =
|
||||
((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE);
|
||||
|
||||
if ((bSTGM_SHARE_EXCLUSIVE) || (bSTGM_SHARE_DENY_READ))
|
||||
dwShareMode = 0;
|
||||
|
||||
if (bSTGM_SHARE_DENY_NONE)
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
if (bSTGM_SHARE_DENY_WRITE)
|
||||
dwShareMode = FILE_SHARE_READ;
|
||||
|
||||
return dwShareMode;
|
||||
switch (STGM_SHARE_MODE(stgm))
|
||||
{
|
||||
case STGM_SHARE_DENY_NONE:
|
||||
return FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
case STGM_SHARE_DENY_READ:
|
||||
return FILE_SHARE_WRITE;
|
||||
case STGM_SHARE_DENY_WRITE:
|
||||
return FILE_SHARE_READ;
|
||||
case STGM_SHARE_EXCLUSIVE:
|
||||
return 0;
|
||||
}
|
||||
ERR("Invalid share mode!\n");
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -6128,21 +6182,17 @@ static DWORD GetShareModeFromSTGM(DWORD stgm)
|
|||
*/
|
||||
static DWORD GetAccessModeFromSTGM(DWORD stgm)
|
||||
{
|
||||
DWORD dwDesiredAccess = GENERIC_READ;
|
||||
BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE);
|
||||
BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE);
|
||||
BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE);
|
||||
|
||||
if (bSTGM_READ)
|
||||
dwDesiredAccess = GENERIC_READ;
|
||||
|
||||
if (bSTGM_WRITE)
|
||||
dwDesiredAccess |= GENERIC_WRITE;
|
||||
|
||||
if (bSTGM_READWRITE)
|
||||
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
|
||||
return dwDesiredAccess;
|
||||
switch (STGM_ACCESS_MODE(stgm))
|
||||
{
|
||||
case STGM_READ:
|
||||
return GENERIC_READ;
|
||||
case STGM_WRITE:
|
||||
case STGM_READWRITE:
|
||||
return GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
ERR("Invalid access mode!\n");
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -6153,16 +6203,19 @@ static DWORD GetAccessModeFromSTGM(DWORD stgm)
|
|||
*/
|
||||
static DWORD GetCreationModeFromSTGM(DWORD stgm)
|
||||
{
|
||||
if ( stgm & STGM_CREATE)
|
||||
switch(STGM_CREATE_MODE(stgm))
|
||||
{
|
||||
case STGM_CREATE:
|
||||
return CREATE_ALWAYS;
|
||||
if (stgm & STGM_CONVERT) {
|
||||
case STGM_CONVERT:
|
||||
FIXME("STGM_CONVERT not implemented!\n");
|
||||
return CREATE_NEW;
|
||||
case STGM_FAILIFTHERE:
|
||||
return CREATE_NEW;
|
||||
}
|
||||
/* All other cases */
|
||||
if (stgm & ~ (STGM_CREATE|STGM_CONVERT))
|
||||
FIXME("unhandled storage mode : 0x%08lx\n",stgm & ~ (STGM_CREATE|STGM_CONVERT));
|
||||
return CREATE_NEW;
|
||||
ERR("Invalid create mode!\n");
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6831,7 +6884,7 @@ HRESULT WINAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT* pcf, LPOLESTR* lp
|
|||
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm );
|
||||
if( FAILED ( r ) )
|
||||
{
|
||||
ERR("Failed to open stream\n");
|
||||
WARN("Failed to open stream r = %08lx\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,14 @@ static const ULONG PROPERTY_NULL = 0xFFFFFFFF;
|
|||
#define LIMIT_TO_USE_SMALL_BLOCK 0x1000
|
||||
#define NUM_BLOCKS_PER_DEPOT_BLOCK 128
|
||||
|
||||
#define STGM_ACCESS_MODE(stgm) ((stgm)&0x0000f)
|
||||
#define STGM_SHARE_MODE(stgm) ((stgm)&0x000f0)
|
||||
#define STGM_CREATE_MODE(stgm) ((stgm)&0x0f000)
|
||||
|
||||
#define STGM_KNOWN_FLAGS (0xf0ff | \
|
||||
STGM_TRANSACTED | STGM_CONVERT | STGM_PRIORITY | STGM_NOSCRATCH | \
|
||||
STGM_NOSNAPSHOT | STGM_DIRECT_SWMR | STGM_DELETEONRELEASE | STGM_SIMPLE)
|
||||
|
||||
/*
|
||||
* These are signatures to detect the type of Document file.
|
||||
*/
|
||||
|
@ -207,6 +215,8 @@ struct StorageBaseImpl
|
|||
IStorageVtbl *lpVtbl; /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
|
||||
IPropertySetStorageVtbl *pssVtbl; /* interface for adding a properties stream */
|
||||
|
||||
/*
|
||||
* Reference count of this object
|
||||
*/
|
||||
|
@ -298,17 +308,7 @@ HRESULT WINAPI StorageBaseImpl_SetClass(
|
|||
*/
|
||||
struct StorageImpl
|
||||
{
|
||||
IStorageVtbl *lpVtbl; /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
|
||||
/*
|
||||
* Declare the member of the Storage32BaseImpl class to allow
|
||||
* casting as a Storage32BaseImpl
|
||||
*/
|
||||
ULONG ref;
|
||||
struct StorageImpl* ancestorStorage;
|
||||
ULONG rootPropertySetIndex;
|
||||
void (*v_destructor)(struct StorageImpl*);
|
||||
struct StorageBaseImpl base;
|
||||
|
||||
/*
|
||||
* The following data members are specific to the Storage32Impl
|
||||
|
@ -405,7 +405,7 @@ HRESULT WINAPI StorageImpl_Stat(IStorage* iface,
|
|||
DWORD grfStatFlag); /* [in] */
|
||||
|
||||
void StorageImpl_Destroy(
|
||||
StorageImpl* This);
|
||||
StorageBaseImpl* This);
|
||||
|
||||
HRESULT StorageImpl_Construct(
|
||||
StorageImpl* This,
|
||||
|
@ -498,17 +498,7 @@ void Storage32Impl_SetExtDepotBlock(StorageImpl* This,
|
|||
*/
|
||||
struct StorageInternalImpl
|
||||
{
|
||||
IStorageVtbl *lpVtbl; /* Needs to be the first item in the struct
|
||||
* since we want to cast this in a Storage32 pointer */
|
||||
|
||||
/*
|
||||
* Declare the member of the Storage32BaseImpl class to allow
|
||||
* casting as a Storage32BaseImpl
|
||||
*/
|
||||
ULONG ref;
|
||||
struct StorageImpl* ancestorStorage;
|
||||
ULONG rootPropertySetIndex;
|
||||
void (*v_destructor)(struct StorageInternalImpl*);
|
||||
struct StorageBaseImpl base;
|
||||
|
||||
/*
|
||||
* There is no specific data for this class.
|
||||
|
@ -523,7 +513,7 @@ StorageInternalImpl* StorageInternalImpl_Construct(
|
|||
ULONG rootTropertyIndex);
|
||||
|
||||
void StorageInternalImpl_Destroy(
|
||||
StorageInternalImpl* This);
|
||||
StorageBaseImpl* This);
|
||||
|
||||
HRESULT WINAPI StorageInternalImpl_Commit(
|
||||
IStorage* iface,
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -48,7 +49,7 @@ static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const
|
|||
/* creates a new stub manager and adds it into the apartment. caller must
|
||||
* release stub manager when it is no longer required. the apartment and
|
||||
* external refs together take one implicit ref */
|
||||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
|
||||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object, MSHLFLAGS mshlflags)
|
||||
{
|
||||
struct stub_manager *sm;
|
||||
|
||||
|
@ -74,6 +75,13 @@ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
|
|||
* the marshalled ifptr.
|
||||
*/
|
||||
sm->extrefs = 0;
|
||||
|
||||
if (mshlflags & MSHLFLAGS_TABLESTRONG)
|
||||
sm->state = STUBSTATE_TABLE_STRONG;
|
||||
else if (mshlflags & MSHLFLAGS_TABLEWEAK)
|
||||
sm->state = STUBSTATE_TABLE_WEAK_UNMARSHALED;
|
||||
else
|
||||
sm->state = STUBSTATE_NORMAL_MARSHALED;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
sm->oid = apt->oidc++;
|
||||
|
@ -228,8 +236,16 @@ ULONG stub_manager_int_release(struct stub_manager *This)
|
|||
/* add some external references (ie from a client that unmarshaled an ifptr) */
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs)
|
||||
{
|
||||
ULONG rc = InterlockedExchangeAdd(&m->extrefs, refs) + refs;
|
||||
ULONG rc;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
||||
/* make sure we don't overflow extrefs */
|
||||
refs = min(refs, (ULONG_MAX-1 - m->extrefs));
|
||||
rc = (m->extrefs += refs);
|
||||
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("added %lu refs to %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
|
||||
|
||||
return rc;
|
||||
|
@ -238,7 +254,15 @@ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs)
|
|||
/* remove some external references */
|
||||
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs)
|
||||
{
|
||||
ULONG rc = InterlockedExchangeAdd(&m->extrefs, -refs) - refs;
|
||||
ULONG rc;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
||||
/* make sure we don't underflow extrefs */
|
||||
refs = min(refs, m->extrefs);
|
||||
rc = (m->extrefs -= refs);
|
||||
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("removed %lu refs from %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc);
|
||||
|
||||
|
@ -321,24 +345,27 @@ HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid)
|
||||
/* gets the apartment and IRpcStubBuffer from an object. the caller must
|
||||
* release the references to both objects */
|
||||
IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt)
|
||||
{
|
||||
IRpcStubBuffer *ret = NULL;
|
||||
APARTMENT *apt;
|
||||
struct stub_manager *stubmgr;
|
||||
struct ifstub *ifstub;
|
||||
HRESULT hr;
|
||||
|
||||
hr = ipid_to_stub_manager(ipid, &apt, &stubmgr);
|
||||
*stub_apt = NULL;
|
||||
|
||||
hr = ipid_to_stub_manager(ipid, stub_apt, &stubmgr);
|
||||
if (hr != S_OK) return NULL;
|
||||
|
||||
ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid);
|
||||
if (ifstub)
|
||||
ret = ifstub->stubbuffer;
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
if (ret) IRpcStubBuffer_AddRef(ret);
|
||||
|
||||
COM_ApartmentRelease(apt);
|
||||
stub_manager_int_release(stubmgr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -367,12 +394,12 @@ static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
|
|||
}
|
||||
|
||||
/* registers a new interface stub COM object with the stub manager and returns registration record */
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal)
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid)
|
||||
{
|
||||
struct ifstub *stub;
|
||||
|
||||
TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s, tablemarshal=%s\n",
|
||||
wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid), tablemarshal ? "TRUE" : "FALSE");
|
||||
TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n",
|
||||
wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid));
|
||||
|
||||
stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub));
|
||||
if (!stub) return NULL;
|
||||
|
@ -383,11 +410,6 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
|
|||
/* no need to ref this, same object as sb */
|
||||
stub->iface = iptr;
|
||||
|
||||
if (tablemarshal)
|
||||
stub->state = IFSTUB_STATE_TABLE_MARSHALED;
|
||||
else
|
||||
stub->state = IFSTUB_STATE_NORMAL_MARSHALED;
|
||||
|
||||
stub->iid = *iid;
|
||||
|
||||
/* FIXME: hack for IRemUnknown because we don't notify SCM of our IPID
|
||||
|
@ -415,8 +437,10 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
|
|||
static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub)
|
||||
{
|
||||
TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid));
|
||||
|
||||
|
||||
list_remove(&ifstub->entry);
|
||||
|
||||
RPC_UnregisterInterface(&ifstub->iid);
|
||||
|
||||
IUnknown_Release(ifstub->stubbuffer);
|
||||
IUnknown_Release(ifstub->iface);
|
||||
|
@ -425,33 +449,30 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if
|
|||
}
|
||||
|
||||
/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m)
|
||||
{
|
||||
struct ifstub *ifstub;
|
||||
BOOL ret;
|
||||
|
||||
ifstub = stub_manager_ipid_to_ifstub(m, ipid);
|
||||
if (!ifstub)
|
||||
{
|
||||
WARN("Can't find ifstub for OID %s, IPID %s\n",
|
||||
wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
||||
switch (ifstub->state)
|
||||
switch (m->state)
|
||||
{
|
||||
case IFSTUB_STATE_TABLE_MARSHALED:
|
||||
case STUBSTATE_TABLE_STRONG:
|
||||
case STUBSTATE_TABLE_WEAK_MARSHALED:
|
||||
/* no transition */
|
||||
ret = TRUE;
|
||||
break;
|
||||
case IFSTUB_STATE_NORMAL_MARSHALED:
|
||||
ifstub->state = IFSTUB_STATE_NORMAL_UNMARSHALED;
|
||||
case STUBSTATE_TABLE_WEAK_UNMARSHALED:
|
||||
m->state = STUBSTATE_TABLE_WEAK_MARSHALED;
|
||||
ret = TRUE;
|
||||
break;
|
||||
case STUBSTATE_NORMAL_MARSHALED:
|
||||
m->state = STUBSTATE_NORMAL_UNMARSHALED;
|
||||
ret = TRUE;
|
||||
break;
|
||||
default:
|
||||
WARN("object OID %s, IPID %s already unmarshaled\n",
|
||||
wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid));
|
||||
WARN("object OID %s already unmarshaled\n",
|
||||
wine_dbgstr_longlong(m->oid));
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
@ -461,22 +482,39 @@ BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* is an ifstub table marshaled? */
|
||||
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
|
||||
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs)
|
||||
{
|
||||
struct ifstub *ifstub;
|
||||
BOOL ret;
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
||||
ifstub = stub_manager_ipid_to_ifstub(m, ipid);
|
||||
if (!ifstub)
|
||||
switch (m->state)
|
||||
{
|
||||
WARN("Can't find ifstub for OID %s, IPID %s\n",
|
||||
wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid));
|
||||
return FALSE;
|
||||
case STUBSTATE_NORMAL_MARSHALED:
|
||||
case STUBSTATE_NORMAL_UNMARSHALED: /* FIXME: check this */
|
||||
/* nothing to change */
|
||||
break;
|
||||
case STUBSTATE_TABLE_WEAK_UNMARSHALED:
|
||||
case STUBSTATE_TABLE_STRONG:
|
||||
refs = 1;
|
||||
break;
|
||||
case STUBSTATE_TABLE_WEAK_MARSHALED:
|
||||
refs = 0; /* like native */
|
||||
break;
|
||||
}
|
||||
|
||||
stub_manager_ext_release(m, refs);
|
||||
|
||||
LeaveCriticalSection(&m->lock);
|
||||
}
|
||||
|
||||
/* is an ifstub table marshaled? */
|
||||
BOOL stub_manager_is_table_marshaled(struct stub_manager *m)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
ret = (ifstub->state == IFSTUB_STATE_TABLE_MARSHALED);
|
||||
ret = ((m->state == STUBSTATE_TABLE_STRONG) ||
|
||||
(m->state == STUBSTATE_TABLE_WEAK_MARSHALED) ||
|
||||
(m->state == STUBSTATE_TABLE_WEAK_UNMARSHALED));
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return ret;
|
||||
|
@ -688,7 +726,7 @@ HRESULT start_apartment_remote_unknown()
|
|||
{
|
||||
STDOBJREF stdobjref; /* dummy - not used */
|
||||
/* register it with the stub manager */
|
||||
hr = register_ifstub(COM_CurrentApt(), &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL);
|
||||
hr = register_ifstub(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL);
|
||||
/* release our reference to the object as the stub manager will manage the life cycle for us */
|
||||
IRemUnknown_Release(pRemUnknown);
|
||||
if (hr == S_OK)
|
||||
|
|
Loading…
Reference in a new issue