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:
Gé van Geldorp 2005-03-14 23:17:44 +00:00
parent 8c43665c8d
commit 9a10a39940
19 changed files with 1483 additions and 1060 deletions

View file

@ -34,6 +34,7 @@ C_SRCS = \
regsvr.c \
rpc.c \
stg_bigblockfile.c \
stg_prop.c \
stg_stream.c \
storage32.c \
stubmanager.c

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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,
};

View file

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

View file

@ -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,
&currentProperty);
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,
&currentProperty);
if (currentProperty.dirProperty != PROPERTY_NULL)
@ -1343,7 +1352,7 @@ static void updatePropertyChain(
/*
* Read
*/
StorageImpl_ReadProperty(storage->ancestorStorage,
StorageImpl_ReadProperty(storage->base.ancestorStorage,
currentProperty.dirProperty,
&currentProperty);
@ -1359,7 +1368,7 @@ static void updatePropertyChain(
{
if (previous != PROPERTY_NULL)
{
StorageImpl_ReadProperty(storage->ancestorStorage,
StorageImpl_ReadProperty(storage->base.ancestorStorage,
previous,
&currentProperty);
current = previous;
@ -1367,7 +1376,7 @@ static void updatePropertyChain(
else
{
currentProperty.previousProperty = newPropertyIndex;
StorageImpl_WriteProperty(storage->ancestorStorage,
StorageImpl_WriteProperty(storage->base.ancestorStorage,
current,
&currentProperty);
found = 1;
@ -1377,7 +1386,7 @@ static void updatePropertyChain(
{
if (next != PROPERTY_NULL)
{
StorageImpl_ReadProperty(storage->ancestorStorage,
StorageImpl_ReadProperty(storage->base.ancestorStorage,
next,
&currentProperty);
current = next;
@ -1385,7 +1394,7 @@ static void updatePropertyChain(
else
{
currentProperty.nextProperty = newPropertyIndex;
StorageImpl_WriteProperty(storage->ancestorStorage,
StorageImpl_WriteProperty(storage->base.ancestorStorage,
current,
&currentProperty);
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,
&currentProperty);
}
}
@ -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;
}

View file

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

View file

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