diff --git a/reactos/lib/ole32/Makefile.in b/reactos/lib/ole32/Makefile.in index 229f1367c1a..81dafe3ffcc 100644 --- a/reactos/lib/ole32/Makefile.in +++ b/reactos/lib/ole32/Makefile.in @@ -34,6 +34,7 @@ C_SRCS = \ regsvr.c \ rpc.c \ stg_bigblockfile.c \ + stg_prop.c \ stg_stream.c \ storage32.c \ stubmanager.c diff --git a/reactos/lib/ole32/clipboard.c b/reactos/lib/ole32/clipboard.c index e21eb5bc061..124cddeaf54 100644 --- a/reactos/lib/ole32/clipboard.c +++ b/reactos/lib/ole32/clipboard.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. */ diff --git a/reactos/lib/ole32/compobj.c b/reactos/lib/ole32/compobj.c index a3da9bf4a38..ffa5af09d5a 100644 --- a/reactos/lib/ole32/compobj.c +++ b/reactos/lib/ole32/compobj.c @@ -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) */ diff --git a/reactos/lib/ole32/compobj_private.h b/reactos/lib/ole32/compobj_private.h index 056f1491d5f..a421a582a01 100644 --- a/reactos/lib/ole32/compobj_private.h +++ b/reactos/lib/ole32/compobj_private.h @@ -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 diff --git a/reactos/lib/ole32/errorinfo.c b/reactos/lib/ole32/errorinfo.c index 5c127347f3f..6a33aa8c329 100644 --- a/reactos/lib/ole32/errorinfo.c +++ b/reactos/lib/ole32/errorinfo.c @@ -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; } diff --git a/reactos/lib/ole32/filemoniker.c b/reactos/lib/ole32/filemoniker.c index d9536989e8e..8c4fffeeb7f 100644 --- a/reactos/lib/ole32/filemoniker.c +++ b/reactos/lib/ole32/filemoniker.c @@ -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); diff --git a/reactos/lib/ole32/git.c b/reactos/lib/ole32/git.c index 18c02c2edae..a6ab947d541 100644 --- a/reactos/lib/ole32/git.c +++ b/reactos/lib/ole32/git.c @@ -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 */ diff --git a/reactos/lib/ole32/itemmoniker.c b/reactos/lib/ole32/itemmoniker.c index 4c1e4e3c8d1..7c59545fbc0 100644 --- a/reactos/lib/ole32/itemmoniker.c +++ b/reactos/lib/ole32/itemmoniker.c @@ -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); } diff --git a/reactos/lib/ole32/marshal.c b/reactos/lib/ole32/marshal.c index 2ae897ae9bf..b0839c73cbc 100644 --- a/reactos/lib/ole32/marshal.c +++ b/reactos/lib/ole32/marshal.c @@ -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); diff --git a/reactos/lib/ole32/ole2.c b/reactos/lib/ole32/ole2.c index cfa0b5aa8a5..3760001fe32 100644 --- a/reactos/lib/ole32/ole2.c +++ b/reactos/lib/ole32/ole2.c @@ -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 ) { diff --git a/reactos/lib/ole32/ole32.spec b/reactos/lib/ole32/ole32.spec index 3a8d3333260..678db3967de 100644 --- a/reactos/lib/ole32/ole32.spec +++ b/reactos/lib/ole32/ole32.spec @@ -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 diff --git a/reactos/lib/ole32/oleproxy.c b/reactos/lib/ole32/oleproxy.c index 951d1660dee..2653017766e 100644 --- a/reactos/lib/ole32/oleproxy.c +++ b/reactos/lib/ole32/oleproxy.c @@ -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); diff --git a/reactos/lib/ole32/rpc.c b/reactos/lib/ole32/rpc.c index e7262045a32..c4c0bb29a6a 100644 --- a/reactos/lib/ole32/rpc.c +++ b/reactos/lib/ole32/rpc.c @@ -1,6 +1,7 @@ /* * (Local) RPC Stuff * + * Copyright 2001 Ove Kåven, TransGaming Technologies * Copyright 2002 Marcus Meissner * Copyright 2005 Mike Hearn, Rob Shearman for CodeWeavers * @@ -49,425 +50,530 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); -#define PIPEPREF "\\\\.\\pipe\\" -#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr" +static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg); -#define REQTYPE_REQUEST 0 -#define REQTYPE_RESPONSE 1 +/* we only use one function to dispatch calls for all methods - we use the + * RPC_IF_OLE flag to tell the RPC runtime that this is the case */ +static RPC_DISPATCH_FUNCTION rpc_dispatch_table[1] = { dispatch_rpc }; /* (RO) */ +static RPC_DISPATCH_TABLE rpc_dispatch = { 1, rpc_dispatch_table }; /* (RO) */ -struct request_header +static struct list registered_interfaces = LIST_INIT(registered_interfaces); /* (CS csRegIf) */ +static CRITICAL_SECTION csRegIf; +static CRITICAL_SECTION_DEBUG csRegIf_debug = { - DWORD reqid; - IPID ipid; - DWORD iMethod; - DWORD cbBuffer; + 0, 0, &csRegIf, + { &csRegIf_debug.ProcessLocksList, &csRegIf_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": dcom registered server interfaces") } +}; +static CRITICAL_SECTION csRegIf = { &csRegIf_debug, -1, 0, 0, 0, 0 }; + +static WCHAR wszPipeTransport[] = {'n','c','a','c','n','_','n','p',0}; + + +struct registered_if +{ + struct list entry; + DWORD refs; /* ref count */ + RPC_SERVER_INTERFACE If; /* interface registered with the RPC runtime */ }; -struct response_header +/* get the pipe endpoint specified of the specified apartment */ +static inline void get_rpc_endpoint(LPWSTR endpoint, const OXID *oxid) { - DWORD reqid; - DWORD cbBuffer; - DWORD retval; -}; - - -#define REQSTATE_START 0 -#define REQSTATE_REQ_QUEUED 1 -#define REQSTATE_REQ_WAITING_FOR_REPLY 2 -#define REQSTATE_REQ_GOT 3 -#define REQSTATE_INVOKING 4 -#define REQSTATE_RESP_QUEUED 5 -#define REQSTATE_RESP_GOT 6 -#define REQSTATE_DONE 6 - -struct rpc -{ - int state; - HANDLE hPipe; /* temp copy of handle */ - struct request_header reqh; - struct response_header resph; - LPBYTE Buffer; -}; - -/* fixme: this should have a lock */ -static struct rpc **reqs = NULL; -static int nrofreqs = 0; - -/* This pipe is _thread_ based, each thread which talks to a remote - * apartment (oxid) has its own pipe. The same structure is used both - * for outgoing and incoming RPCs. - */ -struct pipe -{ - wine_marshal_id mid; /* target mid */ - DWORD tid; /* thread which owns this pipe */ - HANDLE hPipe; - - int pending; - HANDLE hThread; - CRITICAL_SECTION crit; - - APARTMENT *apt; /* apartment of the marshalling thread for the stub dispatch case */ -}; - -typedef struct _PipeBuf { - IRpcChannelBufferVtbl *lpVtbl; - DWORD ref; - - wine_marshal_id mid; - HANDLE pipe; -} PipeBuf; - - - -/* some helper functions */ - -static HRESULT WINAPI read_pipe(HANDLE hf, LPVOID ptr, DWORD size) -{ - DWORD res; - - if (!ReadFile(hf,ptr,size,&res,NULL)) - { - ERR("Failed to read from %p, le is %ld\n",hf,GetLastError()); - return E_FAIL; - } - - if (res != size) - { - if (!res) - { - WARN("%p disconnected\n", hf); - return RPC_E_DISCONNECTED; - } - ERR("Read only %ld of %ld bytes from %p.\n",res,size,hf); - return E_FAIL; - } - return S_OK; + /* FIXME: should get endpoint from rpcss */ + static const WCHAR wszEndpointFormat[] = {'\\','p','i','p','e','\\','O','L','E','_','%','0','8','l','x','%','0','8','l','x',0}; + wsprintfW(endpoint, wszEndpointFormat, (DWORD)(*oxid >> 32),(DWORD)*oxid); } -static HRESULT WINAPI -write_pipe(HANDLE hf, LPVOID ptr, DWORD size) { - DWORD res; - if (!WriteFile(hf,ptr,size,&res,NULL)) { - FIXME("Failed to write to %p, le is %ld\n",hf,GetLastError()); - return E_FAIL; - } - if (res!=size) { - FIXME("Wrote only %ld of %ld bytes to %p.\n",res,size,hf); - return E_FAIL; - } - return S_OK; -} - -static HANDLE dupe_handle(HANDLE h) +typedef struct { - HANDLE h2; - - if (!DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), - &h2, 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - ERR("could not duplicate handle: %ld\n", GetLastError()); - return INVALID_HANDLE_VALUE; - } - - return h2; -} + const IRpcChannelBufferVtbl *lpVtbl; + DWORD refs; +} RpcChannelBuffer; - - - -static DWORD WINAPI client_dispatch_thread(LPVOID); - -/* FIXME: this all needs to be made thread safe */ -static HRESULT RPC_GetRequest(struct rpc **req) +typedef struct { - static int reqid = 0; - int i; + RpcChannelBuffer super; /* superclass */ - /* try to reuse */ - for (i = 0; i < nrofreqs; i++) - { - if (reqs[i]->state == REQSTATE_DONE) - { - TRACE("reusing reqs[%d]\n", i); - - reqs[i]->reqh.reqid = reqid++; - reqs[i]->resph.reqid = reqs[i]->reqh.reqid; - reqs[i]->hPipe = INVALID_HANDLE_VALUE; - reqs[i]->state = REQSTATE_START; - *req = reqs[i]; - return S_OK; - } - } - - TRACE("creating new struct rpc (request)\n"); - - if (reqs) - reqs = (struct rpc**)HeapReAlloc( - GetProcessHeap(), - HEAP_ZERO_MEMORY, - reqs, - sizeof(struct rpc*)*(nrofreqs+1) - ); - else - reqs = (struct rpc**)HeapAlloc( - GetProcessHeap(), - HEAP_ZERO_MEMORY, - sizeof(struct rpc*) - ); - - if (!reqs) return E_OUTOFMEMORY; - - reqs[nrofreqs] = (struct rpc*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(struct rpc)); - reqs[nrofreqs]->reqh.reqid = reqid++; - reqs[nrofreqs]->resph.reqid = reqs[nrofreqs]->reqh.reqid; - reqs[nrofreqs]->hPipe = INVALID_HANDLE_VALUE; - reqs[nrofreqs]->state = REQSTATE_START; - *req = reqs[nrofreqs]; - - nrofreqs++; - - return S_OK; -} + RPC_BINDING_HANDLE bind; /* handle to the remote server */ +} ClientRpcChannelBuffer; -static HRESULT WINAPI -PipeBuf_QueryInterface( - LPRPCCHANNELBUFFER iface,REFIID riid,LPVOID *ppv -) { +static HRESULT WINAPI RpcChannelBuffer_QueryInterface(LPRPCCHANNELBUFFER iface, REFIID riid, LPVOID *ppv) +{ *ppv = NULL; - if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) { - *ppv = (LPVOID)iface; - IUnknown_AddRef(iface); - return S_OK; + if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) + { + *ppv = (LPVOID)iface; + IUnknown_AddRef(iface); + return S_OK; } return E_NOINTERFACE; } -static ULONG WINAPI -PipeBuf_AddRef(LPRPCCHANNELBUFFER iface) { - PipeBuf *This = (PipeBuf *)iface; - return InterlockedIncrement(&This->ref); +static ULONG WINAPI RpcChannelBuffer_AddRef(LPRPCCHANNELBUFFER iface) +{ + RpcChannelBuffer *This = (RpcChannelBuffer *)iface; + return InterlockedIncrement(&This->refs); } -static ULONG WINAPI -PipeBuf_Release(LPRPCCHANNELBUFFER iface) { - PipeBuf *This = (PipeBuf *)iface; +static ULONG WINAPI ServerRpcChannelBuffer_Release(LPRPCCHANNELBUFFER iface) +{ + RpcChannelBuffer *This = (RpcChannelBuffer *)iface; ULONG ref; - ref = InterlockedDecrement(&This->ref); + ref = InterlockedDecrement(&This->refs); if (ref) - return ref; + return ref; - CloseHandle(This->pipe); - HeapFree(GetProcessHeap(),0,This); + HeapFree(GetProcessHeap(), 0, This); return 0; } -static HRESULT WINAPI -PipeBuf_GetBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,REFIID riid) +static ULONG WINAPI ClientRpcChannelBuffer_Release(LPRPCCHANNELBUFFER iface) { - TRACE("(%p,%s)\n",msg,debugstr_guid(riid)); - /* probably reuses IID in real. */ - if (msg->cbBuffer && (msg->Buffer == NULL)) - msg->Buffer = HeapAlloc(GetProcessHeap(),0,msg->cbBuffer); - return S_OK; + ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface; + ULONG ref; + + ref = InterlockedDecrement(&This->super.refs); + if (ref) + return ref; + + RpcBindingFree(&This->bind); + HeapFree(GetProcessHeap(), 0, This); + return 0; } -static HRESULT -COM_InvokeAndRpcSend(struct rpc *req) { - IRpcStubBuffer *stub; - RPCOLEMESSAGE msg; - HRESULT hres; - DWORD reqtype; +static HRESULT WINAPI ServerRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid) +{ + RpcChannelBuffer *This = (RpcChannelBuffer *)iface; + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_STATUS status; - if (!(stub = ipid_to_stubbuffer(&(req->reqh.ipid)))) - /* ipid_to_stubbuffer will already have logged the error */ - return RPC_E_DISCONNECTED; + TRACE("(%p)->(%p,%p)\n", This, olemsg, riid); - IUnknown_AddRef(stub); - msg.Buffer = req->Buffer; - msg.iMethod = req->reqh.iMethod; - msg.cbBuffer = req->reqh.cbBuffer; - msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; - req->state = REQSTATE_INVOKING; - req->resph.retval = IRpcStubBuffer_Invoke(stub,&msg,NULL); - IUnknown_Release(stub); - req->Buffer = msg.Buffer; - req->resph.cbBuffer = msg.cbBuffer; - reqtype = REQTYPE_RESPONSE; - hres = write_pipe(req->hPipe,&reqtype,sizeof(reqtype)); - if (hres) return hres; - hres = write_pipe(req->hPipe,&(req->resph),sizeof(req->resph)); - if (hres) return hres; - hres = write_pipe(req->hPipe,req->Buffer,req->resph.cbBuffer); - if (hres) return hres; - req->state = REQSTATE_DONE; - return S_OK; + status = I_RpcGetBuffer(msg); + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); } -static HRESULT process_incoming_rpc(HANDLE pipe); - -static HRESULT RPC_QueueRequestAndWait(struct rpc *req, HANDLE pipe) +static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid) { - int i; - struct rpc *xreq; - HRESULT hres; - DWORD reqtype; + ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface; + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_CLIENT_INTERFACE *cif; + RPC_STATUS status; - req->hPipe = pipe; - req->state = REQSTATE_REQ_WAITING_FOR_REPLY; - reqtype = REQTYPE_REQUEST; - hres = write_pipe(req->hPipe,&reqtype,sizeof(reqtype)); - if (hres) return hres; - hres = write_pipe(req->hPipe,&(req->reqh),sizeof(req->reqh)); - if (hres) return hres; - hres = write_pipe(req->hPipe,req->Buffer,req->reqh.cbBuffer); - if (hres) return hres; + TRACE("(%p)->(%p,%p)\n", This, olemsg, riid); - /* This loop is about allowing re-entrancy. While waiting for the - * response to one RPC we may receive a request starting another. */ - while (!hres) { - hres = process_incoming_rpc(pipe); - if (hres) break; + cif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_CLIENT_INTERFACE)); + if (!cif) + return E_OUTOFMEMORY; - for (i=0;istate==REQSTATE_REQ_GOT) && (xreq->hPipe==req->hPipe)) { - hres = COM_InvokeAndRpcSend(xreq); - if (hres) break; - } - } - if (req->state == REQSTATE_RESP_GOT) - return S_OK; - } - if (FAILED(hres)) - WARN("-- 0x%08lx\n", hres); - return hres; -} - -static HRESULT WINAPI -PipeBuf_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *msg, ULONG *status) -{ - PipeBuf *This = (PipeBuf *)iface; - struct rpc *req; - HRESULT hres; - - if (This->mid.oxid == COM_CurrentApt()->oxid) { - ERR("Need to call directly!\n"); - return E_FAIL; - } - - hres = RPC_GetRequest(&req); - if (hres) return hres; - req->reqh.iMethod = msg->iMethod; - req->reqh.cbBuffer = msg->cbBuffer; - req->reqh.ipid = This->mid.ipid; - req->Buffer = msg->Buffer; - TRACE(" -> rpc ->\n"); - hres = RPC_QueueRequestAndWait(req, This->pipe); - TRACE(" <- response <-\n"); - if (hres) - { - req->state = REQSTATE_DONE; - return hres; - } + cif->Length = sizeof(RPC_CLIENT_INTERFACE); + /* RPC interface ID = COM interface ID */ + cif->InterfaceId.SyntaxGUID = *riid; + /* COM objects always have a version of 0.0 */ + cif->InterfaceId.SyntaxVersion.MajorVersion = 0; + cif->InterfaceId.SyntaxVersion.MinorVersion = 0; + msg->RpcInterfaceInformation = cif; + msg->Handle = This->bind; - msg->cbBuffer = req->resph.cbBuffer; - msg->Buffer = req->Buffer; - *status = req->resph.retval; - req->state = REQSTATE_DONE; - - return S_OK; + status = I_RpcGetBuffer(msg); + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); } - -static HRESULT WINAPI -PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg) +struct rpc_sendreceive_params { - TRACE("(%p)\n",msg); - HeapFree(GetProcessHeap(), 0, msg->Buffer); - return S_OK; -} - -static HRESULT WINAPI -PipeBuf_GetDestCtx(LPRPCCHANNELBUFFER iface,DWORD* pdwDestContext,void** ppvDestContext) -{ - FIXME("(%p,%p), stub!\n",pdwDestContext,ppvDestContext); - return E_FAIL; -} - -static HRESULT WINAPI -PipeBuf_IsConnected(LPRPCCHANNELBUFFER iface) -{ - FIXME("(), stub!\n"); - return S_OK; -} - -static IRpcChannelBufferVtbl pipebufvt = { - PipeBuf_QueryInterface, - PipeBuf_AddRef, - PipeBuf_Release, - PipeBuf_GetBuffer, - PipeBuf_SendReceive, - PipeBuf_FreeBuffer, - PipeBuf_GetDestCtx, - PipeBuf_IsConnected + RPC_MESSAGE *msg; + RPC_STATUS status; }; -/* returns a pipebuf for proxies */ -HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) +/* this thread runs an outgoing RPC */ +static DWORD WINAPI rpc_sendreceive_thread(LPVOID param) { - wine_marshal_id ourid; - HANDLE handle; - PipeBuf *pbuf; - char pipefn[200]; + struct rpc_sendreceive_params *data = (struct rpc_sendreceive_params *) param; + + TRACE("starting up\n"); - /* connect to the apartment listener thread */ - sprintf(pipefn,OLESTUBMGR"_%08lx%08lx",(DWORD)(mid->oxid >> 32),(DWORD)mid->oxid); + /* FIXME: trap and rethrow RPC exceptions in app thread */ + data->status = I_RpcSendReceive(data->msg); - TRACE("proxy pipe: connecting to apartment listener thread: %s\n", pipefn); + TRACE("completed with status 0x%lx\n", data->status); + + return 0; +} + +static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus) +{ + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + HRESULT hr = S_OK; + HANDLE thread; + struct rpc_sendreceive_params *params; + DWORD tid, res; + RPC_STATUS status; + + TRACE("(%p)\n", msg); + + params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params)); + if (!params) return E_OUTOFMEMORY; + + params->msg = msg; + + /* we use a separate thread here because we need to be able to + * pump the message loop in the application thread: if we do not, + * any windows created by this thread will hang and RPCs that try + * and re-enter this STA from an incoming server thread will + * deadlock. InstallShield is an example of that. + */ + + thread = CreateThread(NULL, 0, rpc_sendreceive_thread, params, 0, &tid); + if (!thread) + { + ERR("Could not create RpcSendReceive thread, error %lx\n", GetLastError()); + return E_UNEXPECTED; + } while (TRUE) { - BOOL ret = WaitNamedPipeA(pipefn, NMPWAIT_USE_DEFAULT_WAIT); - if (!ret) + TRACE("waiting for rpc completion or window message\n"); + res = MsgWaitForMultipleObjectsEx(1, &thread, INFINITE, QS_ALLINPUT, 0); + + if (res == WAIT_OBJECT_0 + 1) /* messages available */ { - ERR("Could not open named pipe %s, error %ld\n", pipefn, GetLastError()); - return RPC_E_SERVER_DIED; + MSG message; + while (PeekMessageW(&message, NULL, 0, 0, PM_REMOVE)) + { + /* FIXME: filter the messages here */ + if (message.message == DM_EXECUTERPC) + TRACE("received DM_EXECUTRPC dispatch request, re-entering ...\n"); + else + TRACE("received message whilst waiting for RPC: 0x%x\n", message.message); + TranslateMessage(&message); + DispatchMessageW(&message); + } } - - handle = CreateFileA(pipefn, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, 0, 0); - - if (handle == INVALID_HANDLE_VALUE) + else if (res == WAIT_OBJECT_0) { - if (GetLastError() == ERROR_PIPE_BUSY) continue; - - ERR("Could not open named pipe %s, error %ld\n", pipefn, GetLastError()); - return RPC_E_SERVER_DIED; + break; /* RPC is completed */ + } + else + { + ERR("Unexpected wait termination: %ld, %ld\n", res, GetLastError()); + hr = E_UNEXPECTED; + break; } - - break; } + + CloseHandle(thread); + + status = params->status; + HeapFree(GetProcessHeap(), 0, params); + params = NULL; + if (hr) return hr; - memset(&ourid,0,sizeof(ourid)); - ourid.oxid = COM_CurrentApt()->oxid; - - TRACE("constructing new pipebuf for proxy\n"); - - pbuf = (PipeBuf*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PipeBuf)); - pbuf->lpVtbl = &pipebufvt; - pbuf->ref = 1; - memcpy(&(pbuf->mid),mid,sizeof(*mid)); - pbuf->pipe = dupe_handle(handle); - - *pipebuf = (IRpcChannelBuffer*)pbuf; - + if (pstatus) *pstatus = status; + + TRACE("RPC call status: 0x%lx\n", status); + if (status == RPC_S_OK) + hr = S_OK; + else if (status == RPC_S_CALL_FAILED) + hr = *(HRESULT *)msg->Buffer; + else + hr = HRESULT_FROM_WIN32(status); + + TRACE("-- 0x%08lx\n", hr); + + return hr; +} + +static HRESULT WINAPI ServerRpcChannelBuffer_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg) +{ + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_STATUS status; + + TRACE("(%p)\n", msg); + + status = I_RpcFreeBuffer(msg); + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); +} + +static HRESULT WINAPI ClientRpcChannelBuffer_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg) +{ + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_STATUS status; + + TRACE("(%p)\n", msg); + + status = I_RpcFreeBuffer(msg); + + HeapFree(GetProcessHeap(), 0, msg->RpcInterfaceInformation); + msg->RpcInterfaceInformation = NULL; + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); +} + +static HRESULT WINAPI RpcChannelBuffer_GetDestCtx(LPRPCCHANNELBUFFER iface, DWORD* pdwDestContext, void** ppvDestContext) +{ + FIXME("(%p,%p), stub!\n", pdwDestContext, ppvDestContext); + return E_FAIL; +} + +static HRESULT WINAPI RpcChannelBuffer_IsConnected(LPRPCCHANNELBUFFER iface) +{ + TRACE("()\n"); + /* native does nothing too */ return S_OK; } -static HRESULT -create_server(REFCLSID rclsid) +static const IRpcChannelBufferVtbl ClientRpcChannelBufferVtbl = +{ + RpcChannelBuffer_QueryInterface, + RpcChannelBuffer_AddRef, + ClientRpcChannelBuffer_Release, + ClientRpcChannelBuffer_GetBuffer, + RpcChannelBuffer_SendReceive, + ClientRpcChannelBuffer_FreeBuffer, + RpcChannelBuffer_GetDestCtx, + RpcChannelBuffer_IsConnected +}; + +static const IRpcChannelBufferVtbl ServerRpcChannelBufferVtbl = +{ + RpcChannelBuffer_QueryInterface, + RpcChannelBuffer_AddRef, + ServerRpcChannelBuffer_Release, + ServerRpcChannelBuffer_GetBuffer, + RpcChannelBuffer_SendReceive, + ServerRpcChannelBuffer_FreeBuffer, + RpcChannelBuffer_GetDestCtx, + RpcChannelBuffer_IsConnected +}; + +/* returns a channel buffer for proxies */ +HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **chan) +{ + ClientRpcChannelBuffer *This; + WCHAR endpoint[200]; + RPC_BINDING_HANDLE bind; + RPC_STATUS status; + LPWSTR string_binding; + + /* connect to the apartment listener thread */ + get_rpc_endpoint(endpoint, oxid); + + TRACE("proxy pipe: connecting to endpoint: %s\n", debugstr_w(endpoint)); + + status = RpcStringBindingComposeW( + NULL, + wszPipeTransport, + NULL, + endpoint, + NULL, + &string_binding); + + if (status == RPC_S_OK) + { + status = RpcBindingFromStringBindingW(string_binding, &bind); + + if (status == RPC_S_OK) + { + IPID ipid2 = *ipid; /* why can't RpcBindingSetObject take a const? */ + status = RpcBindingSetObject(bind, &ipid2); + if (status != RPC_S_OK) + RpcBindingFree(&bind); + } + + RpcStringFreeW(&string_binding); + } + + if (status != RPC_S_OK) + { + ERR("Couldn't get binding for endpoint %s, status = %ld\n", debugstr_w(endpoint), status); + return HRESULT_FROM_WIN32(status); + } + + This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) + { + RpcBindingFree(&bind); + return E_OUTOFMEMORY; + } + + This->super.lpVtbl = &ClientRpcChannelBufferVtbl; + This->super.refs = 1; + This->bind = bind; + + *chan = (IRpcChannelBuffer*)This; + + return S_OK; +} + +HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan) +{ + RpcChannelBuffer *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->lpVtbl = &ServerRpcChannelBufferVtbl; + This->refs = 1; + + *chan = (IRpcChannelBuffer*)This; + + return S_OK; +} + + +HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub) +{ + /* FIXME: pass server channel buffer, but don't create it every time */ + return IRpcStubBuffer_Invoke(stub, msg, NULL); +} + +static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg) +{ + IRpcStubBuffer *stub; + APARTMENT *apt; + IPID ipid; + + RpcBindingInqObject(msg->Handle, &ipid); + + stub = ipid_to_apt_and_stubbuffer(&ipid, &apt); + if (!apt || !stub) + { + if (apt) COM_ApartmentRelease(apt); + /* ipid_to_apt_and_stubbuffer will already have logged the error */ + return RpcRaiseException(RPC_E_DISCONNECTED); + } + + /* Note: this is the important difference between STAs and MTAs - we + * always execute RPCs to STAs in the thread that originally created the + * apartment (i.e. the one that pumps messages to the window) */ + if (apt->model & COINIT_APARTMENTTHREADED) + SendMessageW(apt->win, DM_EXECUTERPC, (WPARAM)msg, (LPARAM)stub); + else + RPC_ExecuteCall((RPCOLEMESSAGE *)msg, stub); + + COM_ApartmentRelease(apt); + IRpcStubBuffer_Release(stub); +} + +/* stub registration */ +HRESULT RPC_RegisterInterface(REFIID riid) +{ + struct registered_if *rif; + BOOL found = FALSE; + HRESULT hr = S_OK; + + TRACE("(%s)\n", debugstr_guid(riid)); + + EnterCriticalSection(&csRegIf); + LIST_FOR_EACH_ENTRY(rif, ®istered_interfaces, struct registered_if, entry) + { + if (IsEqualGUID(&rif->If.InterfaceId.SyntaxGUID, riid)) + { + rif->refs++; + found = TRUE; + break; + } + } + if (!found) + { + TRACE("Creating new interface\n"); + + rif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rif)); + if (rif) + { + RPC_STATUS status; + + rif->refs = 1; + rif->If.Length = sizeof(RPC_SERVER_INTERFACE); + /* RPC interface ID = COM interface ID */ + rif->If.InterfaceId.SyntaxGUID = *riid; + rif->If.DispatchTable = &rpc_dispatch; + /* all other fields are 0, including the version asCOM objects + * always have a version of 0.0 */ + status = RpcServerRegisterIfEx( + (RPC_IF_HANDLE)&rif->If, + NULL, NULL, + RPC_IF_OLE | RPC_IF_AUTOLISTEN, + RPC_C_LISTEN_MAX_CALLS_DEFAULT, + NULL); + if (status == RPC_S_OK) + list_add_tail(®istered_interfaces, &rif->entry); + else + { + ERR("RpcServerRegisterIfEx failed with error %ld\n", status); + HeapFree(GetProcessHeap(), 0, rif); + hr = HRESULT_FROM_WIN32(status); + } + } + else + hr = E_OUTOFMEMORY; + } + LeaveCriticalSection(&csRegIf); + return hr; +} + +/* stub unregistration */ +void RPC_UnregisterInterface(REFIID riid) +{ + struct registered_if *rif; + EnterCriticalSection(&csRegIf); + LIST_FOR_EACH_ENTRY(rif, ®istered_interfaces, struct registered_if, entry) + { + if (IsEqualGUID(&rif->If.InterfaceId.SyntaxGUID, riid)) + { + if (!--rif->refs) + { +#if 0 /* this is a stub in builtin and spams the console with FIXME's */ + IID iid = *riid; /* RpcServerUnregisterIf doesn't take const IID */ + RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, &iid, 0); + list_remove(&rif->entry); + HeapFree(GetProcessHeap(), 0, rif); +#endif + } + break; + } + } + LeaveCriticalSection(&csRegIf); +} + +/* make the apartment reachable by other threads and processes and create the + * IRemUnknown object */ +void RPC_StartRemoting(struct apartment *apt) +{ + if (!InterlockedExchange(&apt->remoting_started, TRUE)) + { + WCHAR endpoint[200]; + RPC_STATUS status; + + get_rpc_endpoint(endpoint, &apt->oxid); + + status = RpcServerUseProtseqEpW( + wszPipeTransport, + RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + endpoint, + NULL); + if (status != RPC_S_OK) + ERR("Couldn't register endpoint %s\n", debugstr_w(endpoint)); + + /* FIXME: move remote unknown exporting into this function */ + } + start_apartment_remote_unknown(); +} + + +static HRESULT create_server(REFCLSID rclsid) { static const WCHAR embedding[] = { ' ', '-','E','m','b','e','d','d','i','n','g',0 }; HKEY key; @@ -512,8 +618,10 @@ create_server(REFCLSID rclsid) if (!CreateProcessW(exe, command, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo)) { WARN("failed to run local server %s\n", debugstr_w(exe)); - return E_FAIL; + return HRESULT_FROM_WIN32(GetLastError()); } + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); return S_OK; } @@ -521,8 +629,7 @@ create_server(REFCLSID rclsid) /* * start_local_service() - start a service given its name and parameters */ -static DWORD -start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) +static DWORD start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) { SC_HANDLE handle, hsvc; DWORD r = ERROR_FUNCTION_FAILED; @@ -559,8 +666,7 @@ start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) * * Note: Local Services are not supported under Windows 9x */ -static HRESULT -create_local_service(REFCLSID rclsid) +static HRESULT create_local_service(REFCLSID rclsid) { HRESULT hres = REGDB_E_READREGDB; WCHAR buf[40], keyname[50]; @@ -625,8 +731,10 @@ create_local_service(REFCLSID rclsid) return hres; } -/* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */ -HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +#define PIPEPREF "\\\\.\\pipe\\" + +/* FIXME: should call to rpcss instead */ +HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { HRESULT hres; HANDLE hPipe; @@ -637,8 +745,8 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) LARGE_INTEGER seekto; ULARGE_INTEGER newpos; int tries = 0; - - static const int MAXTRIES = 10000; + + static const int MAXTRIES = 30; /* 30 seconds */ TRACE("rclsid=%s, iid=%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); @@ -691,302 +799,13 @@ out: } -/* this reads an RPC from the given pipe and places it in the global reqs array */ -static HRESULT process_incoming_rpc(HANDLE pipe) -{ - DWORD reqtype; - HRESULT hres = S_OK; - - hres = read_pipe(pipe,&reqtype,sizeof(reqtype)); - if (hres) return hres; - - /* only received by servers */ - if (reqtype == REQTYPE_REQUEST) - { - struct rpc *xreq; - - RPC_GetRequest(&xreq); - - xreq->hPipe = pipe; - hres = read_pipe(pipe,&(xreq->reqh),sizeof(xreq->reqh)); - if (hres) - { - xreq->state = REQSTATE_DONE; - return hres; - } - - xreq->resph.reqid = xreq->reqh.reqid; - xreq->Buffer = HeapAlloc(GetProcessHeap(),0, xreq->reqh.cbBuffer); - hres = read_pipe(pipe,xreq->Buffer,xreq->reqh.cbBuffer); - if (hres) goto end; - - TRACE("received RPC for IPID %s\n", debugstr_guid(&xreq->reqh.ipid)); - - xreq->state = REQSTATE_REQ_GOT; - goto end; - } - else if (reqtype == REQTYPE_RESPONSE) - { - struct response_header resph; - int i; - - hres = read_pipe(pipe,&resph,sizeof(resph)); - if (hres) goto end; - - TRACE("read RPC response\n"); - - for (i = nrofreqs; i--;) - { - struct rpc *xreq = reqs[i]; - - if (xreq->state != REQSTATE_REQ_WAITING_FOR_REPLY) - continue; - - if (xreq->reqh.reqid == resph.reqid) - { - memcpy(&(xreq->resph),&resph,sizeof(resph)); - - if (xreq->Buffer) - xreq->Buffer = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->Buffer,xreq->resph.cbBuffer); - else - xreq->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->resph.cbBuffer); - - hres = read_pipe(pipe,xreq->Buffer,xreq->resph.cbBuffer); - if (hres) goto end; - - TRACE("received response for reqid 0x%lx\n", xreq->reqh.reqid); - - xreq->state = REQSTATE_RESP_GOT; - goto end; - } - } - - ERR("protocol error: did not find request for id %lx\n",resph.reqid); - hres = E_FAIL; - goto end; - } - - ERR("protocol error: unknown reqtype %ld\n",reqtype); - hres = E_FAIL; -end: - return hres; -} - -struct stub_dispatch_params -{ - struct apartment *apt; - HANDLE pipe; -}; - -/* This thread listens on the given pipe for requests to any stub manager */ -static DWORD WINAPI client_dispatch_thread(LPVOID param) -{ - HANDLE pipe = ((struct stub_dispatch_params *)param)->pipe; - struct apartment *apt = ((struct stub_dispatch_params *)param)->apt; - HRESULT hres = S_OK; - HANDLE shutdown_event = dupe_handle(apt->shutdown_event); - - HeapFree(GetProcessHeap(), 0, param); - - /* join marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */ - COM_CurrentInfo()->apt = apt; - - while (TRUE) - { - int i; - - TRACE("waiting for RPC on OXID: %08lx%08lx\n", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - - /* read a new request into the global array, block if no requests have been sent */ - hres = process_incoming_rpc(pipe); - if (hres) break; - - /* do you expect me to talk? */ - if (WaitForSingleObject(shutdown_event, 0) == WAIT_OBJECT_0) - { - /* no mr bond, i expect you to die! bwahaha */ - CloseHandle(shutdown_event); - break; - } - - TRACE("received RPC on OXID: %08lx%08lx\n", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - - /* now scan the array looking for the RPC just loaded */ - for (i=nrofreqs;i--;) - { - struct rpc *req = reqs[i]; - - if ((req->state == REQSTATE_REQ_GOT) && (req->hPipe == pipe)) - { - hres = COM_InvokeAndRpcSend(req); - if (!hres) break; - } - } - } - - TRACE("exiting with hres %lx\n",hres); - - /* leave marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */ - COM_CurrentInfo()->apt = NULL; - - DisconnectNamedPipe(pipe); - CloseHandle(pipe); - return 0; -} - -struct apartment_listener_params -{ - APARTMENT *apt; - HANDLE event; -}; - -/* This thread listens on a named pipe for each apartment that exports - * objects. It deals with incoming connection requests. Each time a - * client connects a separate thread is spawned for that particular - * connection. - * - * This architecture is different in native DCOM. - */ -static DWORD WINAPI apartment_listener_thread(LPVOID p) -{ - char pipefn[200]; - HANDLE listenPipe, thread_handle; - OVERLAPPED overlapped; - HANDLE wait[2]; - - struct apartment_listener_params * params = (struct apartment_listener_params *)p; - struct apartment *apt = params->apt; - HANDLE event = params->event; - HANDLE apt_shutdown_event = dupe_handle(apt->shutdown_event); - OXID this_oxid = apt->oxid; /* copy here so we can print it when we shut down */ - - HeapFree(GetProcessHeap(), 0, params); - - overlapped.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - - /* we must join the marshalling threads apartment. we already have a ref here */ - COM_CurrentInfo()->apt = apt; - - sprintf(pipefn,OLESTUBMGR"_%08lx%08lx", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - TRACE("Apartment listener thread starting on (%s)\n",pipefn); - - while (TRUE) - { - struct stub_dispatch_params *params; - DWORD res; - - listenPipe = CreateNamedPipeA( - pipefn, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE|PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - 4096, - 4096, - 500 /* 0.5 seconds */, - NULL - ); - - /* tell function that started this thread that we have attempted to created the - * named pipe. */ - if (event) { - SetEvent(event); - event = NULL; - } - - if (listenPipe == INVALID_HANDLE_VALUE) { - FIXME("pipe creation failed for %s, error %ld\n",pipefn,GetLastError()); - break; /* permanent failure, so quit stubmgr thread */ - } - - TRACE("waiting for a client ...\n"); - - /* an already connected pipe is not an error */ - if (!ConnectNamedPipe(listenPipe, &overlapped)) - { - DWORD le = GetLastError(); - - if ((le != ERROR_IO_PENDING) && (le != ERROR_PIPE_CONNECTED)) - { - ERR("Failure during ConnectNamedPipe %ld!\n",GetLastError()); - CloseHandle(listenPipe); - continue; - } - } - - /* wait for action */ - wait[0] = apt_shutdown_event; - wait[1] = overlapped.hEvent; - res = WaitForMultipleObjectsEx(2, wait, FALSE, INFINITE, FALSE); - if (res == WAIT_OBJECT_0) break; - - ResetEvent(overlapped.hEvent); - - /* start the stub dispatch thread for this connection */ - TRACE("starting stub dispatch thread for OXID %08lx%08lx\n", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - params = HeapAlloc(GetProcessHeap(), 0, sizeof(struct stub_dispatch_params)); - if (!params) - { - ERR("out of memory, dropping this client\n"); - CloseHandle(listenPipe); - continue; - } - params->apt = apt; - params->pipe = listenPipe; - thread_handle = CreateThread(NULL, 0, &client_dispatch_thread, params, 0, NULL); - CloseHandle(thread_handle); - } - - TRACE("shutting down: %s\n", wine_dbgstr_longlong(this_oxid)); - - /* we must leave the marshalling threads apartment. we don't have a ref here */ - COM_CurrentInfo()->apt = NULL; - - DisconnectNamedPipe(listenPipe); - CloseHandle(listenPipe); - CloseHandle(overlapped.hEvent); - CloseHandle(apt_shutdown_event); - return 0; -} - -void start_apartment_listener_thread() -{ - APARTMENT *apt = COM_CurrentApt(); - - assert( apt ); - - TRACE("apt->listenertid=%ld\n", apt->listenertid); - - /* apt->listenertid is a hack which needs to die at some point, as - * it leaks information into the apartment structure. in fact, - * this thread isn't quite correct anyway as native RPC doesn't - * use a thread per apartment at all, instead the dispatch thread - * either enters the apartment to perform the RPC (for MTAs, RTAs) - * or does a context switch into it for STAs. - */ - - if (!apt->listenertid) - { - HANDLE thread; - HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL); - struct apartment_listener_params * params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params)); - - params->apt = apt; - params->event = event; - thread = CreateThread(NULL, 0, apartment_listener_thread, params, 0, &apt->listenertid); - CloseHandle(thread); - /* wait for pipe to be created before returning, otherwise we - * might try to use it and fail */ - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - } -} - struct local_server_params { CLSID clsid; IStream *stream; }; +/* FIXME: should call to rpcss instead */ static DWORD WINAPI local_server_thread(LPVOID param) { struct local_server_params * lsp = (struct local_server_params *)param; diff --git a/reactos/lib/ole32/stg_bigblockfile.c b/reactos/lib/ole32/stg_bigblockfile.c index 47ed3384c44..c67d8a987a0 100644 --- a/reactos/lib/ole32/stg_bigblockfile.c +++ b/reactos/lib/ole32/stg_bigblockfile.c @@ -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; } diff --git a/reactos/lib/ole32/stg_prop.c b/reactos/lib/ole32/stg_prop.c new file mode 100644 index 00000000000..543d16192fa --- /dev/null +++ b/reactos/lib/ole32/stg_prop.c @@ -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 +#include +#include +#include +#include + +#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, +}; diff --git a/reactos/lib/ole32/stg_stream.c b/reactos/lib/ole32/stg_stream.c index e6569f5d1b4..476f2e61bff 100644 --- a/reactos/lib/ole32/stg_stream.c +++ b/reactos/lib/ole32/stg_stream.c @@ -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; } diff --git a/reactos/lib/ole32/storage32.c b/reactos/lib/ole32/storage32.c index 633657f319a..cbfeeca1d21 100644 --- a/reactos/lib/ole32/storage32.c +++ b/reactos/lib/ole32/storage32.c @@ -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; } diff --git a/reactos/lib/ole32/storage32.h b/reactos/lib/ole32/storage32.h index 40602ea69f4..2a17dc44acb 100644 --- a/reactos/lib/ole32/storage32.h +++ b/reactos/lib/ole32/storage32.h @@ -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, diff --git a/reactos/lib/ole32/stubmanager.c b/reactos/lib/ole32/stubmanager.c index 24c77517b15..ea8161fe360 100644 --- a/reactos/lib/ole32/stubmanager.c +++ b/reactos/lib/ole32/stubmanager.c @@ -29,6 +29,7 @@ #include #include +#include #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)