mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Sync to Wine-20050111:
Michael Stefaniuc <mstefani@redhat.de> - Do not check for non NULL pointer before HeapFree'ing it. It's redundant. Eric Pouech <pouech-eric@wanadoo.fr> - Fixed some errors in function prototypes. - ReadFile and WriteFile must be passed a parameter for the number of handled bytes when no overlapped operation is done. - Removed excessive statement (break after return or goto, not useful break, not needed vars...) Robert Shearman <rob@codeweavers.com> - Remove unnecessary WNDPROC casts. - Document how thread-safety is ensured for each member of the stub_manager and ifstub structs. - Make stub_manager ref counted to ensure it doesn't get freed whilst it is still being used. - ifstubs are now freed only when the controlling stub_manager is freed. - Rename stub_manager_ref/unref to stub_manager_ext_addref/release respectively and make then take an unsigned long to prevent malicious callers from passing in a negative value and corrupting the ref count. - Rename iid in wine_marshal_id to ipid and use IPIDs instead of IIDs in the stub manager. - The channel buffer can be NULL if the proxy is disconnected, so check for this before releasing it. - Make the ClassFactory proxy support aggregation. - Document how thread-safety is ensured for each member of the stub_manager and ifstub structs. - Make stub_manager ref counted to ensure it doesn't get freed whilst it is still being used. - ifstubs are now freed only when the controlling stub_manager is freed. - Rename stub_manager_ref/unref to stub_manager_ext_addref/release respectively and make then take an unsigned long to prevent malicious callers from passing in a negative value and corrupting the ref count. - The current architecture cannot handle pipes changing address, so use a static array. Fixes memory corruption that sometimes occurs when using multiple pipes. - Fix race on apartment creation. - Display errors in decimal to make searching for the meaning in winerror.h easier. - Move named pipe macros into rpc.c. - Remove unneeded function. - Implement COM local servers using table marshaling to avoid doing the marshaling in a child thread where COM has not been initialized. - Remove unneeded includes and the unused COMPOBJ_hInstance32 variable. - Make the wine_marshal_id structure more like the DCOM OBJREF structure, by replacing the process id field by apartment id (OXID), changing the users of the process id field to use the new field and renaming the objectid field to oid. - Fix StdMarshalImpl_UnmarshalInterface to invalidate and release its stub when doing a same apartment marshal. - Fixed incorrect unsigned test. - Add tracing for proxy ref count functions. - Release the channel on proxy destruction. - Implement proxy manager. - Add documentation to several functions. - Coding style changes according to the style Mike and I have agreed upon for COM related files. - Use OBJREF on the wire for generic marshaling functions. - Add some function declarations to objbase.h. - Add stubs for server ref counting. - Implement HRESULT marshaling. - Make struct oletls ref counted so that it is only detached from the apartment on the final CoUninitialize. - Decrease the size of the crit sec on destroying an apartment - it is only needed for touching the apartment list. - Small cleanups. Mike Hearn <mh@codeweavers.com> - Implement the COM stub manager, refactor the current stub code. - Begin implementing interface stubs. - Make apartment access thread-safe by introducing refcounting and wider usage of the apartment lock. - Rework OLE TLS management to eliminate uninitialised apartments and parent chaining. - Comment out an assert, as we don't yet implement IRemUnknown. - Propagate apartments through the intermediate threads, make listener thread apartment scoped. - Rename the STUBMGR thread to more accurately reflect its purpose. - Add a DCOM todo list. Mike McCormack <mike@codeweavers.com> - Test and fix a few problems with OLE storage streams. - Allow COM to start services containing COM servers. - Tests and fixes for StgOpenStorage. - Test and fix StgCreateDocFile grfModes. Paul Vriens <Paul.Vriens@xs4all.nl> - use Interlocked* functions in AddRef and Release. - store the result of the Interlocked functions and use only this. Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Alexandre Julliard <julliard@winehq.org> - Janitorial: C booleans must not be compared against TRUE. Bill Medland <billmedland@mercuryspeed.com> - Corrected testing for multithreaded (based upon observations by Paul Vriens, Christian Costa and Robert Shearman). - Added TRACE for investigating OXID errors. svn path=/trunk/; revision=12952
This commit is contained in:
parent
f887ae590d
commit
8d07772195
27 changed files with 1959 additions and 919 deletions
153
reactos/include/wine/list.h
Normal file
153
reactos/include/wine/list.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Linked lists support
|
||||
*
|
||||
* Copyright (C) 2002 Alexandre Julliard
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __WINE_SERVER_LIST_H
|
||||
#define __WINE_SERVER_LIST_H
|
||||
|
||||
struct list
|
||||
{
|
||||
struct list *next;
|
||||
struct list *prev;
|
||||
};
|
||||
|
||||
/* Define a list like so:
|
||||
*
|
||||
* struct gadget
|
||||
* {
|
||||
* struct list entry; <-- doesn't have to be the first item in the struct
|
||||
* int a, b;
|
||||
* };
|
||||
*
|
||||
* static struct list global_gadgets = LIST_INIT( global_gadgets );
|
||||
*
|
||||
* or
|
||||
*
|
||||
* struct some_global_thing
|
||||
* {
|
||||
* struct list gadgets;
|
||||
* };
|
||||
*
|
||||
* list_init( &some_global_thing->gadgets );
|
||||
*
|
||||
* Manipulate it like this:
|
||||
*
|
||||
* list_add_head( &global_gadgets, &new_gadget->entry );
|
||||
* list_remove( &new_gadget->entry );
|
||||
* list_add_after( &some_random_gadget->entry, &new_gadget->entry );
|
||||
*
|
||||
* And to iterate over it:
|
||||
*
|
||||
* struct list *cursor;
|
||||
* LIST_FOR_EACH( cursor, &global_gadgets )
|
||||
* {
|
||||
* struct gadget *gadget = LIST_ENTRY( cursor, struct gadget, entry );
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
/* add an element after the specified one */
|
||||
inline static void list_add_after( struct list *elem, struct list *to_add )
|
||||
{
|
||||
to_add->next = elem->next;
|
||||
to_add->prev = elem;
|
||||
elem->next->prev = to_add;
|
||||
elem->next = to_add;
|
||||
}
|
||||
|
||||
/* add an element before the specified one */
|
||||
inline static void list_add_before( struct list *elem, struct list *to_add )
|
||||
{
|
||||
to_add->next = elem;
|
||||
to_add->prev = elem->prev;
|
||||
elem->prev->next = to_add;
|
||||
elem->prev = to_add;
|
||||
}
|
||||
|
||||
/* add element at the head of the list */
|
||||
inline static void list_add_head( struct list *list, struct list *elem )
|
||||
{
|
||||
list_add_after( list, elem );
|
||||
}
|
||||
|
||||
/* add element at the tail of the list */
|
||||
inline static void list_add_tail( struct list *list, struct list *elem )
|
||||
{
|
||||
list_add_before( list, elem );
|
||||
}
|
||||
|
||||
/* remove an element from its list */
|
||||
inline static void list_remove( struct list *elem )
|
||||
{
|
||||
elem->next->prev = elem->prev;
|
||||
elem->prev->next = elem->next;
|
||||
}
|
||||
|
||||
/* get the next element */
|
||||
inline static struct list *list_next( struct list *list, struct list *elem )
|
||||
{
|
||||
struct list *ret = elem->next;
|
||||
if (elem->next == list) ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the previous element */
|
||||
inline static struct list *list_prev( struct list *list, struct list *elem )
|
||||
{
|
||||
struct list *ret = elem->prev;
|
||||
if (elem->prev == list) ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the first element */
|
||||
inline static struct list *list_head( struct list *list )
|
||||
{
|
||||
return list_next( list, list );
|
||||
}
|
||||
|
||||
/* get the last element */
|
||||
inline static struct list *list_tail( struct list *list )
|
||||
{
|
||||
return list_prev( list, list );
|
||||
}
|
||||
|
||||
/* check if a list is empty */
|
||||
inline static int list_empty( struct list *list )
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
/* initialize a list */
|
||||
inline static void list_init( struct list *list )
|
||||
{
|
||||
list->next = list->prev = list;
|
||||
}
|
||||
|
||||
/* iterate through the list */
|
||||
#define LIST_FOR_EACH(cursor,list) \
|
||||
for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
|
||||
|
||||
/* macros for statically initialized lists */
|
||||
#define LIST_INIT(list) { &(list), &(list) }
|
||||
|
||||
/* get pointer to object containing list element */
|
||||
#define LIST_ENTRY(elem, type, field) \
|
||||
((type *)((char *)(elem) - (unsigned int)(&((type *)0)->field)))
|
||||
|
||||
#endif /* __WINE_SERVER_LIST_H */
|
|
@ -1943,4 +1943,67 @@ void __RPC_STUB IGlobalInterfaceTable_GetInterfaceFromGlobal_Stub(
|
|||
|
||||
#endif /* __IGlobalInterfaceTable_INTERFACE_DEFINED__ */
|
||||
|
||||
#ifndef __IInternalUnknown_FWD_DEFINED__
|
||||
#define __IInternalUnknown_FWD_DEFINED__
|
||||
typedef struct IInternalUnknown IInternalUnknown;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IInternalUnknown interface
|
||||
*/
|
||||
#ifndef __IInternalUnknown_INTERFACE_DEFINED__
|
||||
#define __IInternalUnknown_INTERFACE_DEFINED__
|
||||
|
||||
DEFINE_GUID(IID_IInternalUnknown, 0x00000021, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46);
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
struct IInternalUnknown : public IUnknown
|
||||
{
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInternalInterface(
|
||||
REFIID riid,
|
||||
void** ppv) = 0;
|
||||
|
||||
};
|
||||
#else
|
||||
typedef struct IInternalUnknownVtbl IInternalUnknownVtbl;
|
||||
struct IInternalUnknown {
|
||||
const IInternalUnknownVtbl* lpVtbl;
|
||||
};
|
||||
struct IInternalUnknownVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IInternalUnknown* This,
|
||||
REFIID riid,
|
||||
void** ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IInternalUnknown* This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IInternalUnknown* This);
|
||||
|
||||
/*** IInternalUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInternalInterface)(
|
||||
IInternalUnknown* This,
|
||||
REFIID riid,
|
||||
void** ppv);
|
||||
|
||||
END_INTERFACE
|
||||
};
|
||||
|
||||
#ifdef COBJMACROS
|
||||
/*** IUnknown methods ***/
|
||||
#define IInternalUnknown_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define IInternalUnknown_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define IInternalUnknown_Release(p) (p)->lpVtbl->Release(p)
|
||||
/*** IInternalUnknown methods ***/
|
||||
#define IInternalUnknown_QueryInternalInterface(p,a,b) (p)->lpVtbl->QueryInternalInterface(p,a,b)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __IInternalUnknown_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#endif /* __WINE_OBJIDL_H */
|
||||
|
|
|
@ -35,7 +35,8 @@ C_SRCS = \
|
|||
rpc.c \
|
||||
stg_bigblockfile.c \
|
||||
stg_stream.c \
|
||||
storage32.c
|
||||
storage32.c \
|
||||
stubmanager.c
|
||||
|
||||
C_SRCS16 = \
|
||||
memlockbytes16.c \
|
||||
|
|
|
@ -275,8 +275,7 @@ HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
|
|||
|
||||
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 @@ HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)
|
|||
{
|
||||
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 @@ HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
|
|||
/* 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++)
|
||||
|
|
|
@ -736,7 +736,7 @@ static HWND OLEClipbrd_CreateWindow()
|
|||
* 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 @@ CLEANUP:
|
|||
/*
|
||||
* Free the array of FORMATETC's
|
||||
*/
|
||||
if (afmt)
|
||||
HeapFree(GetProcessHeap(), 0, afmt);
|
||||
HeapFree(GetProcessHeap(), 0, afmt);
|
||||
|
||||
/*
|
||||
* Close Windows clipboard
|
||||
|
|
|
@ -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 @@ typedef LPCSTR LPCOLESTR16;
|
|||
*
|
||||
* 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 @@ typedef struct tagRegisteredClass
|
|||
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 @@ static void COM_UninitMTA(void)
|
|||
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,74 +252,131 @@ static void COM_UninitMTA(void)
|
|||
* 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);
|
||||
}
|
||||
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);
|
||||
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 if (!(model & COINIT_UNINITIALIZED)) {
|
||||
apt->parent = &MTA;
|
||||
apt->oxid = MTA.oxid;
|
||||
}
|
||||
EnterCriticalSection(&csApartment);
|
||||
if (create)
|
||||
{
|
||||
if (apts) apts->prev = apt;
|
||||
apt->next = apts;
|
||||
apts = apt;
|
||||
}
|
||||
LeaveCriticalSection(&csApartment);
|
||||
NtCurrentTeb()->ReservedForOle = apt;
|
||||
|
||||
return apt;
|
||||
}
|
||||
|
||||
static void COM_DestroyApartment(APARTMENT *apt)
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt)
|
||||
{
|
||||
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;
|
||||
LeaveCriticalSection(&csApartment);
|
||||
if (apt->model & COINIT_APARTMENTTHREADED) {
|
||||
if (apt->win) DestroyWindow(apt->win);
|
||||
DeleteCriticalSection(&apt->cs);
|
||||
}
|
||||
CloseHandle(apt->thread);
|
||||
HeapFree(GetProcessHeap(), 0, apt);
|
||||
return InterlockedIncrement(&apt->refs);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
HWND win = 0;
|
||||
DWORD ret;
|
||||
|
||||
ret = InterlockedDecrement(&apt->refs);
|
||||
if (ret == 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
apt = apts;
|
||||
while (apt && apt->oxid != oxid) apt = apt->next;
|
||||
if (apt) win = apt->win;
|
||||
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);
|
||||
return win;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HWND COM_GetApartmentWin(OXID oxid, BOOL ref)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
|
||||
apt = COM_ApartmentFromOXID(oxid, ref);
|
||||
if (!apt) return NULL;
|
||||
|
||||
return apt->win;
|
||||
}
|
||||
|
||||
/* Currently inter-thread marshalling is not fully implemented, so this does nothing */
|
||||
|
@ -418,8 +514,7 @@ HRESULT WINAPI CoInitialize(
|
|||
* 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 @@ HRESULT WINAPI CoInitializeEx(
|
|||
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 @@ HRESULT WINAPI CoInitializeEx(
|
|||
|
||||
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 @@ HRESULT WINAPI CoInitializeEx(
|
|||
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,17 +609,25 @@ void COM_FlushMessageQueue(void)
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -536,14 +642,6 @@ void WINAPI CoUninitialize(void)
|
|||
|
||||
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,109 +1189,12 @@ end:
|
|||
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.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* RETURNS
|
||||
* S_OK on success,
|
||||
|
@ -1202,6 +1203,10 @@ _LocalServerThread(LPVOID param) {
|
|||
*
|
||||
* 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 @@ HRESULT WINAPI CoRegisterClassObject(
|
|||
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 @@ HRESULT WINAPI CoRegisterClassObject(
|
|||
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 @@ HRESULT WINAPI CoRegisterClassObject(
|
|||
*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 @@ HRESULT WINAPI CoRevokeClassObject(
|
|||
*/
|
||||
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 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
|
|||
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);
|
||||
|
@ -1982,6 +2022,8 @@ HRESULT WINAPI CoLockObjectExternal(
|
|||
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 CoInitializeWOW(DWORD x,DWORD y) {
|
|||
*/
|
||||
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 CoGetState(IUnknown ** ppv)
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,12 +38,8 @@
|
|||
#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 {
|
||||
|
@ -56,7 +55,7 @@ typedef struct tagXIF {
|
|||
/* 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 @@ typedef struct tagXOBJECT {
|
|||
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,74 +120,123 @@ extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
|
|||
|
||||
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_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub);
|
||||
void MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid);
|
||||
HRESULT MARSHAL_Disconnect_Proxies();
|
||||
|
||||
HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt);
|
||||
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
|
||||
|
||||
void STUBMGR_Start();
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
|
||||
/* 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) */
|
||||
};
|
||||
|
||||
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);
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs);
|
||||
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs);
|
||||
IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *iid);
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal);
|
||||
struct stub_manager *get_stub_manager(OXID oxid, OID oid);
|
||||
struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object);
|
||||
|
||||
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
|
||||
|
||||
void start_apartment_listener_thread(void);
|
||||
|
||||
extern HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf);
|
||||
void RPC_StartLocalServer(REFCLSID clsid, IStream *stream);
|
||||
|
||||
/* This function initialize the Running Object Table */
|
||||
HRESULT WINAPI RunningObjectTableImpl_Initialize();
|
||||
HRESULT WINAPI RunningObjectTableImpl_Initialize(void);
|
||||
|
||||
/* This function uninitialize the Running Object Table */
|
||||
HRESULT WINAPI RunningObjectTableImpl_UnInitialize();
|
||||
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);
|
||||
|
||||
HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id);
|
||||
|
||||
/* compobj.c */
|
||||
APARTMENT *COM_CreateApartment(DWORD model);
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref);
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt);
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt);
|
||||
|
||||
/* this is what is stored in TEB->ReservedForOle */
|
||||
struct oletls
|
||||
{
|
||||
struct apartment *apt;
|
||||
IErrorInfo *errorinfo; /* see errorinfo.c */
|
||||
IUnknown *state; /* see CoSetState */
|
||||
DWORD inits; /* number of times CoInitializeEx called */
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-thread values are stored in the TEB on offset 0xF80,
|
||||
* see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
|
||||
*/
|
||||
static inline APARTMENT* COM_CurrentInfo(void)
|
||||
|
||||
/* will create if necessary */
|
||||
static inline struct oletls *COM_CurrentInfo(void)
|
||||
{
|
||||
APARTMENT* apt = NtCurrentTeb()->ReservedForOle;
|
||||
return apt;
|
||||
}
|
||||
static inline APARTMENT* COM_CurrentApt(void)
|
||||
{
|
||||
APARTMENT* apt = COM_CurrentInfo();
|
||||
if (apt && apt->parent) apt = apt->parent;
|
||||
return apt;
|
||||
if (!NtCurrentTeb()->ReservedForOle)
|
||||
NtCurrentTeb()->ReservedForOle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct oletls));
|
||||
|
||||
return NtCurrentTeb()->ReservedForOle;
|
||||
}
|
||||
|
||||
/* compobj.c */
|
||||
APARTMENT* COM_CreateApartment(DWORD model);
|
||||
HWND COM_GetApartmentWin(OXID oxid);
|
||||
static inline APARTMENT* COM_CurrentApt(void)
|
||||
{
|
||||
return COM_CurrentInfo()->apt;
|
||||
}
|
||||
|
||||
#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
|
||||
|
||||
|
|
|
@ -445,7 +445,7 @@ HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* p
|
|||
|
||||
IMoniker_Enum(iface,TRUE,&enumMk);
|
||||
|
||||
while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
|
||||
while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)){
|
||||
|
||||
IMoniker_GetSizeMax(pmk,&ptmpSize);
|
||||
|
||||
|
|
|
@ -1132,8 +1132,7 @@ static HRESULT WINAPI DataCache_GetData(
|
|||
|
||||
cleanup:
|
||||
|
||||
if (mfBits)
|
||||
HeapFree(GetProcessHeap(), 0, mfBits);
|
||||
HeapFree(GetProcessHeap(), 0, mfBits);
|
||||
|
||||
if (pStream)
|
||||
IStream_Release(pStream);
|
||||
|
|
|
@ -514,17 +514,10 @@ static void DefaultHandler_Destroy(
|
|||
/*
|
||||
* Free the strings idenfitying the object
|
||||
*/
|
||||
if (ptrToDestroy->containerApp!=NULL)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerApp );
|
||||
ptrToDestroy->containerApp = NULL;
|
||||
}
|
||||
|
||||
if (ptrToDestroy->containerObj!=NULL)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerObj );
|
||||
ptrToDestroy->containerObj = NULL;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerApp );
|
||||
ptrToDestroy->containerApp = NULL;
|
||||
HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerObj );
|
||||
ptrToDestroy->containerObj = NULL;
|
||||
|
||||
/*
|
||||
* Release our reference to the data cache.
|
||||
|
@ -822,17 +815,10 @@ static HRESULT WINAPI DefaultHandler_SetHostNames(
|
|||
/*
|
||||
* Be sure to cleanup before re-assinging the strings.
|
||||
*/
|
||||
if (this->containerApp!=NULL)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, this->containerApp );
|
||||
this->containerApp = NULL;
|
||||
}
|
||||
|
||||
if (this->containerObj!=NULL)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, this->containerObj );
|
||||
this->containerObj = NULL;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, this->containerApp );
|
||||
this->containerApp = NULL;
|
||||
HeapFree( GetProcessHeap(), 0, this->containerObj );
|
||||
this->containerObj = NULL;
|
||||
|
||||
/*
|
||||
* Copy the string supplied.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* NOTES:
|
||||
*
|
||||
* The errorinfo is a per-thread object. The reference is stored in the
|
||||
* TEB at offset 0xf80
|
||||
* TEB at offset 0xf80.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
@ -149,13 +149,13 @@ static ISupportErrorInfoVtbl ISupportErrorInfoImpl_VTable;
|
|||
converts a objectpointer to This
|
||||
*/
|
||||
#define _IErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtei)))
|
||||
#define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset);
|
||||
#define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset)
|
||||
|
||||
#define _ICreateErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtcei)))
|
||||
#define _ICOM_THIS_From_ICreateErrorInfo(class, name) class* This = (class*)(((char*)name)-_ICreateErrorInfo_Offset);
|
||||
#define _ICOM_THIS_From_ICreateErrorInfo(class, name) class* This = (class*)(((char*)name)-_ICreateErrorInfo_Offset)
|
||||
|
||||
#define _ISupportErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtsei)))
|
||||
#define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset);
|
||||
#define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset)
|
||||
|
||||
/*
|
||||
converts This to a objectpointer
|
||||
|
@ -227,15 +227,17 @@ static ULONG WINAPI IErrorInfoImpl_Release(
|
|||
IErrorInfo* iface)
|
||||
{
|
||||
_ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
|
||||
TRACE("(%p)->(count=%lu)\n",This,This->ref);
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
if (!InterlockedDecrement(&This->ref))
|
||||
TRACE("(%p)->(count=%lu)\n",This,ref+1);
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
TRACE("-- destroying IErrorInfo(%p)\n",This);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
return 0;
|
||||
}
|
||||
return This->ref;
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IErrorInfoImpl_GetGUID(
|
||||
|
@ -483,20 +485,20 @@ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo)
|
|||
*/
|
||||
HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
||||
{
|
||||
APARTMENT * apt = COM_CurrentInfo();
|
||||
|
||||
TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->ErrorInfo);
|
||||
TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->errorinfo);
|
||||
|
||||
if(!pperrinfo) return E_INVALIDARG;
|
||||
if (!apt || !apt->ErrorInfo)
|
||||
|
||||
if (!COM_CurrentInfo()->errorinfo)
|
||||
{
|
||||
*pperrinfo = NULL;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
*pperrinfo = (IErrorInfo*)(apt->ErrorInfo);
|
||||
*pperrinfo = COM_CurrentInfo()->errorinfo;
|
||||
|
||||
/* clear thread error state */
|
||||
apt->ErrorInfo = NULL;
|
||||
COM_CurrentInfo()->errorinfo = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -506,18 +508,16 @@ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
|||
HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo)
|
||||
{
|
||||
IErrorInfo * pei;
|
||||
APARTMENT * apt = COM_CurrentInfo();
|
||||
|
||||
TRACE("(%ld, %p)\n", dwReserved, perrinfo);
|
||||
|
||||
if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED);
|
||||
|
||||
/* release old errorinfo */
|
||||
pei = (IErrorInfo*)apt->ErrorInfo;
|
||||
if(pei) IErrorInfo_Release(pei);
|
||||
pei = COM_CurrentInfo()->errorinfo;
|
||||
if (pei) IErrorInfo_Release(pei);
|
||||
|
||||
/* set to new value */
|
||||
apt->ErrorInfo = perrinfo;
|
||||
if(perrinfo) IErrorInfo_AddRef(perrinfo);
|
||||
COM_CurrentInfo()->errorinfo = perrinfo;
|
||||
if (perrinfo) IErrorInfo_AddRef(perrinfo);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -325,8 +325,7 @@ HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (This->filePathName!=NULL)
|
||||
HeapFree(GetProcessHeap(),0,This->filePathName);
|
||||
HeapFree(GetProcessHeap(),0,This->filePathName);
|
||||
|
||||
This->filePathName=filePathW;
|
||||
|
||||
|
@ -540,9 +539,7 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
|
|||
{
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
if (This->filePathName!=NULL)
|
||||
HeapFree(GetProcessHeap(),0,This->filePathName);
|
||||
|
||||
HeapFree(GetProcessHeap(),0,This->filePathName);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
|
||||
return S_OK;
|
||||
|
|
|
@ -156,8 +156,6 @@ HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, vo
|
|||
hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
|
||||
IMarshal_Release (pMarshal);
|
||||
return hres;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
|
||||
|
|
|
@ -598,8 +598,9 @@ HRESULT WINAPI HGLOBALStreamImpl_Seek(
|
|||
* If the file pointer ends-up after the end of the stream, the next Write operation will
|
||||
* make the file larger. This is how it is documented.
|
||||
*/
|
||||
if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart) return STG_E_INVALIDFUNCTION;
|
||||
|
||||
newPosition.QuadPart = RtlLargeIntegerAdd(newPosition.QuadPart, dlibMove.QuadPart);
|
||||
if (newPosition.QuadPart < 0) return STG_E_INVALIDFUNCTION;
|
||||
|
||||
if (plibNewPosition) *plibNewPosition = newPosition;
|
||||
This->currentPosition = newPosition;
|
||||
|
|
|
@ -394,10 +394,11 @@ static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface)
|
|||
{
|
||||
|
||||
_MallocSpy *This = (_MallocSpy *)iface;
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
|
||||
TRACE ("(%p)->(count=%lu)\n", This, ref - 1);
|
||||
|
||||
return ++(This->ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -410,13 +411,14 @@ static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface)
|
|||
{
|
||||
|
||||
_MallocSpy *This = (_MallocSpy *)iface;
|
||||
ULONG ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
TRACE ("(%p)->(count=%lu)\n", This, This->ref);
|
||||
TRACE ("(%p)->(count=%lu)\n", This, ref + 1);
|
||||
|
||||
if (!--(This->ref)) {
|
||||
if (!ref) {
|
||||
/* our allocation list MUST be empty here */
|
||||
}
|
||||
return This->ref;
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest)
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef struct IMalloc16 *LPMALLOC16;
|
|||
|
||||
/**********************************************************************/
|
||||
|
||||
extern LPMALLOC16 IMalloc16_Constructor();
|
||||
extern LPMALLOC16 IMalloc16_Constructor(void);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
|
|
|
@ -415,12 +415,8 @@ HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
|
|||
{
|
||||
TRACE("(%p)\n",This);
|
||||
|
||||
if (This->itemName)
|
||||
HeapFree(GetProcessHeap(),0,This->itemName);
|
||||
|
||||
if (This->itemDelimiter)
|
||||
HeapFree(GetProcessHeap(),0,This->itemDelimiter);
|
||||
|
||||
HeapFree(GetProcessHeap(),0,This->itemName);
|
||||
HeapFree(GetProcessHeap(),0,This->itemDelimiter);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
|
||||
return S_OK;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -32,13 +32,10 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "objbase.h"
|
||||
#include "ole2.h"
|
||||
#include "winerror.h"
|
||||
|
||||
#include "ifs.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
|
|
@ -86,9 +86,9 @@ static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable*
|
|||
static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);
|
||||
static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);
|
||||
/* Local functions*/
|
||||
HRESULT WINAPI RunningObjectTableImpl_Initialize();
|
||||
HRESULT WINAPI RunningObjectTableImpl_UnInitialize();
|
||||
HRESULT WINAPI RunningObjectTableImpl_Destroy();
|
||||
HRESULT WINAPI RunningObjectTableImpl_Initialize(void);
|
||||
HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void);
|
||||
HRESULT WINAPI RunningObjectTableImpl_Destroy(void);
|
||||
HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);
|
||||
|
||||
/* Virtual function table for the IRunningObjectTable class. */
|
||||
|
|
|
@ -129,8 +129,8 @@ static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
|
|||
/******************************************************************************
|
||||
* These are the prototypes of the utility methods used to manage a shared menu
|
||||
*/
|
||||
static void OLEMenu_Initialize();
|
||||
static void OLEMenu_UnInitialize();
|
||||
static void OLEMenu_Initialize(void);
|
||||
static void OLEMenu_UnInitialize(void);
|
||||
BOOL OLEMenu_InstallHooks( DWORD tid );
|
||||
BOOL OLEMenu_UnInstallHooks( DWORD tid );
|
||||
OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid );
|
||||
|
@ -142,14 +142,14 @@ LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
|
|||
/******************************************************************************
|
||||
* These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
|
||||
*/
|
||||
void OLEClipbrd_UnInitialize();
|
||||
void OLEClipbrd_Initialize();
|
||||
void OLEClipbrd_UnInitialize(void);
|
||||
void OLEClipbrd_Initialize(void);
|
||||
|
||||
/******************************************************************************
|
||||
* These are the prototypes of the utility methods used for OLE Drag n Drop
|
||||
*/
|
||||
static void OLEDD_Initialize();
|
||||
static void OLEDD_UnInitialize();
|
||||
static void OLEDD_Initialize(void);
|
||||
static void OLEDD_UnInitialize(void);
|
||||
static void OLEDD_InsertDropTarget(
|
||||
DropTargetNode* nodeToAdd);
|
||||
static DropTargetNode* OLEDD_ExtractDropTarget(
|
||||
|
@ -169,7 +169,7 @@ static void OLEDD_TrackStateChange(
|
|||
TrackerWindowInfo* trackerInfo,
|
||||
POINT mousePos,
|
||||
DWORD keyState);
|
||||
static DWORD OLEDD_GetButtonState();
|
||||
static DWORD OLEDD_GetButtonState(void);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -985,8 +985,7 @@ BOOL OLEMenu_UnInstallHooks( DWORD tid )
|
|||
|
||||
CLEANUP:
|
||||
/* Release the hook table entry */
|
||||
if (pHookItem)
|
||||
HeapFree(pHookItem->hHeap, 0, pHookItem );
|
||||
HeapFree(pHookItem->hHeap, 0, pHookItem );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1602,7 +1601,7 @@ static void OLEDD_Initialize()
|
|||
|
||||
ZeroMemory (&wndClass, sizeof(WNDCLASSA));
|
||||
wndClass.style = CS_GLOBALCLASS;
|
||||
wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc;
|
||||
wndClass.lpfnWndProc = OLEDD_DragTrackerWindowProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = sizeof(TrackerWindowInfo*);
|
||||
wndClass.hCursor = 0;
|
||||
|
|
|
@ -50,7 +50,7 @@ typedef struct OleAdviseHolderImpl
|
|||
|
||||
} OleAdviseHolderImpl;
|
||||
|
||||
static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
|
||||
static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void);
|
||||
static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
|
||||
static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
|
||||
static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
|
||||
|
@ -181,8 +181,11 @@ static ULONG WINAPI OleAdviseHolderImpl_AddRef(
|
|||
LPOLEADVISEHOLDER iface)
|
||||
{
|
||||
OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
|
||||
TRACE("(%p)->(ref=%ld)\n", This, This->ref);
|
||||
return ++(This->ref);
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE("(%p)->(ref=%ld)\n", This, ref - 1);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -377,7 +380,7 @@ typedef struct DataAdviseHolder
|
|||
/**************************************************************************
|
||||
* DataAdviseHolder method prototypes
|
||||
*/
|
||||
static IDataAdviseHolder* DataAdviseHolder_Constructor();
|
||||
static IDataAdviseHolder* DataAdviseHolder_Constructor(void);
|
||||
static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
|
||||
static HRESULT WINAPI DataAdviseHolder_QueryInterface(
|
||||
IDataAdviseHolder* iface,
|
||||
|
|
|
@ -271,6 +271,7 @@ typedef struct _CFProxy {
|
|||
DWORD ref;
|
||||
|
||||
IRpcChannelBuffer *chanbuf;
|
||||
IUnknown *outer_unknown;
|
||||
} CFProxy;
|
||||
|
||||
static HRESULT WINAPI IRpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) {
|
||||
|
@ -317,6 +318,8 @@ static void WINAPI IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
|
|||
|
||||
static HRESULT WINAPI
|
||||
CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
|
||||
if (This->outer_unknown) return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) {
|
||||
*ppv = (LPVOID)iface;
|
||||
|
@ -331,15 +334,22 @@ CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
|
|||
|
||||
static ULONG WINAPI CFProxy_AddRef(LPCLASSFACTORY iface) {
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
|
||||
if (This->outer_unknown) return IUnknown_AddRef(This->outer_unknown);
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
static ULONG WINAPI CFProxy_Release(LPCLASSFACTORY iface) {
|
||||
ULONG ref;
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
|
||||
if (This->outer_unknown)
|
||||
ref = IUnknown_Release(This->outer_unknown);
|
||||
else
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
if (!ref) HeapFree(GetProcessHeap(),0,This);
|
||||
if (!ref) {
|
||||
if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
@ -425,7 +435,7 @@ static IClassFactoryVtbl cfproxyvt = {
|
|||
};
|
||||
|
||||
static HRESULT
|
||||
CFProxy_Construct(LPVOID *ppv,LPVOID *ppProxy) {
|
||||
CFProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
|
||||
CFProxy *cf;
|
||||
|
||||
cf = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CFProxy));
|
||||
|
@ -434,10 +444,13 @@ CFProxy_Construct(LPVOID *ppv,LPVOID *ppProxy) {
|
|||
|
||||
cf->lpvtbl_cf = &cfproxyvt;
|
||||
cf->lpvtbl_proxy = &pspbvtbl;
|
||||
/* 1 reference for the proxy and 1 for the object */
|
||||
cf->ref = 2;
|
||||
/* 1 reference for the proxy... */
|
||||
cf->ref = 1;
|
||||
cf->outer_unknown = pUnkOuter;
|
||||
*ppv = &(cf->lpvtbl_cf);
|
||||
*ppProxy = &(cf->lpvtbl_proxy);
|
||||
/* ...and 1 for the object */
|
||||
IUnknown_AddRef((IUnknown *)*ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -465,7 +478,7 @@ PSFacBuf_CreateProxy(
|
|||
if (IsEqualIID(&IID_IClassFactory,riid) ||
|
||||
IsEqualIID(&IID_IUnknown,riid)
|
||||
)
|
||||
return CFProxy_Construct(ppv,(LPVOID*)ppProxy);
|
||||
return CFProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
|
||||
FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid));
|
||||
return E_FAIL;
|
||||
}
|
||||
|
|
|
@ -33,18 +33,14 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winsvc.h"
|
||||
#include "objbase.h"
|
||||
#include "ole2.h"
|
||||
#include "ole2ver.h"
|
||||
#include "rpc.h"
|
||||
#include "winerror.h"
|
||||
#include "winreg.h"
|
||||
#include "wownt32.h"
|
||||
#include "wtypes.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "compobj_private.h"
|
||||
#include "ifs.h"
|
||||
|
||||
#include "compobj_private.h"
|
||||
|
||||
|
@ -52,6 +48,9 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
#define PIPEPREF "\\\\.\\pipe\\"
|
||||
#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr"
|
||||
|
||||
#define REQTYPE_REQUEST 0
|
||||
typedef struct _wine_rpc_request_header {
|
||||
DWORD reqid;
|
||||
|
@ -96,18 +95,24 @@ static wine_rpc_request **reqs = NULL;
|
|||
static int nrofreqs = 0;
|
||||
|
||||
/* This pipe is _thread_ based, each thread which talks to a remote
|
||||
* apartment (mid) has its own pipe */
|
||||
* apartment (mid) has its own pipe. The same structure is used both
|
||||
* for outgoing and incoming RPCs.
|
||||
*/
|
||||
typedef struct _wine_pipe {
|
||||
wine_marshal_id mid; /* target mid */
|
||||
DWORD tid; /* thread which owns this outgoing pipe */
|
||||
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 */
|
||||
} wine_pipe;
|
||||
|
||||
static wine_pipe *pipes = NULL;
|
||||
#define MAX_WINE_PIPES 256
|
||||
|
||||
static wine_pipe pipes[MAX_WINE_PIPES];
|
||||
static int nrofpipes = 0;
|
||||
|
||||
typedef struct _PipeBuf {
|
||||
|
@ -115,14 +120,13 @@ typedef struct _PipeBuf {
|
|||
DWORD ref;
|
||||
|
||||
wine_marshal_id mid;
|
||||
wine_pipe *pipe;
|
||||
} PipeBuf;
|
||||
|
||||
static HRESULT WINAPI
|
||||
read_pipe(HANDLE hf, LPVOID ptr, DWORD size) {
|
||||
DWORD res;
|
||||
if (!ReadFile(hf,ptr,size,&res,NULL)) {
|
||||
FIXME("Failed to read from %p, le is %lx\n",hf,GetLastError());
|
||||
FIXME("Failed to read from %p, le is %ld\n",hf,GetLastError());
|
||||
return E_FAIL;
|
||||
}
|
||||
if (res!=size) {
|
||||
|
@ -162,7 +166,7 @@ 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 %lx\n",hf,GetLastError());
|
||||
FIXME("Failed to write to %p, le is %ld\n",hf,GetLastError());
|
||||
return E_FAIL;
|
||||
}
|
||||
if (res!=size) {
|
||||
|
@ -172,30 +176,30 @@ write_pipe(HANDLE hf, LPVOID ptr, DWORD size) {
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static DWORD WINAPI _StubReaderThread(LPVOID);
|
||||
static DWORD WINAPI stub_dispatch_thread(LPVOID);
|
||||
|
||||
static HRESULT
|
||||
PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader) {
|
||||
int i;
|
||||
char pipefn[100];
|
||||
wine_pipe *new_pipes;
|
||||
|
||||
for (i=0;i<nrofpipes;i++)
|
||||
if (pipes[i].mid.processid==mid->processid)
|
||||
if (pipes[i].mid.oxid==mid->oxid)
|
||||
return S_OK;
|
||||
if (pipes)
|
||||
new_pipes=(wine_pipe*)HeapReAlloc(GetProcessHeap(),0,pipes,sizeof(pipes[0])*(nrofpipes+1));
|
||||
else
|
||||
new_pipes=(wine_pipe*)HeapAlloc(GetProcessHeap(),0,sizeof(pipes[0]));
|
||||
if (!new_pipes) return E_OUTOFMEMORY;
|
||||
pipes = new_pipes;
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
|
||||
if (nrofpipes + 1 >= MAX_WINE_PIPES)
|
||||
{
|
||||
FIXME("Out of pipes, please increase MAX_WINE_PIPES\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx%08lx",(DWORD)(mid->oxid >> 32),(DWORD)mid->oxid);
|
||||
memcpy(&(pipes[nrofpipes].mid),mid,sizeof(*mid));
|
||||
pipes[nrofpipes].hPipe = hPipe;
|
||||
pipes[nrofpipes].apt = COM_CurrentApt();
|
||||
assert( pipes[nrofpipes].apt );
|
||||
InitializeCriticalSection(&(pipes[nrofpipes].crit));
|
||||
nrofpipes++;
|
||||
if (startreader) {
|
||||
pipes[nrofpipes-1].hThread = CreateThread(NULL,0,_StubReaderThread,(LPVOID)(pipes+(nrofpipes-1)),0,&(pipes[nrofpipes-1].tid));
|
||||
pipes[nrofpipes-1].hThread = CreateThread(NULL,0,stub_dispatch_thread,(LPVOID)(pipes+(nrofpipes-1)),0,&(pipes[nrofpipes-1].tid));
|
||||
} else {
|
||||
pipes[nrofpipes-1].tid = GetCurrentThreadId();
|
||||
}
|
||||
|
@ -206,7 +210,7 @@ static HANDLE
|
|||
PIPE_FindByMID(wine_marshal_id *mid) {
|
||||
int i;
|
||||
for (i=0;i<nrofpipes;i++)
|
||||
if ((pipes[i].mid.processid==mid->processid) &&
|
||||
if ((pipes[i].mid.oxid==mid->oxid) &&
|
||||
(GetCurrentThreadId()==pipes[i].tid)
|
||||
)
|
||||
return pipes[i].hPipe;
|
||||
|
@ -217,7 +221,7 @@ static wine_pipe*
|
|||
PIPE_GetFromMID(wine_marshal_id *mid) {
|
||||
int i;
|
||||
for (i=0;i<nrofpipes;i++) {
|
||||
if ((pipes[i].mid.processid==mid->processid) &&
|
||||
if ((pipes[i].mid.oxid==mid->oxid) &&
|
||||
(GetCurrentThreadId()==pipes[i].tid)
|
||||
)
|
||||
return pipes+i;
|
||||
|
@ -303,8 +307,6 @@ PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
|
|||
if (ref)
|
||||
return ref;
|
||||
|
||||
FIXME("Free all stuff\n");
|
||||
|
||||
memcpy(&header.mid, &This->mid, sizeof(wine_marshal_id));
|
||||
|
||||
pipe = PIPE_FindByMID(&This->mid);
|
||||
|
@ -333,16 +335,18 @@ PipeBuf_GetBuffer(
|
|||
|
||||
static HRESULT
|
||||
COM_InvokeAndRpcSend(wine_rpc_request *req) {
|
||||
IRpcStubBuffer *stub;
|
||||
IRpcStubBuffer *stub;
|
||||
RPCOLEMESSAGE msg;
|
||||
HRESULT hres;
|
||||
DWORD reqtype;
|
||||
|
||||
hres = MARSHAL_Find_Stub_Buffer(&(req->reqh.mid),&stub);
|
||||
if (hres) {
|
||||
if (!(stub = mid_to_stubbuffer(&(req->reqh.mid))))
|
||||
{
|
||||
ERR("Stub not found?\n");
|
||||
return hres;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
IUnknown_AddRef(stub);
|
||||
msg.Buffer = req->Buffer;
|
||||
msg.iMethod = req->reqh.iMethod;
|
||||
msg.cbBuffer = req->reqh.cbBuffer;
|
||||
|
@ -378,10 +382,6 @@ RPC_QueueRequestAndWait(wine_rpc_request *req) {
|
|||
FIXME("no pipe found.\n");
|
||||
return E_POINTER;
|
||||
}
|
||||
if (GetCurrentProcessId() == req->reqh.mid.processid) {
|
||||
ERR("In current process?\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
req->hPipe = xpipe->hPipe;
|
||||
req->state = REQSTATE_REQ_WAITING_FOR_REPLY;
|
||||
reqtype = REQTYPE_REQUEST;
|
||||
|
@ -423,7 +423,7 @@ PipeBuf_SendReceive(
|
|||
|
||||
TRACE("()\n");
|
||||
|
||||
if (This->mid.processid == GetCurrentProcessId()) {
|
||||
if (This->mid.oxid == COM_CurrentApt()->oxid) {
|
||||
ERR("Need to call directly!\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) {
|
|||
hPipe = PIPE_FindByMID(mid);
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
char pipefn[200];
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx%08lx",(DWORD)(mid->oxid >> 32),(DWORD)mid->oxid);
|
||||
hPipe = CreateFileA(
|
||||
pipefn,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
|
@ -506,7 +506,7 @@ PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) {
|
|||
hres = PIPE_RegisterPipe(mid, hPipe, FALSE);
|
||||
if (hres) return hres;
|
||||
memset(&ourid,0,sizeof(ourid));
|
||||
ourid.processid = GetCurrentProcessId();
|
||||
ourid.oxid = COM_CurrentApt()->oxid;
|
||||
if (!WriteFile(hPipe,&ourid,sizeof(ourid),&res,NULL)||(res!=sizeof(ourid))) {
|
||||
ERR("Failed writing startup mid!\n");
|
||||
return E_FAIL;
|
||||
|
@ -569,6 +569,116 @@ create_server(REFCLSID rclsid) {
|
|||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* start_local_service() - start a service given its name and parameters
|
||||
*/
|
||||
static DWORD
|
||||
start_local_service(LPCWSTR name, DWORD num, LPWSTR *params)
|
||||
{
|
||||
SC_HANDLE handle, hsvc;
|
||||
DWORD r = ERROR_FUNCTION_FAILED;
|
||||
|
||||
TRACE("Starting service %s %ld params\n", debugstr_w(name), num);
|
||||
|
||||
handle = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
if (!handle)
|
||||
return r;
|
||||
hsvc = OpenServiceW(handle, name, SC_MANAGER_ALL_ACCESS);
|
||||
if (hsvc)
|
||||
{
|
||||
if(StartServiceW(hsvc, num, (LPCWSTR*)params))
|
||||
r = ERROR_SUCCESS;
|
||||
else
|
||||
r = GetLastError();
|
||||
if (r==ERROR_SERVICE_ALREADY_RUNNING)
|
||||
r = ERROR_SUCCESS;
|
||||
CloseServiceHandle(hsvc);
|
||||
}
|
||||
CloseServiceHandle(handle);
|
||||
|
||||
TRACE("StartService returned error %ld (%s)\n", r, r?"ok":"failed");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* create_local_service() - start a COM server in a service
|
||||
*
|
||||
* To start a Local Service, we read the AppID value under
|
||||
* the class's CLSID key, then open the HKCR\\AppId key specified
|
||||
* there and check for a LocalService value.
|
||||
*
|
||||
* Note: Local Services are not supported under Windows 9x
|
||||
*/
|
||||
static HRESULT
|
||||
create_local_service(REFCLSID rclsid)
|
||||
{
|
||||
HRESULT hres = REGDB_E_READREGDB;
|
||||
WCHAR buf[40], keyname[50];
|
||||
static const WCHAR szClsId[] = { 'C','L','S','I','D','\\',0 };
|
||||
static const WCHAR szAppId[] = { 'A','p','p','I','d',0 };
|
||||
static const WCHAR szAppIdKey[] = { 'A','p','p','I','d','\\',0 };
|
||||
static const WCHAR szLocalService[] = {
|
||||
'L','o','c','a','l','S','e','r','v','i','c','e',0 };
|
||||
static const WCHAR szServiceParams[] = {
|
||||
'S','e','r','v','i','c','e','P','a','r','a','m','s',0};
|
||||
HKEY hkey;
|
||||
LONG r;
|
||||
DWORD type, sz;
|
||||
|
||||
TRACE("Attempting to start Local service for %s\n", debugstr_guid(rclsid));
|
||||
|
||||
/* read the AppID value under the class's key */
|
||||
strcpyW(keyname,szClsId);
|
||||
StringFromGUID2(rclsid,&keyname[6],39);
|
||||
r = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &hkey);
|
||||
if (r!=ERROR_SUCCESS)
|
||||
return hres;
|
||||
sz = sizeof buf;
|
||||
r = RegQueryValueExW(hkey, szAppId, NULL, &type, (LPBYTE)buf, &sz);
|
||||
RegCloseKey(hkey);
|
||||
if (r!=ERROR_SUCCESS || type!=REG_SZ)
|
||||
return hres;
|
||||
|
||||
/* read the LocalService and ServiceParameters values from the AppID key */
|
||||
strcpyW(keyname, szAppIdKey);
|
||||
strcatW(keyname, buf);
|
||||
r = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &hkey);
|
||||
if (r!=ERROR_SUCCESS)
|
||||
return hres;
|
||||
sz = sizeof buf;
|
||||
r = RegQueryValueExW(hkey, szLocalService, NULL, &type, (LPBYTE)buf, &sz);
|
||||
if (r==ERROR_SUCCESS && type==REG_SZ)
|
||||
{
|
||||
DWORD num_args = 0;
|
||||
LPWSTR args[1] = { NULL };
|
||||
|
||||
/*
|
||||
* FIXME: I'm not really sure how to deal with the service parameters.
|
||||
* I suspect that the string returned from RegQueryValueExW
|
||||
* should be split into a number of arguments by spaces.
|
||||
* It would make more sense if ServiceParams contained a
|
||||
* REG_MULTI_SZ here, but it's a REG_SZ for the services
|
||||
* that I'm interested in for the moment.
|
||||
*/
|
||||
r = RegQueryValueExW(hkey, szServiceParams, NULL, &type, NULL, &sz);
|
||||
if (r == ERROR_SUCCESS && type == REG_SZ && sz)
|
||||
{
|
||||
args[0] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz);
|
||||
num_args++;
|
||||
RegQueryValueExW(hkey, szServiceParams, NULL, &type, (LPBYTE)args[0], &sz);
|
||||
}
|
||||
r = start_local_service(buf, num_args, args);
|
||||
if (r==ERROR_SUCCESS)
|
||||
hres = S_OK;
|
||||
HeapFree(GetProcessHeap(),0,args[0]);
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
|
||||
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) {
|
||||
HRESULT hres;
|
||||
|
@ -588,6 +698,8 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
|
|||
WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF));
|
||||
|
||||
while (tries++<MAXTRIES) {
|
||||
TRACE("waiting for %s\n", pipefn);
|
||||
|
||||
WaitNamedPipeA( pipefn, NMPWAIT_WAIT_FOREVER );
|
||||
hPipe = CreateFileA(
|
||||
pipefn,
|
||||
|
@ -600,7 +712,8 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
|
|||
);
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
if (tries == 1) {
|
||||
if ((hres = create_server(rclsid)))
|
||||
if ( (hres = create_server(rclsid)) &&
|
||||
(hres = create_local_service(rclsid)) )
|
||||
return hres;
|
||||
Sleep(1000);
|
||||
} else {
|
||||
|
@ -615,6 +728,7 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
|
|||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
TRACE("read marshal id from pipe\n");
|
||||
CloseHandle(hPipe);
|
||||
break;
|
||||
}
|
||||
|
@ -626,6 +740,7 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
|
|||
if (hres) goto out;
|
||||
seekto.u.LowPart = 0;seekto.u.HighPart = 0;
|
||||
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
|
||||
TRACE("unmarshalling classfactory\n");
|
||||
hres = CoUnmarshalInterface(pStm,&IID_IClassFactory,ppv);
|
||||
out:
|
||||
IStream_Release(pStm);
|
||||
|
@ -660,8 +775,7 @@ COM_RpcReceive(wine_pipe *xpipe) {
|
|||
|
||||
if (reqtype == REQTYPE_DISCONNECT) { /* only received by servers */
|
||||
wine_rpc_disconnect_header header;
|
||||
IRpcStubBuffer *stub;
|
||||
ULONG ret;
|
||||
struct stub_manager *stubmgr;
|
||||
|
||||
hres = read_pipe(xhPipe, &header, sizeof(header));
|
||||
if (hres) {
|
||||
|
@ -671,20 +785,16 @@ COM_RpcReceive(wine_pipe *xpipe) {
|
|||
|
||||
TRACE("read disconnect header\n");
|
||||
|
||||
hres = MARSHAL_Find_Stub_Buffer(&header.mid, &stub);
|
||||
if (hres) {
|
||||
ERR("could not locate stub to disconnect, mid.objectid=%p\n", (void*)header.mid.objectid);
|
||||
if (!(stubmgr = get_stub_manager(header.mid.oxid, header.mid.oid)))
|
||||
{
|
||||
ERR("could not locate stub to disconnect, mid.oid=%s\n", wine_dbgstr_longlong(header.mid.oid));
|
||||
goto end;
|
||||
}
|
||||
|
||||
stub_manager_ext_release(stubmgr, 1);
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
|
||||
/* release reference added by MARSHAL_Find_Stub_Buffer call */
|
||||
IRpcStubBuffer_Release(stub);
|
||||
/* release it for real */
|
||||
ret = IRpcStubBuffer_Release(stub);
|
||||
/* FIXME: race */
|
||||
if (ret == 0)
|
||||
MARSHAL_Invalidate_Stub_From_MID(&header.mid);
|
||||
goto end;
|
||||
} else if (reqtype == REQTYPE_REQUEST) {
|
||||
wine_rpc_request *xreq;
|
||||
|
@ -734,15 +844,21 @@ end:
|
|||
return hres;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
_StubReaderThread(LPVOID param) {
|
||||
/* This thread listens on the given pipe for requests to a particular stub manager */
|
||||
static DWORD WINAPI stub_dispatch_thread(LPVOID param)
|
||||
{
|
||||
wine_pipe *xpipe = (wine_pipe*)param;
|
||||
HANDLE xhPipe = xpipe->hPipe;
|
||||
HRESULT hres = S_OK;
|
||||
|
||||
TRACE("STUB reader thread %lx\n",GetCurrentProcessId());
|
||||
TRACE("starting for apartment OXID %08lx%08lx\n", (DWORD)(xpipe->mid.oxid >> 32), (DWORD)(xpipe->mid.oxid));
|
||||
|
||||
/* join marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */
|
||||
NtCurrentTeb()->ReservedForOle = xpipe->apt;
|
||||
|
||||
while (!hres) {
|
||||
int i;
|
||||
|
||||
hres = COM_RpcReceive(xpipe);
|
||||
if (hres) break;
|
||||
|
||||
|
@ -754,18 +870,41 @@ _StubReaderThread(LPVOID param) {
|
|||
}
|
||||
}
|
||||
}
|
||||
FIXME("Failed with hres %lx\n",hres);
|
||||
|
||||
/* fixme: this thread never quits naturally */
|
||||
WARN("exiting with hres %lx\n",hres);
|
||||
CloseHandle(xhPipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
_StubMgrThread(LPVOID param) {
|
||||
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;
|
||||
struct apartment_listener_params * params = (struct apartment_listener_params *)p;
|
||||
APARTMENT *apt = params->apt;
|
||||
HANDLE event = params->event;
|
||||
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx",GetCurrentProcessId());
|
||||
TRACE("Stub Manager Thread starting on (%s)\n",pipefn);
|
||||
HeapFree(GetProcessHeap(), 0, params);
|
||||
|
||||
/* we must join the marshalling threads apartment. we already have a ref here */
|
||||
NtCurrentTeb()->ReservedForOle = apt;
|
||||
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx%08lx", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid));
|
||||
TRACE("Apartment listener thread starting on (%s)\n",pipefn);
|
||||
|
||||
while (1) {
|
||||
listenPipe = CreateNamedPipeA(
|
||||
|
@ -778,28 +917,148 @@ _StubMgrThread(LPVOID param) {
|
|||
NMPWAIT_USE_DEFAULT_WAIT,
|
||||
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, le is %lx\n",pipefn,GetLastError());
|
||||
FIXME("pipe creation failed for %s, error %ld\n",pipefn,GetLastError());
|
||||
return 1; /* permanent failure, so quit stubmgr thread */
|
||||
}
|
||||
if (!ConnectNamedPipe(listenPipe,NULL)) {
|
||||
ERR("Failure during ConnectNamedPipe %lx!\n",GetLastError());
|
||||
|
||||
/* an already connected pipe is not an error */
|
||||
if (!ConnectNamedPipe(listenPipe,NULL) &&
|
||||
(GetLastError() != ERROR_PIPE_CONNECTED)) {
|
||||
ERR("Failure during ConnectNamedPipe %ld!\n",GetLastError());
|
||||
CloseHandle(listenPipe);
|
||||
continue;
|
||||
}
|
||||
|
||||
PIPE_StartRequestThread(listenPipe);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
STUBMGR_Start() {
|
||||
static BOOL stubMgrRunning = FALSE;
|
||||
DWORD tid;
|
||||
void start_apartment_listener_thread()
|
||||
{
|
||||
APARTMENT *apt = COM_CurrentApt();
|
||||
|
||||
if (!stubMgrRunning) {
|
||||
stubMgrRunning = TRUE;
|
||||
CreateThread(NULL,0,_StubMgrThread,NULL,0,&tid);
|
||||
Sleep(2000); /* actually we just try opening the pipe until it succeeds */
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
static DWORD WINAPI local_server_thread(LPVOID param)
|
||||
{
|
||||
struct local_server_params * lsp = (struct local_server_params *)param;
|
||||
HANDLE hPipe;
|
||||
char pipefn[200];
|
||||
HRESULT hres;
|
||||
IStream *pStm = lsp->stream;
|
||||
STATSTG ststg;
|
||||
unsigned char *buffer;
|
||||
int buflen;
|
||||
LARGE_INTEGER seekto;
|
||||
ULARGE_INTEGER newpos;
|
||||
ULONG res;
|
||||
|
||||
TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
|
||||
|
||||
strcpy(pipefn,PIPEPREF);
|
||||
WINE_StringFromCLSID(&lsp->clsid,pipefn+strlen(PIPEPREF));
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, lsp);
|
||||
|
||||
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 %ld\n",pipefn,GetLastError());
|
||||
return 1;
|
||||
}
|
||||
while (1) {
|
||||
if (!ConnectNamedPipe(hPipe,NULL)) {
|
||||
ERR("Failure during ConnectNamedPipe %ld, ABORT!\n",GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("marshalling IClassFactory to client\n");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void RPC_StartLocalServer(REFCLSID clsid, IStream *stream)
|
||||
{
|
||||
DWORD tid;
|
||||
HANDLE thread;
|
||||
struct local_server_params *lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
|
||||
|
||||
lsp->clsid = *clsid;
|
||||
lsp->stream = stream;
|
||||
|
||||
thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
|
||||
CloseHandle(thread);
|
||||
/* FIXME: failure handling */
|
||||
}
|
||||
|
|
|
@ -423,6 +423,7 @@ void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize)
|
|||
if (This->fileBased)
|
||||
{
|
||||
char buf[10];
|
||||
DWORD w;
|
||||
|
||||
/*
|
||||
* close file-mapping object, must be done before call to SetEndFile
|
||||
|
@ -445,7 +446,7 @@ void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize)
|
|||
*/
|
||||
memset(buf, '0', 10);
|
||||
SetFilePointer(This->hfile, newSize.u.LowPart, NULL, FILE_BEGIN);
|
||||
WriteFile(This->hfile, buf, 10, NULL, NULL);
|
||||
WriteFile(This->hfile, buf, 10, &w, NULL);
|
||||
/*
|
||||
* END HACK
|
||||
*/
|
||||
|
|
|
@ -447,6 +447,9 @@ HRESULT WINAPI StgStreamImpl_Write(
|
|||
return STG_E_ACCESSDENIED;
|
||||
}
|
||||
|
||||
if (!pv)
|
||||
return STG_E_INVALIDPOINTER;
|
||||
|
||||
/*
|
||||
* If the caller is not interested in the number of bytes written,
|
||||
* we use another buffer to avoid "if" statements in the code.
|
||||
|
|
|
@ -51,6 +51,7 @@ 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
|
||||
|
@ -872,18 +873,23 @@ HRESULT WINAPI StorageBaseImpl_CreateStream(
|
|||
if (pwcsName == 0)
|
||||
return STG_E_INVALIDNAME;
|
||||
|
||||
if (reserved1 || reserved2)
|
||||
return STG_E_INVALIDPARAMETER;
|
||||
|
||||
/*
|
||||
* Validate the STGM flags
|
||||
*/
|
||||
if ( FAILED( validateSTGM(grfMode) ))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) )
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
/*
|
||||
* As documented.
|
||||
*/
|
||||
if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ||
|
||||
(grfMode & STGM_DELETEONRELEASE) ||
|
||||
(grfMode & STGM_TRANSACTED) )
|
||||
if ((grfMode & STGM_DELETEONRELEASE) ||
|
||||
(grfMode & STGM_TRANSACTED))
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
|
||||
/*
|
||||
|
@ -1680,7 +1686,7 @@ HRESULT WINAPI StorageImpl_DestroyElement(
|
|||
This->rootPropertySetIndex,
|
||||
&parentProperty);
|
||||
|
||||
assert(res==TRUE);
|
||||
assert(res);
|
||||
|
||||
/*
|
||||
* Second, check to see if by any chance the actual storage (This) is not
|
||||
|
@ -2395,8 +2401,7 @@ void StorageImpl_Destroy(
|
|||
{
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
if(This->pwcsName)
|
||||
HeapFree(GetProcessHeap(), 0, This->pwcsName);
|
||||
HeapFree(GetProcessHeap(), 0, This->pwcsName);
|
||||
|
||||
BlockChainStream_Destroy(This->smallBlockRootChain);
|
||||
BlockChainStream_Destroy(This->rootBlockChain);
|
||||
|
@ -5426,6 +5431,8 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
*/
|
||||
if (ppstgOpen == 0)
|
||||
return STG_E_INVALIDPOINTER;
|
||||
if (reserved != 0)
|
||||
return STG_E_INVALIDPARAMETER;
|
||||
|
||||
/*
|
||||
* Validate the STGM flags
|
||||
|
@ -5433,6 +5440,14 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
if ( FAILED( validateSTGM(grfMode) ))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
/* StgCreateDocFile always opens for write */
|
||||
if (!(grfMode & (STGM_WRITE|STGM_READWRITE)))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
/* always opens non-shared */
|
||||
if (!(grfMode & STGM_SHARE_EXCLUSIVE))
|
||||
return STG_E_INVALIDFLAG;
|
||||
|
||||
/*
|
||||
* Generate a unique name.
|
||||
*/
|
||||
|
@ -5493,6 +5508,8 @@ HRESULT WINAPI StgCreateDocfile(
|
|||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if(GetLastError() == ERROR_FILE_EXISTS)
|
||||
return STG_E_FILEALREADYEXISTS;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
@ -5564,18 +5581,44 @@ HRESULT WINAPI StgOpenStorage(
|
|||
snbExclude, reserved, ppstgOpen);
|
||||
|
||||
/*
|
||||
* Perform a sanity check
|
||||
* Perform sanity checks
|
||||
*/
|
||||
if (( pwcsName == 0) || (ppstgOpen == 0) )
|
||||
if (pwcsName == 0)
|
||||
{
|
||||
hr = STG_E_INVALIDNAME;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ppstgOpen == 0)
|
||||
{
|
||||
hr = STG_E_INVALIDPOINTER;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (reserved)
|
||||
{
|
||||
hr = STG_E_INVALIDPARAMETER;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the sharing mode
|
||||
*/
|
||||
switch(STGM_SHARE_MODE(grfMode))
|
||||
{
|
||||
case STGM_SHARE_EXCLUSIVE:
|
||||
case STGM_SHARE_DENY_WRITE:
|
||||
break;
|
||||
default:
|
||||
hr = STG_E_INVALIDFLAG;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the STGM flags
|
||||
*/
|
||||
if ( FAILED( validateSTGM(grfMode) ))
|
||||
if ( FAILED( validateSTGM(grfMode) ) ||
|
||||
(grfMode&STGM_CREATE))
|
||||
{
|
||||
hr = STG_E_INVALIDFLAG;
|
||||
goto end;
|
||||
|
@ -5600,8 +5643,6 @@ HRESULT WINAPI StgOpenStorage(
|
|||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
||||
0);
|
||||
|
||||
length = GetFileSize(hFile, NULL);
|
||||
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD last_error = GetLastError();
|
||||
|
@ -5634,6 +5675,8 @@ HRESULT WINAPI StgOpenStorage(
|
|||
goto end;
|
||||
}
|
||||
|
||||
length = GetFileSize(hFile, NULL);
|
||||
|
||||
/*
|
||||
* Allocate and initialize the new IStorage32object.
|
||||
*/
|
||||
|
@ -7355,15 +7398,9 @@ HRESULT WINAPI OleConvertOLESTREAMToIStorage (
|
|||
/* Free allocated memory */
|
||||
for(i=0; i < 2; i++)
|
||||
{
|
||||
if(pOleStreamData[i].pData != NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
|
||||
}
|
||||
if(pOleStreamData[i].pstrOleObjFileName != NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName);
|
||||
pOleStreamData[i].pstrOleObjFileName = NULL;
|
||||
}
|
||||
HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
|
||||
HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName);
|
||||
pOleStreamData[i].pstrOleObjFileName = NULL;
|
||||
}
|
||||
return hRes;
|
||||
}
|
||||
|
@ -7432,10 +7469,7 @@ HRESULT WINAPI OleConvertIStorageToOLESTREAM (
|
|||
/* Free allocated memory */
|
||||
for(i=0; i < 2; i++)
|
||||
{
|
||||
if(pOleStreamData[i].pData != NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
|
||||
}
|
||||
HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData);
|
||||
}
|
||||
|
||||
return hRes;
|
||||
|
|
Loading…
Reference in a new issue