Wine-20050111 vendor drop Added: vendor/wine/dlls/ole32/Wine-20050111/ Modified: vendor/wine/dlls/ole32/Wine-20050111/Makefile.in Modified: vendor/wine/dlls/ole32/Wine-20050111/bindctx.c Modified: vendor/wine/dlls/ole32/Wine-20050111/clipboard.c Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj.c Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj_private.h Modified: vendor/wine/dlls/ole32/Wine-20050111/compositemoniker.c Modified: vendor/wine/dlls/ole32/Wine-20050111/datacache.c Modified: vendor/wine/dlls/ole32/Wine-20050111/defaulthandler.c Modified: vendor/wine/dlls/ole32/Wine-20050111/errorinfo.c Modified: vendor/wine/dlls/ole32/Wine-20050111/filemoniker.c Modified: vendor/wine/dlls/ole32/Wine-20050111/ftmarshal.c Modified: vendor/wine/dlls/ole32/Wine-20050111/hglobalstream.c Modified: vendor/wine/dlls/ole32/Wine-20050111/ifs.c Modified: vendor/wine/dlls/ole32/Wine-20050111/ifs.h Modified: vendor/wine/dlls/ole32/Wine-20050111/itemmoniker.c Modified: vendor/wine/dlls/ole32/Wine-20050111/marshal.c Modified: vendor/wine/dlls/ole32/Wine-20050111/memlockbytes.c Modified: vendor/wine/dlls/ole32/Wine-20050111/moniker.c Modified: vendor/wine/dlls/ole32/Wine-20050111/ole2.c Modified: vendor/wine/dlls/ole32/Wine-20050111/oleobj.c Modified: vendor/wine/dlls/ole32/Wine-20050111/oleproxy.c Modified: vendor/wine/dlls/ole32/Wine-20050111/rpc.c Modified: vendor/wine/dlls/ole32/Wine-20050111/stg_bigblockfile.c Modified: vendor/wine/dlls/ole32/Wine-20050111/stg_stream.c Modified: vendor/wine/dlls/ole32/Wine-20050111/storage32.c Added: vendor/wine/dlls/ole32/Wine-20050111/stubmanager.c Modified: vendor/wine/dlls/ole32/current/Makefile.in Modified: vendor/wine/dlls/ole32/current/bindctx.c Modified: vendor/wine/dlls/ole32/current/clipboard.c Modified: vendor/wine/dlls/ole32/current/compobj.c Modified: vendor/wine/dlls/ole32/current/compobj_private.h Modified: vendor/wine/dlls/ole32/current/compositemoniker.c Modified: vendor/wine/dlls/ole32/current/datacache.c Modified: vendor/wine/dlls/ole32/current/defaulthandler.c Modified: vendor/wine/dlls/ole32/current/errorinfo.c Modified: vendor/wine/dlls/ole32/current/filemoniker.c Modified: vendor/wine/dlls/ole32/current/ftmarshal.c Modified: vendor/wine/dlls/ole32/current/hglobalstream.c Modified: vendor/wine/dlls/ole32/current/ifs.c Modified: vendor/wine/dlls/ole32/current/ifs.h Modified: vendor/wine/dlls/ole32/current/itemmoniker.c Modified: vendor/wine/dlls/ole32/current/marshal.c Modified: vendor/wine/dlls/ole32/current/memlockbytes.c Modified: vendor/wine/dlls/ole32/current/moniker.c Modified: vendor/wine/dlls/ole32/current/ole2.c Modified: vendor/wine/dlls/ole32/current/oleobj.c Modified: vendor/wine/dlls/ole32/current/oleproxy.c Modified: vendor/wine/dlls/ole32/current/rpc.c Modified: vendor/wine/dlls/ole32/current/stg_bigblockfile.c Modified: vendor/wine/dlls/ole32/current/stg_stream.c Modified: vendor/wine/dlls/ole32/current/storage32.c Added: vendor/wine/dlls/ole32/current/stubmanager.c _____
Copied: vendor/wine/dlls/ole32/Wine-20050111 (from rev 12927, vendor/wine/dlls/ole32/current) _____
Modified: vendor/wine/dlls/ole32/Wine-20050111/Makefile.in --- vendor/wine/dlls/ole32/current/Makefile.in 2005-01-11 20:23:48 UTC (rev 12927) +++ vendor/wine/dlls/ole32/Wine-20050111/Makefile.in 2005-01-12 09:03:31 UTC (rev 12947) @@ -35,7 +35,8 @@
rpc.c \ stg_bigblockfile.c \ stg_stream.c \ - storage32.c + storage32.c \ + stubmanager.c
C_SRCS16 = \ memlockbytes16.c \ _____
Modified: vendor/wine/dlls/ole32/Wine-20050111/bindctx.c --- vendor/wine/dlls/ole32/current/bindctx.c 2005-01-11 20:23:48 UTC (rev 12927) +++ vendor/wine/dlls/ole32/Wine-20050111/bindctx.c 2005-01-12 09:03:31 UTC (rev 12947) @@ -275,8 +275,7 @@
if(This->bindCtxTable[index].pObj) IUnknown_Release(This->bindCtxTable[index].pObj); - if(This->bindCtxTable[index].pkeyObj) - HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj); + HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
/* left-shift all elements in the right side of the current revoked object */ for(j=index; j<This->bindCtxTableLastIndex-1; j++) @@ -302,8 +301,7 @@ { if(This->bindCtxTable[i].pObj) IUnknown_Release(This->bindCtxTable[i].pObj); - if(This->bindCtxTable[i].pkeyObj) - HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj); + HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj); }
This->bindCtxTableLastIndex = 0; @@ -472,8 +470,7 @@ /* release the object if it's found */ if(This->bindCtxTable[index].pObj) IUnknown_Release(This->bindCtxTable[index].pObj); - if(This->bindCtxTable[index].pkeyObj) - HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj); + HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
/* remove the object from the table with a left-shifting of all objects in the right side */ for(j=index; j<This->bindCtxTableLastIndex-1; j++) _____
Modified: vendor/wine/dlls/ole32/Wine-20050111/clipboard.c --- vendor/wine/dlls/ole32/current/clipboard.c 2005-01-11 20:23:48 UTC (rev 12927) +++ vendor/wine/dlls/ole32/Wine-20050111/clipboard.c 2005-01-12 09:03:31 UTC (rev 12947) @@ -736,7 +736,7 @@
* We don't bother doing this since the FindClassByAtom code * would have to be changed to deal with this idiosyncrasy. */ wcex.style = CS_GLOBALCLASS; - wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc; + wcex.lpfnWndProc = OLEClipbrd_WndProc; wcex.hInstance = 0; wcex.lpszClassName = OLEClipbrd_WNDCLASS;
@@ -1489,8 +1489,7 @@ /* * Free the array of FORMATETC's */ - if (afmt) - HeapFree(GetProcessHeap(), 0, afmt); + HeapFree(GetProcessHeap(), 0, afmt);
/* * Close Windows clipboard _____
Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj.c --- vendor/wine/dlls/ole32/current/compobj.c 2005-01-11 20:23:48 UTC (rev 12927) +++ vendor/wine/dlls/ole32/Wine-20050111/compobj.c 2005-01-12 09:03:31 UTC (rev 12947) @@ -21,6 +21,44 @@
* 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 + * + * Note + * 1. COINIT_MULTITHREADED is 0; it is the lack of COINIT_APARTMENTTHREADED + * Therefore do not test against COINIT_MULTITHREADED + * + * TODO list: (items bunched together depend on each other) + * + * - Switch wine_marshal_id to use IPIDs not IIDs + * - Once that's done, replace wine_marshal_id with STDOBJREF + * + * - Rewrite the CoLockObjectExternal code, it does totally the wrong + * thing currently (should be controlling the stub manager) + * + * - Make the MTA dynamically allocated and refcounted + * - Free the ReservedForOle data in DllMain(THREAD_DETACH) + * + * - 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 + * 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 + * - Rework threading so re-entrant calls don't need to be sent on + * the incoming pipe + * - Implement RPC thread affinity (should fix InstallShield painting + * problems) + * + * - Implement IRemUnknown and marshalling for it, then use that for + * reffing/unreffing the stub manager from a proxy instead of our + * current hack of simply reffing the stub manager once when it's + * registered. + * - Implement table marshalling, then use it to let us do the final + * rework of the threading + * + * - Make our custom marshalling use NDR to be wire compatible with + * native DCOM + * + * */
#include "config.h" @@ -61,15 +99,15 @@ * * TODO: Most of these things will have to be made thread-safe. */ -HINSTANCE COMPOBJ_hInstance32 = 0;
static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN* ppUnk); -static void COM_RevokeAllClasses(); -static void COM_ExternalLockFreeList(); +static void COM_RevokeAllClasses(void); +static void COM_ExternalLockFreeList(void);
const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
-APARTMENT MTA, *apts; +APARTMENT MTA; +static struct list apts = LIST_INIT( apts );
static CRITICAL_SECTION csApartment; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -102,7 +140,7 @@ DWORD runContext; DWORD connectFlags; DWORD dwCookie; - HANDLE hThread; /* only for localserver */ + LPSTREAM pMarshaledData; /* FIXME: only really need to store OXID and IPID */ struct tagRegisteredClass* nextClass; } RegisteredClass;
@@ -206,6 +244,7 @@ MTA.oxid = 0; }
+ /* creates an apartment structure which stores OLE thread-local * information. Call with COINIT_UNINITIALIZED to create an apartment * that will be initialized with a model later. Note: do not call @@ -213,81 +252,138 @@ * with a different COINIT value */ APARTMENT* COM_CreateApartment(DWORD model) { - APARTMENT *apt; - BOOL create = (NtCurrentTeb()->ReservedForOle == NULL); + APARTMENT *apt = COM_CurrentApt();
- if (create) + if (!apt) { + if (!(model & COINIT_APARTMENTTHREADED)) /* See note 1 above */ + { + TRACE("thread 0x%lx is entering the multithreaded apartment\n", GetCurrentThreadId()); + COM_CurrentInfo()->apt = &MTA; + return COM_CurrentInfo()->apt; + } + + TRACE("creating new apartment, model=%ld\n", model); + apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT)); apt->tid = GetCurrentThreadId(); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &apt->thread, THREAD_ALL_ACCESS, FALSE, 0); + + list_init(&apt->proxies); + list_init(&apt->stubmgrs); + apt->oidc = 1; + apt->refs = 1; + InitializeCriticalSection(&apt->cs); + + apt->model = model; + + /* we don't ref the apartment as CoInitializeEx will do it for us */ + + if (model & COINIT_APARTMENTTHREADED) + { + /* FIXME: how does windoze create OXIDs? */ + apt->oxid = MTA.oxid | GetCurrentThreadId(); + TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid)); + apt->win = CreateWindowA(aptWinClass, NULL, 0, + 0, 0, 0, 0, + 0, 0, OLE32_hInstance, NULL); + } + + EnterCriticalSection(&csApartment); + list_add_head(&apts, &apt->entry); + LeaveCriticalSection(&csApartment); + + COM_CurrentInfo()->apt = apt; } - else - apt = NtCurrentTeb()->ReservedForOle;
- apt->model = model; - if (model & COINIT_APARTMENTTHREADED) { - /* FIXME: how does windoze create OXIDs? */ - apt->oxid = MTA.oxid | GetCurrentThreadId(); - apt->win = CreateWindowA(aptWinClass, NULL, 0, - 0, 0, 0, 0, - 0, 0, OLE32_hInstance, NULL); - InitializeCriticalSection(&apt->cs); - } - else if (!(model & COINIT_UNINITIALIZED)) { - apt->parent = &MTA; - apt->oxid = MTA.oxid; - } - EnterCriticalSection(&csApartment); - if (create) + return apt; +} + +DWORD COM_ApartmentAddRef(struct apartment *apt) +{ + return InterlockedIncrement(&apt->refs); +} + +DWORD COM_ApartmentRelease(struct apartment *apt) +{ + DWORD ret; + + ret = InterlockedDecrement(&apt->refs); + if (ret == 0) { - if (apts) apts->prev = apt; - apt->next = apts; - apts = apt; + TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid)); + + EnterCriticalSection(&csApartment); + list_remove(&apt->entry); + LeaveCriticalSection(&csApartment); + + MARSHAL_Disconnect_Proxies(apt); + + if (apt->win) DestroyWindow(apt->win); + + if (!list_empty(&apt->stubmgrs)) + { + FIXME("Destroy outstanding stubs\n"); + } + + if (apt->filter) IUnknown_Release(apt->filter); + + + DeleteCriticalSection(&apt->cs); + CloseHandle(apt->thread); + HeapFree(GetProcessHeap(), 0, apt); + + apt = NULL; } - LeaveCriticalSection(&csApartment); - NtCurrentTeb()->ReservedForOle = apt; - return apt; + + return ret; }
-static void COM_DestroyApartment(APARTMENT *apt) +/* The given OXID must be local to this process: you cannot use + * apartment windows to send RPCs to other processes. This all needs + * to move to rpcrt4. + * + * The ref parameter is here mostly to ensure people remember that + * they get one, you should normally take a ref for thread safety. + */ +APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref) { + APARTMENT *result = NULL; + struct list *cursor; + EnterCriticalSection(&csApartment); - if (apt->prev) apt->prev->next = apt->next; - if (apt->next) apt->next->prev = apt->prev; - if (apts == apt) apts = apt->next; - apt->prev = NULL; apt->next = NULL; + LIST_FOR_EACH( cursor, &apts ) + { + struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry ); + if (apt->oxid == oxid) + { + result = apt; + if (ref) COM_ApartmentAddRef(result); + break; + } + } LeaveCriticalSection(&csApartment); - if (apt->model & COINIT_APARTMENTTHREADED) { - if (apt->win) DestroyWindow(apt->win); - DeleteCriticalSection(&apt->cs); - } - CloseHandle(apt->thread); - HeapFree(GetProcessHeap(), 0, apt); + + return result; }
-/* The given OXID must be local to this process: you cannot use apartment - windows to send RPCs to other processes. This all needs to move to rpcrt4 */ -HWND COM_GetApartmentWin(OXID oxid) +HWND COM_GetApartmentWin(OXID oxid, BOOL ref) { APARTMENT *apt; - HWND win = 0;
- EnterCriticalSection(&csApartment); - apt = apts; - while (apt && apt->oxid != oxid) apt = apt->next; - if (apt) win = apt->win; - LeaveCriticalSection(&csApartment); - return win; + apt = COM_ApartmentFromOXID(oxid, ref); + if (!apt) return NULL; + + 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); -} +}
/*********************************************************************** ****** * This section contains OpenDllList implemantation @@ -418,8 +514,7 @@ * CoUninitialize */ HRESULT WINAPI CoInitializeEx( - LPVOID lpReserved, /* [in] pointer to win32 malloc interface - (obsolete, should be NULL) */ + LPVOID lpReserved, /* [in] pointer to win32 malloc interface (obsolete, should be NULL) */ DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */ ) { @@ -433,21 +528,6 @@ ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved); }
- apt = NtCurrentTeb()->ReservedForOle; - if (apt && !(apt->model == COINIT_UNINITIALIZED)) - { - if (dwCoInit != apt->model) - { - /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine - code then we are probably using the wrong threading model to implement that API. */ - ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); - return RPC_E_CHANGED_MODE; - } - hr = S_FALSE; - } - else - hr = S_OK; - /* * Check the lock count. If this is the first time going through the initialize * process, we have to initialize the libraries. @@ -463,13 +543,25 @@
COM_InitMTA();
+ /* we may need to defer this until after apartment initialisation */ RunningObjectTableImpl_Initialize(); }
- if (!apt || apt->model == COINIT_UNINITIALIZED) apt = COM_CreateApartment(dwCoInit); + if (!(apt = COM_CurrentInfo()->apt)) + { + apt = COM_CreateApartment(dwCoInit); + if (!apt) return E_OUTOFMEMORY; + } + else if (dwCoInit != apt->model) + { + /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine + code then we are probably using the wrong threading model to implement that API. */ + ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); + COM_ApartmentRelease(apt); + return RPC_E_CHANGED_MODE; + }
- InterlockedIncrement(&apt->inits); - if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt; + COM_CurrentInfo()->inits++;
return hr; } @@ -480,14 +572,20 @@ void COM_FlushMessageQueue(void) { MSG message; - APARTMENT *apt = NtCurrentTeb()->ReservedForOle; + APARTMENT *apt = COM_CurrentApt();
if (!apt || !apt->win) return;
TRACE("Flushing STA message queue\n");
- while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) { - if (message.hwnd != apt->win) continue; + while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) + { + if (message.hwnd != apt->win) + { + WARN("discarding message 0x%x for window %p\n", message.message, message.hwnd); + continue; + } + TranslateMessage(&message); DispatchMessageA(&message); } @@ -511,19 +609,27 @@ */ void WINAPI CoUninitialize(void) { + struct oletls * info = COM_CurrentInfo(); LONG lCOMRefCnt; - APARTMENT *apt;
TRACE("()\n");
- apt = NtCurrentTeb()->ReservedForOle; - if (!apt) return; - if (InterlockedDecrement(&apt->inits)==0) { - NtCurrentTeb()->ReservedForOle = NULL; - COM_DestroyApartment(apt); - apt = NULL; + /* will only happen on OOM */ + if (!info) return; + + /* sanity check */ + if (!info->inits) + { + ERR("Mismatched CoUninitialize\n"); + return; }
+ if (!--info->inits) + { + COM_ApartmentRelease(info->apt); + info->apt = NULL; + } + /* * Decrease the reference count. * If we are back to 0 locks on the COM library, make sure we free @@ -536,14 +642,6 @@
RunningObjectTableImpl_UnInitialize();
- /* disconnect proxies to release the corresponding stubs. - * It is confirmed in "Essential COM" in the sub-chapter on - * "Lifecycle Management and Marshalling" that the native version also - * does some kind of proxy cleanup in this function. - * FIXME: does it just disconnect or completely destroy the proxies? - * FIXME: should this be in the apartment destructor? */ - MARSHAL_Disconnect_Proxies(); - /* Release the references to the registered class objects */ COM_RevokeAllClasses();
@@ -1091,117 +1189,24 @@ return hr; }
-static DWORD WINAPI -_LocalServerThread(LPVOID param) { - HANDLE hPipe; - char pipefn[200]; - RegisteredClass *newClass = (RegisteredClass*)param; - HRESULT hres; - IStream *pStm; - STATSTG ststg; - unsigned char *buffer; - int buflen; - IClassFactory *classfac; - LARGE_INTEGER seekto; - ULARGE_INTEGER newpos; - ULONG res; - - TRACE("Starting threader for %s.\n",debugstr_guid(&newClass->classIdentifier)); - - strcpy(pipefn,PIPEPREF); - WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF)) ; - - hPipe = CreateNamedPipeA( pipefn, PIPE_ACCESS_DUPLEX, - PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, - 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT, NULL ); - if (hPipe == INVALID_HANDLE_VALUE) { - FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError()); - return 1; - } - while (1) { - if (!ConnectNamedPipe(hPipe,NULL)) { - ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError()); - break; - } - - TRACE("marshalling IClassFactory to client\n"); - - hres = IUnknown_QueryInterface(newClass->classObject,&IID_IClassFactory,(LPVOID *)&classfac); - if (hres) return hres; - - hres = CreateStreamOnHGlobal(0,TRUE,&pStm); - if (hres) { - FIXME("Failed to create stream on hglobal.\n"); - return hres; - } - hres = CoMarshalInterface(pStm,&IID_IClassFactory,(LPVOID)classfac,0,NULL,0); - if (hres) { - FIXME("CoMarshalInterface failed, %lx!\n",hres); - return hres; - } - - IUnknown_Release(classfac); /* is this right? */ - - hres = IStream_Stat(pStm,&ststg,0); - if (hres) return hres; - - buflen = ststg.cbSize.u.LowPart; - buffer = HeapAlloc(GetProcessHeap(),0,buflen); - seekto.u.LowPart = 0; - seekto.u.HighPart = 0; - hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); - if (hres) { - FIXME("IStream_Seek failed, %lx\n",hres); - return hres; - } - - hres = IStream_Read(pStm,buffer,buflen,&res); - if (hres) { - FIXME("Stream Read failed, %lx\n",hres); - return hres; - } - - IStream_Release(pStm); - - WriteFile(hPipe,buffer,buflen,&res,NULL); - FlushFileBuffers(hPipe); - DisconnectNamedPipe(hPipe); - - TRACE("done marshalling IClassFactory\n"); - } - CloseHandle(hPipe); - return 0; -} -
/*********************************************************************** ******* * CoRegisterClassObject [OLE32.@] - * - * This method will register the class object for a given class - * ID. Servers housed in EXE files use this method instead of - * exporting DllGetClassObject to allow other code to connect to their - * objects. * - * When a class object (an object which implements IClassFactory) is - * registered in this way, a new thread is started which listens for - * connections on a named pipe specific to the registered CLSID. When - * something else connects to it, it writes out the marshalled - * IClassFactory interface to the pipe. The code on the other end uses - * this buffer to unmarshal the class factory, and can then call - * methods on it. + * Registers the class object for a given class ID. Servers housed in EXE + * files use this method instead of exporting DllGetClassObject to allow + * other code to connect to their objects. * - * In Windows, such objects are registered with the RPC endpoint - * mapper, not with a unique named pipe. - * - * MSDN claims that multiple interface registrations are legal, but we - * can't do that with our current implementation. - * * RETURNS - * S_OK on success, - * E_INVALIDARG if lpdwRegister or pUnk are NULL, + * S_OK on success, + * E_INVALIDARG if lpdwRegister or pUnk are NULL, * CO_E_OBJISREG if the object is already registered. We should not return this. * * SEE ALSO * CoRevokeClassObject, CoGetClassObject + * + * BUGS + * MSDN claims that multiple interface registrations are legal, but we + * can't do that with our current implementation. */ HRESULT WINAPI CoRegisterClassObject( REFCLSID rclsid, /* [in] CLSID of the object to register */ @@ -1220,6 +1225,12 @@ if ( (lpdwRegister==0) || (pUnk==0) ) return E_INVALIDARG;
+ if (!COM_CurrentApt()) + { + ERR("COM was not initialized\n"); + return CO_E_NOTINITIALIZED; + } + *lpdwRegister = 0;
/* @@ -1243,7 +1254,7 @@ newClass->connectFlags = flags; /* * Use the address of the chain node as the cookie since we are sure it's - * unique. + * unique. FIXME: not on 64-bit platforms. */ newClass->dwCookie = (DWORD)newClass; newClass->nextClass = firstRegisteredClass; @@ -1261,10 +1272,30 @@ *lpdwRegister = newClass->dwCookie;
if (dwClsContext & CLSCTX_LOCAL_SERVER) { - DWORD tid; + IClassFactory *classfac;
- STUBMGR_Start(); - newClass->hThread=CreateThread(NULL,0,_LocalServerThread,newClass,0,&tid ); + hr = IUnknown_QueryInterface(newClass->classObject, &IID_IClassFactory, + (LPVOID*)&classfac); + if (hr) return hr; + + hr = CreateStreamOnHGlobal(0, TRUE, &newClass->pMarshaledData); + if (hr) { + FIXME("Failed to create stream on hglobal, %lx\n", hr); + IUnknown_Release(classfac); + return hr; + } + hr = CoMarshalInterface(newClass->pMarshaledData, &IID_IClassFactory, + (LPVOID)classfac, MSHCTX_LOCAL, NULL, + MSHLFLAGS_TABLESTRONG); + if (hr) { + FIXME("CoMarshalInterface failed, %lx!\n",hr); + IUnknown_Release(classfac); + return hr; + } + + IUnknown_Release(classfac); + + RPC_StartLocalServer(&newClass->classIdentifier, newClass->pMarshaledData); } return S_OK; } @@ -1310,6 +1341,15 @@ */ IUnknown_Release(curClass->classObject);
+ if (curClass->pMarshaledData) + { + LARGE_INTEGER zero; + memset(&zero, 0, sizeof(zero)); + /* FIXME: stop local server thread */ + IStream_Seek(curClass->pMarshaledData, zero, SEEK_SET, NULL); + CoReleaseMarshalData(curClass->pMarshaledData); + } + /* * Free the memory used by the chain node. */ @@ -1509,7 +1549,7 @@ pat=ReadPatternFromRegistry(i,j); hFile=CreateFileW(filePathName,,,,,,hFile); SetFilePosition(hFile,pat.offset); - ReadFile(hFile,buf,pat.size,NULL,NULL); + ReadFile(hFile,buf,pat.size,&r,NULL); if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
*pclsid=ReadCLSIDFromRegistry(i); @@ -1573,7 +1613,7 @@ LPCLASSFACTORY lpclf = 0;
if (!COM_CurrentApt()) return CO_E_NOTINITIALIZED; - + /* * Sanity check */ @@ -1590,15 +1630,15 @@ * Rather than create a class factory, we can just check for it here */ if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable)) { - if (StdGlobalInterfaceTableInstance == NULL) + if (StdGlobalInterfaceTableInstance == NULL) StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct(); hres = IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, iid, ppv); if (hres) return hres; - + TRACE("Retrieved GIT (%p)\n", *ppv); return S_OK; } - + /* * Get a class factory to construct the object we want. */ @@ -1982,6 +2022,8 @@ BOOL fLock, /* [in] do lock */ BOOL fLastUnlockReleases) /* [in] unlock all */ { + TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n", + pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE");
if (fLock) { /* @@ -2015,19 +2057,19 @@ */ HRESULT WINAPI CoGetState(IUnknown ** ppv) { - APARTMENT * apt = COM_CurrentInfo(); + HRESULT hr = E_FAIL;
- FIXME("\n"); + *ppv = NULL;
- if(apt && apt->state) { - IUnknown_AddRef(apt->state); - *ppv = apt->state; - FIXME("-- %p\n", *ppv); - return S_OK; - } - *ppv = NULL; - return E_FAIL; + if (COM_CurrentInfo()->state) + { + IUnknown_AddRef(COM_CurrentInfo()->state); + *ppv = COM_CurrentInfo()->state; + TRACE("apt->state=%p\n", COM_CurrentInfo()->state); + hr = S_OK; + }
+ return hr; }
/*********************************************************************** @@ -2036,22 +2078,17 @@ */ HRESULT WINAPI CoSetState(IUnknown * pv) { - APARTMENT * apt = COM_CurrentInfo(); + if (pv) IUnknown_AddRef(pv);
- if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED); + if (COM_CurrentInfo()->state) + { + TRACE("-- release %p now\n", COM_CurrentInfo()->state); + IUnknown_Release(COM_CurrentInfo()->state); + }
- FIXME("(%p),stub!\n", pv); + COM_CurrentInfo()->state = pv;
- if (pv) { - IUnknown_AddRef(pv); - } - - if (apt->state) { - TRACE("-- release %p now\n", apt->state); - IUnknown_Release(apt->state); - } - apt->state = pv; - return S_OK; + return S_OK; }
@@ -2206,7 +2243,7 @@ done: if (hkey) RegCloseKey(hkey); return res; - + }
/*********************************************************************** _____
Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj_private.h --- vendor/wine/dlls/ole32/current/compobj_private.h 2005-01-11 20:23:48 UTC (rev 12927) +++ vendor/wine/dlls/ole32/Wine-20050111/compobj_private.h 2005-01-12 09:03:31 UTC (rev 12947) @@ -5,6 +5,7 @@
* Copyright 1999 Sylvain St-Germain * Copyright 2002 Marcus Meissner * Copyright 2003 Ove Kåven, TransGaming Technologies + * Copyright 2004 Mike Hearn, CodeWeavers Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +29,8 @@
#include <stdarg.h>
+#include "wine/list.h" + #include "windef.h" #include "winbase.h" #include "wtypes.h" @@ -35,13 +38,9 @@ #include "winreg.h" #include "winternl.h"
-/* Windows maps COINIT values to 0x80 for apartment threaded, 0x140 - * for free threaded, and 0 for uninitialized apartments. There is - * no real advantage in us doing this and certainly no release version - * of an app should be poking around with these flags. So we need a - * special value for uninitialized */ -#define COINIT_UNINITIALIZED 0x100 +struct apartment;
+ /* exported interface */ typedef struct tagXIF { struct tagXIF *next; @@ -56,7 +55,7 @@ /* exported object */ typedef struct tagXOBJECT { IRpcStubBufferVtbl *lpVtbl; - struct tagAPARTMENT *parent; + struct apartment *parent; struct tagXOBJECT *next; LPUNKNOWN obj; /* object identity (IUnknown) */ OID oid; /* object ID */ @@ -65,51 +64,54 @@ DWORD refs; /* external reference count */ } XOBJECT;
-/* imported interface */ -typedef struct tagIIF { - struct tagIIF *next; +/* imported interface proxy */ +struct ifproxy +{ + struct list entry; LPVOID iface; /* interface pointer */ IID iid; /* interface ID */ IPID ipid; /* imported interface ID */ LPRPCPROXYBUFFER proxy; /* interface proxy */ DWORD refs; /* imported (public) references */ - HRESULT hres; /* result of proxy creation attempt */ -} IIF; +};
-/* imported object */ -typedef struct tagIOBJECT { - IRemUnknownVtbl *lpVtbl; - struct tagAPARTMENT *parent; - struct tagIOBJECT *next; +/* imported object / proxy manager */ +struct proxy_manager +{ + const IInternalUnknownVtbl *lpVtbl; + struct apartment *parent; + struct list entry; LPRPCCHANNELBUFFER chan; /* channel to object */ OXID oxid; /* object exported ID */ OID oid; /* object ID */ - IPID ipid; /* first imported interface ID */ - IIF *ifaces; /* imported interfaces */ + struct list interfaces; /* imported interfaces */ DWORD refs; /* proxy reference count */ -} IOBJECT; + CRITICAL_SECTION cs; /* thread safety for this object and children */ +};
-/* apartment */ -typedef struct tagAPARTMENT { - struct tagAPARTMENT *next, *prev, *parent; +/* this needs to become a COM object that implements IRemUnknown */ +struct apartment +{ + struct list entry; + + DWORD refs; /* refcount of the apartment */ DWORD model; /* threading model */ - DWORD inits; /* CoInitialize count */ DWORD tid; /* thread id */ HANDLE thread; /* thread handle */ OXID oxid; /* object exporter ID */ - OID oidc; /* object ID counter */ + OID oidc; /* object ID counter, starts at 1, zero is invalid OID */ HWND win; /* message window */ CRITICAL_SECTION cs; /* thread safety */ LPMESSAGEFILTER filter; /* message filter */ XOBJECT *objs; /* exported objects */ - IOBJECT *proxies; /* imported objects */ - LPUNKNOWN state; /* state object (see Co[Get,Set]State) */ - LPVOID ErrorInfo; /* thread error info */ -} APARTMENT; + struct list proxies; /* imported objects */ + DWORD listenertid; /* id of apartment_listener_thread */ + struct list stubmgrs; /* stub managers for exported objects */ +};
-extern APARTMENT MTA, *apts; +typedef struct apartment APARTMENT;
-extern void* StdGlobalInterfaceTable_Construct(); +extern void* StdGlobalInterfaceTable_Construct(void); extern void StdGlobalInterfaceTable_Destroy(void* self); extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv);
@@ -118,75 +120,124 @@
extern void* StdGlobalInterfaceTableInstance;
-#define PIPEPREF "\\.\pipe\" -#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr" - /* Standard Marshalling definitions */ typedef struct _wine_marshal_id { - DWORD processid; - DWORD objectid; /* unique value corresp. IUnknown of object */ - IID iid; + 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->processid == mid2->processid) && - (mid1->objectid == mid2->objectid) && - IsEqualIID(&(mid1->iid),&(mid2->iid)) + (mid1->oxid == mid2->oxid) && + (mid1->oid == mid2->oid) && + IsEqualGUID(&(mid1->ipid),&(mid2->ipid)) ; }
-/* compare without interface compare */ -inline static BOOL -MARSHAL_Compare_Mids_NoInterface(wine_marshal_id *mid1, wine_marshal_id *mid2) { - return - (mid1->processid == mid2->processid) && - (mid1->objectid == mid2->objectid) - ; -} +HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt); +HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
-HRESULT MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub); -void MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid); -HRESULT MARSHAL_Disconnect_Proxies(); +/* Thread-safety Annotation Legend: + * + * RO - The value is read only. It never changes after creation, so no + * locking is required. + * LOCK - The value is written to only using Interlocked* functions. + * CS - The value is read or written to with a critical section held. + * The identifier following "CS" is the specific critical section that + * must be used. + */
-HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv); +/* an interface stub */ +struct ifstub +{ + struct list entry; /* entry in stub_manager->ifstubs list (CS stub_manager->lock) */ + IRpcStubBuffer *stubbuffer; /* RO */ + IID iid; /* RO */ + IPID ipid; /* RO */ + IUnknown *iface; /* RO */ + BOOL table; /* CS stub_manager->lock */ +};
-void STUBMGR_Start();
+/* stub managers hold refs on the object and each interface stub */ +struct stub_manager +{ + struct list entry; /* entry in apartment stubmgr list (CS apt->cs) */ + struct list ifstubs; /* list of active ifstubs for the object (CS lock) */ + CRITICAL_SECTION lock; + APARTMENT *apt; /* owning apt (RO) */ + + ULONG extrefs; /* number of 'external' references (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) */ [truncated at 1000 lines; 7593 more skipped]