mirror of
https://github.com/reactos/reactos.git
synced 2025-01-04 21:38:43 +00:00
Sync to Wine-20040716:
Mike McCormack <mike@codeweavers.com> - Fix a few serious race conditions in the OLE object pipe server. - Add some explanations to compobj.c, implement flushing message queue on shutdown. Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Marcus Meissner <marcus@jet.franken.de> - IMalloc vtables are static. - IID_IObjectWithSite is already in libuuid, no need to declare here. Aric Stewart <aric@codeweavers.com> - Return an error in CoMarshalInterface if the IUnknown pointer is NULL and don't crash. Ivan Leo Puoti <puoti@inwind.it> - Removed the winedefault.reg message. Robert Shearman <rob@codeweavers.com> - Add static to non-exported marshal functions. - Remove unused marshal functions. - Rename several RPC functions. svn path=/trunk/; revision=10431
This commit is contained in:
parent
66219a7d31
commit
d0bf3394ea
5 changed files with 120 additions and 69 deletions
|
@ -4,8 +4,9 @@
|
|||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1998 Justin Bradford
|
||||
* Copyright 1999 Francis Beaudet
|
||||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 2002 Marcus Meissner
|
||||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 2002 Marcus Meissner
|
||||
* Copyright 2004 Mike Hearn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -118,10 +119,10 @@ static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0,
|
|||
* This section contains OpenDllList definitions
|
||||
*
|
||||
* The OpenDllList contains only handles of dll loaded by CoGetClassObject or
|
||||
* other functions what do LoadLibrary _without_ giving back a HMODULE.
|
||||
* Without this list these handles would be freed never.
|
||||
* other functions that do LoadLibrary _without_ giving back a HMODULE.
|
||||
* Without this list these handles would never be freed.
|
||||
*
|
||||
* FIXME: a DLL what says OK whenn asked for unloading is unloaded in the
|
||||
* FIXME: a DLL that says OK when asked for unloading is unloaded in the
|
||||
* next unload-call but not before 600 sec.
|
||||
*/
|
||||
|
||||
|
@ -147,14 +148,17 @@ static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARA
|
|||
static void COMPOBJ_DLLList_Add(HANDLE hLibrary);
|
||||
static void COMPOBJ_DllList_FreeUnused(int Timeout);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Initialize/Unitialize threading stuff.
|
||||
*/
|
||||
void COMPOBJ_InitProcess( void )
|
||||
{
|
||||
WNDCLASSA wclass;
|
||||
|
||||
/* Inter-thread RPCs are done through window messages rather than pipes. When
|
||||
an interface is marshalled into another apartment in the same process,
|
||||
a window of the following class is created. The *caller* of CoMarshalInterface
|
||||
(ie the application) is responsible for pumping the message loop in that thread,
|
||||
the WM_USER messages which point to the RPCs are then dispatched to COM_AptWndProc
|
||||
by the users code.
|
||||
*/
|
||||
memset(&wclass, 0, sizeof(wclass));
|
||||
wclass.lpfnWndProc = &COM_AptWndProc;
|
||||
wclass.hInstance = OLE32_hInstance;
|
||||
|
@ -170,10 +174,22 @@ void COMPOBJ_UninitProcess( void )
|
|||
/******************************************************************************
|
||||
* Manage apartments.
|
||||
*/
|
||||
|
||||
|
||||
/* The multi-threaded apartment (MTA) contains zero or more threads interacting
|
||||
with free threaded (ie thread safe) COM objects. There is only ever one MTA
|
||||
in a process - you can enter it by calling CoInitializeEx(COINIT_MULTITHREADED)
|
||||
*/
|
||||
static void COM_InitMTA(void)
|
||||
{
|
||||
/* FIXME: how does windoze create OXIDs?
|
||||
* this method will only work for local RPC */
|
||||
/* OXIDs are object exporter IDs. Each apartment has an OXID, which is unique
|
||||
within a network. That is, two different MTAs on different machines will have
|
||||
different OXIDs.
|
||||
|
||||
This method of generating an OXID is therefore wrong as it doesn't work across
|
||||
a network, but for local RPC only it's OK. We can distinguish between MTAs and
|
||||
STAs because STAs use the thread ID as well, and no thread can have an ID of zero.
|
||||
*/
|
||||
MTA.oxid = ((OXID)GetCurrentProcessId() << 32);
|
||||
InitializeCriticalSection(&MTA.cs);
|
||||
}
|
||||
|
@ -204,6 +220,7 @@ APARTMENT* COM_CreateApartment(DWORD model)
|
|||
}
|
||||
else
|
||||
apt = NtCurrentTeb()->ReservedForOle;
|
||||
|
||||
apt->model = model;
|
||||
if (model & COINIT_APARTMENTTHREADED) {
|
||||
/* FIXME: how does windoze create OXIDs? */
|
||||
|
@ -245,6 +262,8 @@ static void COM_DestroyApartment(APARTMENT *apt)
|
|||
HeapFree(GetProcessHeap(), 0, apt);
|
||||
}
|
||||
|
||||
/* The given OXID must be local to this process: you cannot use apartment
|
||||
windows to send RPCs to other processes */
|
||||
HWND COM_GetApartmentWin(OXID oxid)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
|
@ -258,6 +277,7 @@ HWND COM_GetApartmentWin(OXID oxid)
|
|||
return 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);
|
||||
|
@ -378,8 +398,8 @@ HRESULT WINAPI CoInitialize(
|
|||
* RETURNS
|
||||
* S_OK if successful,
|
||||
* S_FALSE if this function was called already.
|
||||
* RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
|
||||
* threading model.
|
||||
* RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified another
|
||||
* threading model.
|
||||
*/
|
||||
HRESULT WINAPI CoInitializeEx(
|
||||
LPVOID lpReserved, /* [in] pointer to win32 malloc interface
|
||||
|
@ -402,7 +422,9 @@ HRESULT WINAPI CoInitializeEx(
|
|||
{
|
||||
if (dwCoInit != apt->model)
|
||||
{
|
||||
WARN("Apartment threading model already initialized with another model\n");
|
||||
/* 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. */
|
||||
WARN("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;
|
||||
|
@ -436,6 +458,25 @@ HRESULT WINAPI CoInitializeEx(
|
|||
return hr;
|
||||
}
|
||||
|
||||
/* On COM finalization for a STA thread, the message queue is flushed to ensure no
|
||||
pending RPCs are ignored. Non-COM messages are discarded at this point.
|
||||
*/
|
||||
void COM_FlushMessageQueue(void)
|
||||
{
|
||||
MSG message;
|
||||
APARTMENT *apt = NtCurrentTeb()->ReservedForOle;
|
||||
|
||||
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;
|
||||
TranslateMessage(&message);
|
||||
DispatchMessageA(&message);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CoUninitialize [OLE32.@]
|
||||
*
|
||||
|
@ -466,27 +507,22 @@ void WINAPI CoUninitialize(void)
|
|||
lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1);
|
||||
if (lCOMRefCnt==1)
|
||||
{
|
||||
/*
|
||||
* Release the various COM libraries and data structures.
|
||||
*/
|
||||
TRACE("() - Releasing the COM libraries\n");
|
||||
|
||||
RunningObjectTableImpl_UnInitialize();
|
||||
/*
|
||||
* Release the references to the registered class objects.
|
||||
*/
|
||||
|
||||
/* Release the references to the registered class objects */
|
||||
COM_RevokeAllClasses();
|
||||
|
||||
/*
|
||||
* This will free the loaded COM Dlls.
|
||||
*/
|
||||
/* This will free the loaded COM Dlls */
|
||||
CoFreeAllLibraries();
|
||||
|
||||
/*
|
||||
* This will free list of external references to COM objects.
|
||||
*/
|
||||
/* This will free list of external references to COM objects */
|
||||
COM_ExternalLockFreeList();
|
||||
|
||||
/* This ensures we deal with any pending RPCs */
|
||||
COM_FlushMessageQueue();
|
||||
|
||||
COM_UninitMTA();
|
||||
}
|
||||
else if (lCOMRefCnt<1) {
|
||||
|
@ -498,10 +534,17 @@ void WINAPI CoUninitialize(void)
|
|||
/******************************************************************************
|
||||
* CoDisconnectObject [COMPOBJ.15]
|
||||
* CoDisconnectObject [OLE32.@]
|
||||
*
|
||||
* Disconnects all connections to this object from remote processes. Dispatches
|
||||
* pending RPCs while blocking new RPCs from occurring, and then calls
|
||||
* IMarshal::DisconnectObject on the given object.
|
||||
*
|
||||
* Typically called when the object server is forced to shut down, for instance by
|
||||
* the user.
|
||||
*/
|
||||
HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
|
||||
{
|
||||
TRACE("(%p, %lx)\n",lpUnk,reserved);
|
||||
FIXME("(%p, %lx): stub - probably harmless\n",lpUnk,reserved);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -821,10 +864,14 @@ HRESULT WINAPI CLSIDFromProgID(
|
|||
/*****************************************************************************
|
||||
* CoGetPSClsid [OLE32.@]
|
||||
*
|
||||
* This function returns the CLSID of the DLL that implements the proxy and stub
|
||||
* This function returns the CLSID of the proxy/stub factory that implements IPSFactoryBuffer
|
||||
* for the specified interface.
|
||||
*
|
||||
* It determines this by searching the
|
||||
* The standard marshaller activates the object with the CLSID returned and uses the
|
||||
* CreateProxy and CreateStub methods on its IPSFactoryBuffer interface to construct
|
||||
* the proxies and stubs for a given object.
|
||||
*
|
||||
* CoGetPSClsid determines this CLSID by searching the
|
||||
* HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
|
||||
* and any interface id registered by CoRegisterPSClsid within the current process.
|
||||
*
|
||||
|
@ -1047,36 +1094,41 @@ _LocalServerThread(LPVOID param) {
|
|||
}
|
||||
IStream_Release(pStm);
|
||||
|
||||
while (1) {
|
||||
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;
|
||||
}
|
||||
if (!ConnectNamedPipe(hPipe,NULL)) {
|
||||
ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
|
||||
CloseHandle(hPipe);
|
||||
continue;
|
||||
}
|
||||
WriteFile(hPipe,buffer,buflen,&res,NULL);
|
||||
CloseHandle(hPipe);
|
||||
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;
|
||||
}
|
||||
WriteFile(hPipe,buffer,buflen,&res,NULL);
|
||||
FlushFileBuffers(hPipe);
|
||||
DisconnectNamedPipe(hPipe);
|
||||
}
|
||||
CloseHandle(hPipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CoRegisterClassObject [OLE32.@]
|
||||
*
|
||||
* This method will register the class object for a given class ID.
|
||||
* 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.
|
||||
*
|
||||
* In Windows, such objects are registered with the RPC endpoint mapper, not with
|
||||
* a unique named pipe.
|
||||
*
|
||||
* See the Windows documentation for more details.
|
||||
*/
|
||||
|
@ -1103,6 +1155,9 @@ HRESULT WINAPI CoRegisterClassObject(
|
|||
/*
|
||||
* First, check if the class is already registered.
|
||||
* If it is, this should cause an error.
|
||||
*
|
||||
* MSDN claims that multiple interface registrations are legal, but we can't do that with
|
||||
* our current implementation.
|
||||
*/
|
||||
hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
|
||||
if (hr == S_OK) {
|
||||
|
@ -1323,7 +1378,7 @@ HRESULT WINAPI CoGetClassObject(
|
|||
return create_marshalled_proxy(rclsid,iid,ppv);
|
||||
}
|
||||
|
||||
/* Finally try remote */
|
||||
/* Finally try remote: this requires networked DCOM (a lot of work) */
|
||||
if (CLSCTX_REMOTE_SERVER & dwClsContext)
|
||||
{
|
||||
FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
|
||||
|
@ -1339,7 +1394,7 @@ HRESULT WINAPI CoGetClassObject(
|
|||
*/
|
||||
HRESULT WINAPI CoResumeClassObjects(void)
|
||||
{
|
||||
FIXME("\n");
|
||||
FIXME("stub\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -1396,7 +1451,7 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
|
|||
}
|
||||
*/
|
||||
|
||||
/* if the obove strategies fail then search for the extension key in the registry */
|
||||
/* if the above strategies fail then search for the extension key in the registry */
|
||||
|
||||
/* get the last element (absolute file) in the path name */
|
||||
nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
|
||||
|
|
|
@ -45,7 +45,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(olemalloc);
|
|||
*
|
||||
*****************************************************************************/
|
||||
/* set the vtable later */
|
||||
extern ICOM_VTABLE(IMalloc) VT_IMalloc32;
|
||||
static ICOM_VTABLE(IMalloc) VT_IMalloc32;
|
||||
|
||||
typedef struct {
|
||||
ICOM_VFIELD(IMalloc);
|
||||
|
@ -361,7 +361,7 @@ static ICOM_VTABLE(IMalloc) VT_IMalloc32 =
|
|||
*****************************************************************************/
|
||||
|
||||
/* set the vtable later */
|
||||
extern ICOM_VTABLE(IMallocSpy) VT_IMallocSpy;
|
||||
static ICOM_VTABLE(IMallocSpy) VT_IMallocSpy;
|
||||
|
||||
typedef struct {
|
||||
ICOM_VFIELD(IMallocSpy);
|
||||
|
|
|
@ -453,6 +453,10 @@ CoMarshalInterface( IStream *pStm, REFIID riid, IUnknown *pUnk,
|
|||
TRACE("(%p, %s, %p, %lx, %p, %lx)\n",
|
||||
pStm,debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags
|
||||
);
|
||||
|
||||
if (pUnk == NULL)
|
||||
return E_INVALIDARG;
|
||||
|
||||
STUBMGR_Start(); /* Just to be sure we have one running. */
|
||||
mid.processid = GetCurrentProcessId();
|
||||
IUnknown_QueryInterface(pUnk,&IID_IUnknown,(LPVOID*)&pUnknown);
|
||||
|
@ -482,17 +486,11 @@ CoMarshalInterface( IStream *pStm, REFIID riid, IUnknown *pUnk,
|
|||
}
|
||||
hres = IMarshal_MarshalInterface(pMarshal,pStm,riid,pUnk,dwDestContext,pvDestContext,mshlflags);
|
||||
if (hres) {
|
||||
if (IsEqualGUID(riid,&IID_IClassFactory)) {
|
||||
MESSAGE("\nERROR: You need to merge the 'winedefault.reg' file into your\n");
|
||||
MESSAGE(" Wine registry by running: `regedit winedefault.reg'\n\n");
|
||||
if (IsEqualGUID(riid,&IID_IOleObject)) {
|
||||
ERR("WINE currently cannot marshal IOleObject interfaces. This means you cannot embed/link OLE objects between applications.\n");
|
||||
} else {
|
||||
if (IsEqualGUID(riid,&IID_IOleObject)) {
|
||||
ERR("WINE currently cannot marshal IOleObject interfaces. This means you cannot embed/link OLE objects between applications.\n");
|
||||
} else {
|
||||
FIXME("Failed to marshal the interface %s, %lx?\n",debugstr_guid(riid),hres);
|
||||
}
|
||||
FIXME("Failed to marshal the interface %s, %lx?\n",debugstr_guid(riid),hres);
|
||||
}
|
||||
goto release_marshal;
|
||||
}
|
||||
release_marshal:
|
||||
IMarshal_Release(pMarshal);
|
||||
|
|
|
@ -466,9 +466,6 @@ static IID const IID_IFontEventsDisp = {
|
|||
static IID const IID_IProvideMultipleClassInfo = {
|
||||
0xA7ABA9C1, 0x8983, 0x11CF, {0x8F,0x20,0x00,0x80,0x5F,0x2C,0xD0,0x64} };
|
||||
|
||||
static IID const IID_IObjectWithSite = {
|
||||
0xFC4801A3, 0x2BA9, 0x11CF, {0xA2,0x29,0x00,0xAA,0x00,0x3D,0x73,0x52} };
|
||||
|
||||
static struct regsvr_interface const interface_list[] = {
|
||||
{ &IID_IUnknown,
|
||||
"IUnknown",
|
||||
|
|
|
@ -512,6 +512,7 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
|
|||
WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF));
|
||||
|
||||
while (tries++<MAXTRIES) {
|
||||
WaitNamedPipeA( pipefn, NMPWAIT_WAIT_FOREVER );
|
||||
hPipe = CreateFileA(
|
||||
pipefn,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
|
|
Loading…
Reference in a new issue