Sync to Wine-20050211
Jonathan Ernst <Jonathan(a)ErnstFamily.ch>
- Updated French resources.
Added: trunk/reactos/lib/oledlg/oledlg_Fr.rc
Modified: trunk/reactos/lib/oledlg/rsrc.rc
_____
Copied: trunk/reactos/lib/oledlg/oledlg_Fr.rc (from rev 13533,
vendor/wine/dlls/oledlg/current/oledlg_Fr.rc)
--- vendor/wine/dlls/oledlg/current/oledlg_Fr.rc 2005-02-13
21:03:37 UTC (rev 13533)
+++ trunk/reactos/lib/oledlg/oledlg_Fr.rc 2005-02-13 21:06:18 UTC
(rev 13534)
@@ -0,0 +1,59 @@
+/*
+ * oledlg dll resources
+ * French language support
+ *
+ * Copyright (C) 2005 Jonathan Ernst
+ *
+ * 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
+ */
+
+
+LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT
+
+UIINSERTOBJECT DIALOG DISCARDABLE 0, 0, 294, 151
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "InsÚrer Objet"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LISTBOX IDC_OBJTYPELIST,82,19,131,66,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VISIBLE | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Type d'objet:",IDC_OBJTYPELBL,82,7,53,8,WS_VISIBLE
+ DEFPUSHBUTTON "OK",IDOK,221,7,66,14
+ PUSHBUTTON "Annuler",IDCANCEL,221,24,66,14
+ GROUPBOX "RÚsultat",IDC_RESULT,7,103,208,41
+ CONTROL "CrÚer
Nouveau",IDC_CREATENEW,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP,7,20,62,10
+ CONTROL "CrÚer Contr¶le",IDC_CREATECONTROL,"Button",
+ BS_AUTORADIOBUTTON | NOT WS_VISIBLE,7,54,62,10
+ CONTROL "CrÚer Depuis Fichier",IDC_CREATEFROMFILE,"Button",
+ BS_AUTORADIOBUTTON,7,37,67,10
+ LTEXT "",IDC_RESULTDESC,49,112,159,23
+ PUSHBUTTON "&Ajoute
Contr¶le...",IDC_ADDCONTROL,81,88,63,14,NOT WS_VISIBLE
+ CONTROL "Afficher Comme
Ic¶ne",IDC_ASICON,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP | NOT WS_VISIBLE,223,58,64,10
+ PUSHBUTTON "Parcourir...",IDC_BROWSE,83,53,50,14,NOT
WS_VISIBLE
+ LTEXT "Fichier:",IDC_FILELBL,83,27,20,8, NOT WS_VISIBLE
+ EDITTEXT IDC_FILE,83,37,132,13,ES_AUTOHSCROLL | NOT
WS_VISIBLE
+END
+
+STRINGTABLE DISCARDABLE
+{
+ IDS_RESULTOBJDESC "InsÚrer un nouvel object %s dans votre
document"
+ IDS_RESULTFILEOBJDESC "InsÞre le contenu du fichier comme un
objet dans votre document afin que vous puissiez l'activer en utilisant
le programme avec lequel vous l'avez crÚÚ."
+ IDS_BROWSE "Parcourir"
+ IDS_NOTOLEMOD "Le fichier ne semble pas Ûtre un module OLE
valide. Impossible d'enregistrer le contr¶le OLE."
+ IDS_NOTOLEMODCAPTION "Ajouter Contr¶le"
+}
Property changes on: trunk/reactos/lib/oledlg/oledlg_Fr.rc
___________________________________________________________________
Name: svn:eol-style
+ native
_____
Modified: trunk/reactos/lib/oledlg/rsrc.rc
--- trunk/reactos/lib/oledlg/rsrc.rc 2005-02-13 21:03:37 UTC (rev
13533)
+++ trunk/reactos/lib/oledlg/rsrc.rc 2005-02-13 21:06:18 UTC (rev
13534)
@@ -35,6 +35,7 @@
#include "oledlg_De.rc"
#include "oledlg_En.rc"
#include "oledlg_Es.rc"
+#include "oledlg_Fr.rc"
#include "oledlg_It.rc"
#include "oledlg_Ja.rc"
#include "oledlg_Nl.rc"
Sync to Wine-20050211
Robert Shearman <rob(a)codeweavers.com>
- Add documentation for most Co* functions.
- Move several functions into different files to group them with
similar functions.
- Implement CoDisconnectObject.
- Change CoLockObjectExternal so that it does the correct action now
and eliminate a fair few lines of now redundant code.
- Rename OLE32_Dll{Register,Unregister}Server to
Dll{Register,Unregister}Server.
- Move OLE automation interface registration to oleaut32.
- Add IRemUnknown to list of interfaces to register.
- Make proxy manager use IMultiQI instead of IInternalUnknown as tests
show that IInternalUnknown isn't exposed.
- Implement IMultiQI on top of IRemUnknown calls.
- Silence some fixmes that occur during tests and don't give us any
useful information.
- Fix typo in class factory proxy that caused us to use the wrong
offset into the CFProxy structure, causing us to not call the
outer_unknown properly.
- Use InterlockedIncrement for the ipid counter instead of a critical
section (suggested by Mike Hearn).
- Remove a line added by a bad merge.
- Implement RemUnkStub_Disconnect.
- Remove all of the RPC disconnect code.
- Implement IRemUnknown.
- Use IRemUnknown for life-cycle management instead of the current
hacks.
- Generate machine-local IPIDs.
- Make pipes be uniquely identified only by their IPID.
- Implement table marshaling.
- The apartment reference should be held while the stub manager
reference is held.
- Fix same apartment-unmarshal detection.
- Proxies/stubs for IRemUnknown methods, based on code written by Ove
Ksven.
- Initialize ppv pointer in ClientIdentity_QueryInterface to NULL as
apps depend on this.
- Don't release IRpcProxyBuffer on ifproxy destruction - the caller
will do this for us.
- Make find_proxy_manager add a reference to the proxy manager and
make proxy_manager_construct return an object with a valid
ref-count.
- Remove stray not operator to fix a memory leak / crash in
proxy_manager_destroy.
- More debug messages, especially on errors.
- Fix ref-count leak in the Class Factory proxy.
- Add a test case for IClassFactory_CreateInstance.
- Split up apartment creation so that the long code paths that don't
need locking no longer have locking.
- Add special cases for the threads that join apartments but can't
increase the refcount of the apartment.
- Free TLS storage on thread destruction (including releasing the
apartment the thread is in, if any, and so making another test
pass).
- More tests.
- Change return code of CoGetPSClsid to match test result.
- Do a slight hack to make IRemUnknown proxies be added after the
proxy that uses them to stop them being used after they are
destroyed.
- Fix multiple local server connections.
- The apartment reference should be held while the stub manager
reference is held.
- Fix same apartment-unmarshal detection.
- Don't use the pipe caching code because it doesn't work correctly at
the moment.
- Always write disconnect reply packet, even in failure cases.
- Move object-to-stub-manager mapping rule to register_ifstub.
- Pass the original IID to IMarshal_UnmarshalInterface and query for
the requested interface.
- Unmarshaling IID_NULL means use the IID the interface was originally
marshaled with.
- Add code for destroying the thread-local storage data, but don't use
it yet.
- Don't release apartment on changing modes because we didn't add a
reference anywhere.
- Quieten the RPC_E_DISCONNECTED error message as it is an expected
return code.
- Treat IID_NULL the same as IID_IUnknown.
- Make tests compile on Win95 again.
- Fix copy+paste error where the test failure should be from the
CoUnmarshalInterface function.
- Give IUnknown its own ifstub to fix ref-counting and ipid storage
issues.
- Add a new flag SORFP_NOLIFETIMEMGMT to tell the proxy manager not to
call any IRemUnknown functions.
- Move the low-level unmarshaling code into a new function,
unmarshal_object, so that it can be easily reused for unmarshaling
IRemUnknown.
- Consolidate more stub creation details into register_ifstub.
- Replace the current wine_marshal_id structure with STDOBJREF for the
on-the-wire format.
- Initialize clsid member to the marshaler clsid to fix custom
marshaling.
- Make proxy shutdown test succeed by releasing the channel on
disconnect.
- Remove wine_marshal_data: it is unneeded and there is no equivalent in
STDOBJREF.
- Remove obsolete structs, rearrange things to group the structs
together and to group similar functions.
- Document thread-safety of members of structs.
- Document CoSetState & CoGetState.
- Rewrite them to only retrieve TLS info once.
- Remove trailing whitespace in COM_CurrentInfo.
- Release the client security objects when no longer needed (reported by
Mike McCormack).
- Implement CoSetProxyBlanket, CoQueryProxyBlanket and CoCopyProxy.
- Update todo list.
- Destroy stubs on apartment shutdown.
- Make MTA dynamically allocated so that proxies and other resources
are freed at the proper time.
- Changed/removed some incorrect comments regarding apartments.
Mike Hearn <mh(a)codeweavers.com>
- Various formatting/style changes.
- Force context switch on chanbuf disconnect to avoid a race in the test
suite.
Mike Hearn <mh(a)codeweavers.com>
Robert Shearman <rob(a)codeweavers.com>
- Rework RPC dispatch layer to be simpler and not get confused by
server/client duality.
- Make threads shut down at the right time and not access freed memory
after apartment destruction.
- Rename stub_dispatch_thread to client_dispatch_thread.
- Add some more tracing
- Check return value of WaitNamedPipe.
- Change named pipe timeouts to 0.5s, which should be enough for even
the
slowest machines.
Christian Costa <titan.costa(a)wanadoo.fr>
- CoInitialize(Ex) should return S_FALSE when COM is already initialized
for the current thread.
Modified: trunk/reactos/include/wine/list.h
Modified: trunk/reactos/include/wine/objidl.h
Modified: trunk/reactos/lib/ole32/compobj.c
Modified: trunk/reactos/lib/ole32/compobj_private.h
Modified: trunk/reactos/lib/ole32/ifs.c
Modified: trunk/reactos/lib/ole32/marshal.c
Modified: trunk/reactos/lib/ole32/ole2.c
Modified: trunk/reactos/lib/ole32/ole2stubs.c
Modified: trunk/reactos/lib/ole32/ole32.spec
Modified: trunk/reactos/lib/ole32/ole32_main.c
Modified: trunk/reactos/lib/ole32/ole32_main.h
Modified: trunk/reactos/lib/ole32/oleproxy.c
Modified: trunk/reactos/lib/ole32/regsvr.c
Modified: trunk/reactos/lib/ole32/rpc.c
Modified: trunk/reactos/lib/ole32/stubmanager.c
Modified: trunk/reactos/w32api/include/winerror.h
Modified: trunk/reactos/w32api/include/wtypes.h
_____
Modified: trunk/reactos/include/wine/list.h
--- trunk/reactos/include/wine/list.h 2005-02-13 17:25:52 UTC (rev
13531)
+++ trunk/reactos/include/wine/list.h 2005-02-13 20:52:16 UTC (rev
13532)
@@ -143,6 +143,18 @@
#define LIST_FOR_EACH(cursor,list) \
for ((cursor) = (list)->next; (cursor) != (list); (cursor) =
(cursor)->next)
+/* iterate through the list, with safety against removal */
+#define LIST_FOR_EACH_SAFE(cursor, cursor2, list) \
+ for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \
+ (cursor) != (list); \
+ (cursor) = (cursor2), (cursor2) = (cursor)->next)
+
+/* iterate through the list using a list entry */
+#define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
+ for ((elem) = LIST_ENTRY((list)->next, type, field); \
+ &(elem)->field != (list); \
+ (elem) = LIST_ENTRY((elem)->field.next, type, field))
+
/* macros for statically initialized lists */
#define LIST_INIT(list) { &(list), &(list) }
_____
Modified: trunk/reactos/include/wine/objidl.h
--- trunk/reactos/include/wine/objidl.h 2005-02-13 17:25:52 UTC (rev
13531)
+++ trunk/reactos/include/wine/objidl.h 2005-02-13 20:52:16 UTC (rev
13532)
@@ -984,6 +984,17 @@
};
#undef INTERFACE
+#ifdef COBJMACROS
+/*** IUnknown methods ***/
+#define IClientSecurity_QueryInterface(p,a,b)
(p)->lpVtbl->QueryInterface(p,a,b)
+#define IClientSecurity_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IClientSecurity_Release(p) (p)->lpVtbl->Release(p)
+/*** IClientSecurity methods ***/
+#define IClientSecurity_QueryBlanket(p,a,b,c,d,e,f,g,h)
(p)->lpVtbl->QueryBlanket(p,a,b,c,d,e,f,g,h)
+#define IClientSecurity_SetBlanket(p,a,b,c,d,e,f,g,h)
(p)->lpVtbl->SetBlanket(p,a,b,c,d,e,f,g,h)
+#define IClientSecurity_CopyProxy(p,a,b) (p)->lpVtbl->CopyProxy(p,a,b)
+#endif
+
EXTERN_C const IID IID_IServerSecurity;
#define INTERFACE IServerSecurity
DECLARE_INTERFACE_(IServerSecurity,IUnknown)
@@ -2005,5 +2016,78 @@
#endif /* __IInternalUnknown_INTERFACE_DEFINED__ */
+#ifndef __IMultiQI_FWD_DEFINED__
+#define __IMultiQI_FWD_DEFINED__
+typedef struct IMultiQI IMultiQI;
+#endif
+typedef IMultiQI *LPMULTIQI;
+
+/**********************************************************************
*******
+ * IMultiQI interface
+ */
+#ifndef __IMultiQI_INTERFACE_DEFINED__
+#define __IMultiQI_INTERFACE_DEFINED__
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+struct IMultiQI : public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE QueryMultipleInterfaces(
+ ULONG cMQIs,
+ MULTI_QI* pMQIs) = 0;
+
+};
+#else
+typedef struct IMultiQIVtbl IMultiQIVtbl;
+struct IMultiQI {
+ const IMultiQIVtbl* lpVtbl;
+};
+struct IMultiQIVtbl {
+ BEGIN_INTERFACE
+
+ /*** IUnknown methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(
+ IMultiQI* This,
+ REFIID riid,
+ void** ppvObject);
+
+ ULONG (STDMETHODCALLTYPE *AddRef)(
+ IMultiQI* This);
+
+ ULONG (STDMETHODCALLTYPE *Release)(
+ IMultiQI* This);
+
+ /*** IMultiQI methods ***/
+ HRESULT (STDMETHODCALLTYPE *QueryMultipleInterfaces)(
+ IMultiQI* This,
+ ULONG cMQIs,
+ MULTI_QI* pMQIs);
+
+ END_INTERFACE
+};
+
+#ifdef COBJMACROS
+/*** IUnknown methods ***/
+#define IMultiQI_QueryInterface(p,a,b)
(p)->lpVtbl->QueryInterface(p,a,b)
+#define IMultiQI_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IMultiQI_Release(p) (p)->lpVtbl->Release(p)
+/*** IMultiQI methods ***/
+#define IMultiQI_QueryMultipleInterfaces(p,a,b)
(p)->lpVtbl->QueryMultipleInterfaces(p,a,b)
+#endif
+
+#endif
+
+HRESULT CALLBACK IMultiQI_QueryMultipleInterfaces_Proxy(
+ IMultiQI* This,
+ ULONG cMQIs,
+ MULTI_QI* pMQIs);
+void __RPC_STUB IMultiQI_QueryMultipleInterfaces_Stub(
+ struct IRpcStubBuffer* This,
+ struct IRpcChannelBuffer* pRpcChannelBuffer,
+ PRPC_MESSAGE pRpcMessage,
+ DWORD* pdwStubPhase);
+
+#endif /* __IMultiQI_INTERFACE_DEFINED__ */
+
+
#endif /* __WINE_OBJIDL_H */
_____
Modified: trunk/reactos/lib/ole32/compobj.c
--- trunk/reactos/lib/ole32/compobj.c 2005-02-13 17:25:52 UTC (rev
13531)
+++ trunk/reactos/lib/ole32/compobj.c 2005-02-13 20:52:16 UTC (rev
13532)
@@ -28,37 +28,19 @@
*
* 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 all ole interface marshaling use NDR to be wire compatible
with
+ * native DCOM
+ * - Use & interpret ORPCTHIS & ORPCTHAT.
*
- * - Make our custom marshalling use NDR to be wire compatible with
- * native DCOM
- *
- *
*/
#include "config.h"
@@ -102,12 +84,11 @@
static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD
dwClsContext, LPUNKNOWN* ppUnk);
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;
-static struct list apts = LIST_INIT( apts );
+APARTMENT *MTA; /* protected by csApartment */
+static struct list apts = LIST_INIT( apts ); /* protected by
csApartment */
static CRITICAL_SECTION csApartment;
static CRITICAL_SECTION_DEBUG critsect_debug =
@@ -213,89 +194,108 @@
UnregisterClassA(aptWinClass, OLE32_hInstance);
}
+void COM_TlsDestroy()
+{
+ struct oletls *info = NtCurrentTeb()->ReservedForOle;
+ if (info)
+ {
+ if (info->apt) COM_ApartmentRelease(info->apt);
+ if (info->errorinfo) IErrorInfo_Release(info->errorinfo);
+ if (info->state) IUnknown_Release(info->state);
+ HeapFree(GetProcessHeap(), 0, info);
+ NtCurrentTeb()->ReservedForOle = NULL;
+ }
+}
+
/***********************************************************************
*******
* Manage apartments.
*/
-
-/* The multi-threaded apartment (MTA) contains zero or more threads
interacting
- with free threaded (ie thread safe) COM objects. There is only ever
one MTA
- in a process - you can enter it by calling
CoInitializeEx(COINIT_MULTITHREADED)
- */
-static void COM_InitMTA(void)
+/* allocates memory and fills in the necessary fields for a new
apartment
+ * object */
+static APARTMENT *apartment_construct(DWORD model)
{
- /* OXIDs are object exporter IDs. Each apartment has an OXID, which
is unique
- within a network. That is, two different MTAs on different
machines will have
- different OXIDs.
+ APARTMENT *apt;
- This method of generating an OXID is therefore wrong as it
doesn't work across
- a network, but for local RPC only it's OK. We can distinguish
between MTAs and
- STAs because STAs use the thread ID as well, and no thread can
have an ID of zero.
+ TRACE("creating new apartment, model=%ld\n", model);
- The algorithm Microsoft use is currently unknown.
- */
- MTA.oxid = ((OXID)GetCurrentProcessId() << 32);
- InitializeCriticalSection(&MTA.cs);
-}
+ apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*apt));
+ apt->tid = GetCurrentThreadId();
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+ GetCurrentProcess(), &apt->thread,
+ THREAD_ALL_ACCESS, FALSE, 0);
-static void COM_UninitMTA(void)
-{
- DeleteCriticalSection(&MTA.cs);
- MTA.oxid = 0;
+ list_init(&apt->proxies);
+ list_init(&apt->stubmgrs);
+ apt->ipidc = 0;
+ apt->refs = 1;
+ apt->remunk_exported = FALSE;
+ apt->oidc = 1;
+ InitializeCriticalSection(&apt->cs);
+
+ apt->model = model;
+
+ if (model & COINIT_APARTMENTTHREADED)
+ {
+ /* FIXME: should be randomly generated by in an RPC call to
rpcss */
+ apt->oxid = ((OXID)GetCurrentProcessId() << 32) |
GetCurrentThreadId();
+ apt->win = CreateWindowA(aptWinClass, NULL, 0,
+ 0, 0, 0, 0,
+ 0, 0, OLE32_hInstance, NULL);
+ }
+ else
+ {
+ /* FIXME: should be randomly generated by in an RPC call to
rpcss */
+ apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe;
+ }
+
+ apt->shutdown_event = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+ TRACE("Created apartment on OXID %s\n",
wine_dbgstr_longlong(apt->oxid));
+
+ /* the locking here is not currently needed for the MTA case, but
it
+ * doesn't hurt and makes the code simpler */
+ EnterCriticalSection(&csApartment);
+ list_add_head(&apts, &apt->entry);
+ LeaveCriticalSection(&csApartment);
+
+ return apt;
}
-
-/* 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
- * with COINIT_UNINITIALIZED if the apartment has already been
initialized
- * with a different COINIT value */
-APARTMENT* COM_CreateApartment(DWORD model)
+/* gets and existing apartment if one exists or otherwise creates an
apartment
+ * structure which stores OLE apartment-local information and stores a
pointer
+ * to it in the thread-local storage */
+static APARTMENT *get_or_create_apartment(DWORD model)
{
APARTMENT *apt = COM_CurrentApt();
if (!apt)
{
- if (!(model & COINIT_APARTMENTTHREADED)) /* See note 1 above */
+ if (model & COINIT_APARTMENTTHREADED)
{
- TRACE("thread 0x%lx is entering the multithreaded
apartment\n", GetCurrentThreadId());
- COM_CurrentInfo()->apt = &MTA;
- return COM_CurrentInfo()->apt;
+ apt = apartment_construct(model);
+ COM_CurrentInfo()->apt = apt;
}
+ else
+ {
+ EnterCriticalSection(&csApartment);
- TRACE("creating new apartment, model=%ld\n", model);
+ /* The multi-threaded apartment (MTA) contains zero or more
threads interacting
+ * with free threaded (ie thread safe) COM objects. There
is only ever one MTA
+ * in a process */
+ if (MTA)
+ {
+ TRACE("entering the multithreaded apartment %s\n",
wine_dbgstr_longlong(MTA->oxid));
+ COM_ApartmentAddRef(MTA);
+ }
+ else
+ MTA = apartment_construct(model);
- apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(APARTMENT));
- apt->tid = GetCurrentThreadId();
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
- GetCurrentProcess(), &apt->thread,
- THREAD_ALL_ACCESS, FALSE, 0);
+ apt = MTA;
+ COM_CurrentInfo()->apt = apt;
- 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);
+ LeaveCriticalSection(&csApartment);
}
-
- EnterCriticalSection(&csApartment);
- list_add_head(&apts, &apt->entry);
- LeaveCriticalSection(&csApartment);
-
- COM_CurrentInfo()->apt = apt;
}
return apt;
@@ -303,39 +303,61 @@
DWORD COM_ApartmentAddRef(struct apartment *apt)
{
- return InterlockedIncrement(&apt->refs);
+ DWORD refs = InterlockedIncrement(&apt->refs);
+ TRACE("%s: before = %ld\n", wine_dbgstr_longlong(apt->oxid), refs -
1);
+ return refs;
}
DWORD COM_ApartmentRelease(struct apartment *apt)
{
DWORD ret;
+ EnterCriticalSection(&csApartment);
+
ret = InterlockedDecrement(&apt->refs);
+ TRACE("%s: after = %ld\n", wine_dbgstr_longlong(apt->oxid), ret);
+ /* destruction stuff that needs to happen under csApartment CS */
if (ret == 0)
{
+ if (apt == MTA) MTA = NULL;
+ list_remove(&apt->entry);
+ }
+
+ LeaveCriticalSection(&csApartment);
+
+ if (ret == 0)
+ {
+ struct list *cursor, *cursor2;
+
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))
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &apt->stubmgrs)
{
- FIXME("Destroy outstanding stubs\n");
+ struct stub_manager *stubmgr = LIST_ENTRY(cursor, struct
stub_manager, entry);
+ /* release the implicit reference given by the fact that
the
+ * stub has external references (it must do since it is in
the
+ * stub manager list in the apartment and all non-apartment
users
+ * must have a ref on the apartment and so it cannot be
destroyed).
+ */
+ stub_manager_int_release(stubmgr);
}
+ /* if this assert fires, then another thread took a reference
to a
+ * stub manager without taking a reference to the containing
+ * apartment, which it must do. */
+ assert(list_empty(&apt->stubmgrs));
+
if (apt->filter) IUnknown_Release(apt->filter);
-
DeleteCriticalSection(&apt->cs);
+ SetEvent(apt->shutdown_event);
+ CloseHandle(apt->shutdown_event);
CloseHandle(apt->thread);
HeapFree(GetProcessHeap(), 0, apt);
-
- apt = NULL;
}
return ret;
@@ -369,6 +391,30 @@
return result;
}
+/* gets the apartment which has a given creator thread ID. The caller
must
+ * release the reference from the apartment as soon as the apartment
pointer
+ * is no longer required. */
+APARTMENT *COM_ApartmentFromTID(DWORD tid)
+{
+ APARTMENT *result = NULL;
+ struct list *cursor;
+
+ EnterCriticalSection(&csApartment);
+ LIST_FOR_EACH( cursor, &apts )
+ {
+ struct apartment *apt = LIST_ENTRY( cursor, struct apartment,
entry );
+ if (apt->tid == tid)
+ {
+ result = apt;
+ COM_ApartmentAddRef(result);
+ break;
+ }
+ }
+ LeaveCriticalSection(&csApartment);
+
+ return result;
+}
+
HWND COM_GetApartmentWin(OXID oxid, BOOL ref)
{
APARTMENT *apt;
@@ -461,9 +507,13 @@
}
/***********************************************************************
*******
+ * CoBuildVersion [OLE32.@]
* CoBuildVersion [COMPOBJ.1]
- * CoBuildVersion [OLE32.@]
*
+ * Gets the build version of the DLL.
+ *
+ * PARAMS
+ *
* RETURNS
* Current build version, hiword is majornumber, loword is
minornumber
*/
@@ -479,13 +529,17 @@
* Initializes the COM libraries by calling CoInitializeEx with
* COINIT_APARTMENTTHREADED, ie it enters a STA thread.
*
+ * PARAMS
+ * lpReserved [I] Pointer to IMalloc interface (obsolete, should be
NULL).
+ *
+ * RETURNS
+ * Success: S_OK if not already initialized, S_FALSE otherwise.
+ * Failure: HRESULT code.
+ *
* SEE ALSO
* CoInitializeEx
*/
-HRESULT WINAPI CoInitialize(
- LPVOID lpReserved /* [in] pointer to win32 malloc
interface
- (obsolete, should be NULL) */
-)
+HRESULT WINAPI CoInitialize(LPVOID lpReserved)
{
/*
* Just delegate to the newer method.
@@ -496,13 +550,11 @@
/***********************************************************************
*******
* CoInitializeEx [OLE32.@]
*
- * Initializes the COM libraries. The behavior used to set the win32
- * IMalloc used for memory management is obsolete. If
- * COINIT_APARTMENTTHREADED is specified this thread enters a new STA
- * (single threaded apartment), otherwise COINIT_MULTITHREADED should
- * be specified which indicates that the thread will enter the MTA.
+ * Initializes the COM libraries.
*
- * Currently STA threading is only partly implemented.
+ * PARAMS
+ * lpReserved [I] Pointer to IMalloc interface (obsolete, should be
NULL).
+ * dwCoInit [I] One or more flags from the COINIT enumeration. See
notes.
*
* RETURNS
* S_OK if successful,
@@ -510,13 +562,22 @@
* RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified
another
* threading model.
*
+ * NOTES
+ *
+ * The behavior used to set the IMalloc used for memory management is
+ * obsolete.
+ * The dwCoInit parameter must specify of of the following apartment
+ * threading models:
+ *| COINIT_APARTMENTTHREADED - A single-threaded apartment (STA).
+ *| COINIT_MULTITHREADED - A multi-threaded apartment (MTA).
+ * The parameter may also specify zero or more of the following flags:
+ *| COINIT_DISABLE_OLE1DDE - Don't use DDE for OLE1 support.
+ *| COINIT_SPEED_OVER_MEMORY - Trade memory for speed.
+ *
* SEE ALSO
* CoUninitialize
*/
-HRESULT WINAPI CoInitializeEx(
- LPVOID lpReserved, /* [in] pointer to win32 malloc
interface (obsolete, should be NULL) */
- DWORD dwCoInit /* [in] A value from COINIT specifies
the threading model */
-)
+HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
{
HRESULT hr = S_OK;
APARTMENT *apt;
@@ -541,15 +602,13 @@
*/
TRACE("() - Initializing the COM libraries\n");
- COM_InitMTA();
-
/* we may need to defer this until after apartment initialisation
*/
RunningObjectTableImpl_Initialize();
}
if (!(apt = COM_CurrentInfo()->apt))
{
- apt = COM_CreateApartment(dwCoInit);
+ apt = get_or_create_apartment(dwCoInit);
if (!apt) return E_OUTOFMEMORY;
}
else if (dwCoInit != apt->model)
@@ -557,9 +616,10 @@
/* 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;
}
+ else
+ hr = S_FALSE;
COM_CurrentInfo()->inits++;
@@ -594,16 +654,16 @@
/***********************************************************************
* CoUninitialize [OLE32.@]
*
- * This method will decrement the refcount on the COM libraries,
- * potentially unloading them. The current thread leaves the apartment
- * it's currently in. If not in an apartment, the routine does
- * nothing.
+ * This method will decrement the refcount on the current apartment,
freeing
+ * the resources associated with it if it is the last thread in the
apartment.
+ * If the last apartment is freed, the function will additionally
release
+ * any COM resources associated with the process.
*
- * If COM is to be shut down, any outstanding proxies are
- * disconnected, all registered class objects are unregistered and the
- * message queue for the thread is flushed (if native does
- * this or not is unknown).
+ * PARAMS
*
+ * RETURNS
+ * Nothing.
+ *
* SEE ALSO
* CoInitializeEx
*/
@@ -648,13 +708,8 @@
/* This will free the loaded COM Dlls */
CoFreeAllLibraries();
- /* This will free list of external references to COM objects */
- COM_ExternalLockFreeList();
-
/* This ensures we deal with any pending RPCs */
COM_FlushMessageQueue();
-
- COM_UninitMTA();
}
else if (lCOMRefCnt<1) {
ERR( "CoUninitialize() - not CoInitialized.\n" );
@@ -663,8 +718,8 @@
}
/***********************************************************************
*******
+ * CoDisconnectObject [OLE32.@]
* CoDisconnectObject [COMPOBJ.15]
- * CoDisconnectObject [OLE32.@]
*
* Disconnects all connections to this object from remote processes.
Dispatches
* pending RPCs while blocking new RPCs from occurring, and then calls
@@ -672,25 +727,65 @@
*
* Typically called when the object server is forced to shut down, for
instance by
* the user.
+ *
+ * PARAMS
+ * lpUnk [I] The object whose stub should be disconnected.
+ * reserved [I] Reserved. Should be set to 0.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: HRESULT code.
+ *
+ * SEE ALSO
+ * CoMarshalInterface, CoReleaseMarshalData, CoLockObjectExternal
*/
HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
{
- FIXME("(%p, %lx): stub - probably harmless\n",lpUnk,reserved);
+ HRESULT hr;
+ IMarshal *marshal;
+ APARTMENT *apt;
+
+ TRACE("(%p, 0x%08lx)\n", lpUnk, reserved);
+
+ hr = IUnknown_QueryInterface(lpUnk, &IID_IMarshal, (void
**)&marshal);
+ if (hr == S_OK)
+ {
+ hr = IMarshal_DisconnectObject(marshal, reserved);
+ IMarshal_Release(marshal);
+ return hr;
+ }
+
+ apt = COM_CurrentApt();
+ if (!apt)
+ return CO_E_NOTINITIALIZED;
+
+ apartment_disconnect_object(apt, lpUnk);
+
+ /* Note: native is pretty broken here because it just silently
+ * fails, without returning an appropriate error code if the object
was
+ * not found, making apps think that the object was disconnected,
when
+ * it actually wasn't */
+
return S_OK;
}
/***********************************************************************
*******
- * CoCreateGuid[OLE32.@]
+ * CoCreateGuid [OLE32.@]
*
* Simply forwards to UuidCreate in RPCRT4.
*
+ * PARAMS
+ * pguid [O] Points to the GUID to initialize.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: HRESULT code.
+ *
* SEE ALSO
* UuidCreate
- *
*/
-HRESULT WINAPI CoCreateGuid(
- GUID *pguid /* [out] points to the GUID to initialize */
-) {
+HRESULT WINAPI CoCreateGuid(GUID *pguid)
+{
return UuidCreate(pguid);
}
@@ -701,17 +796,24 @@
* Converts a unique identifier from its string representation into
* the GUID struct.
*
+ * PARAMS
+ * idstr [I] The string representation of the GUID.
+ * id [O] GUID converted from the string.
+ *
+ * RETURNS
+ * S_OK on success
+ * CO_E_CLASSSTRING if idstr is not a valid CLSID
+ *
+ * BUGS
+ *
* In Windows, if idstr is not a valid CLSID string then it gets
* treated as a ProgID. Wine currently doesn't do this. If idstr is
* NULL it's treated as an all-zero GUID.
*
- * RETURNS
- * S_OK on success
- * CO_E_CLASSSTRING if idstr is not a valid CLSID
+ * SEE ALSO
+ * StringFromCLSID
*/
-HRESULT WINAPI __CLSIDFromStringA(
- LPCSTR idstr, /* [in] string representation of guid */
- CLSID *id) /* [out] GUID converted from string */
+HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id)
{
const BYTE *s = (const BYTE *) idstr;
int i;
@@ -771,9 +873,7 @@
/***********************************************************************
******/
-HRESULT WINAPI CLSIDFromString(
- LPOLESTR idstr, /* [in] string representation of GUID */
- CLSID *id ) /* [out] GUID represented by above
string */
+HRESULT WINAPI CLSIDFromString(LPOLESTR idstr, CLSID *id )
{
char xid[40];
HRESULT ret;
@@ -831,14 +931,19 @@
* Converts a GUID into the respective string representation.
* The target string is allocated using the OLE IMalloc.
*
+ * PARAMS
+ * id [I] the GUID to be converted.
+ * idstr [O] A pointer to a to-be-allocated pointer pointing to the
resulting string.
+ *
* RETURNS
* S_OK
* E_FAIL
+ *
+ * SEE ALSO
+ * StringFromGUID2, CLSIDFromString
*/
-HRESULT WINAPI StringFromCLSID(
- REFCLSID id, /* [in] the GUID to be converted */
- LPOLESTR *idstr /* [out] a pointer to a to-be-allocated pointer
pointing to the resulting string */
-) {
+HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR *idstr)
+{
char buf[80];
HRESULT ret;
LPMALLOC mllc;
@@ -856,19 +961,22 @@
}
/***********************************************************************
*******
+ * StringFromGUID2 [OLE32.@]
* StringFromGUID2 [COMPOBJ.76]
- * StringFromGUID2 [OLE32.@]
*
* Modified version of StringFromCLSID that allows you to specify max
* buffer size.
*
+ * PARAMS
+ * id [I] GUID to convert to string.
+ * str [O] Buffer where the result will be stored.
+ * cmax [I] Size of the buffer in characters.
+ *
* RETURNS
- * The length of the resulting string, 0 if there was any problem.
+ * Success: The length of the resulting string in characters.
+ * Failure: 0.
*/
-INT WINAPI StringFromGUID2(
- REFGUID id, /* [in] GUID to convert to string */
- LPOLESTR str, /* [out] Unicode buffer to hold result */
- INT cmax)
+INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
{
char xguid[80];
@@ -880,18 +988,18 @@
/***********************************************************************
*******
* ProgIDFromCLSID [OLE32.@]
*
- * Converts a class id into the respective Program ID. (By using a
- * registry lookup)
+ * Converts a class id into the respective program ID.
*
+ * PARAMS
+ * clsid [I] Class ID, as found in registry.
+ * lplpszProgID [O] Associated ProgID.
+ *
* RETURNS
* S_OK
* E_OUTOFMEMORY
* REGDB_E_CLASSNOTREG if the given clsid has no associated ProgID
*/
-HRESULT WINAPI ProgIDFromCLSID(
- REFCLSID clsid, /* [in] class id as found in registry */
- LPOLESTR *lplpszProgID/* [out] associated Prog ID */
-)
+HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID)
{
char strCLSID[50], *buf, *buf2;
DWORD buf2len;
@@ -959,18 +1067,20 @@
}
/***********************************************************************
*******
+ * CLSIDFromProgID [OLE32.@]
* CLSIDFromProgID [COMPOBJ.61]
*
- * Converts a program id into the respective GUID. (By using a
- * registry lookup)
+ * Converts a program id into the respective GUID.
*
+ * PARAMS
+ * progid [I] Unicode program ID, as found in registry.
+ * riid [O] Associated CLSID.
+ *
* RETURNS
- * S_OK
- * CO_E_CLASSSTRING if the given ProgID cannot be found
+ * Success: S_OK
+ * Failure: CO_E_CLASSSTRING - the given ProgID cannot be found.
*/
-HRESULT WINAPI CLSIDFromProgID(
- LPCOLESTR progid, /* [in] Unicode program id as found in
registry */
- LPCLSID riid ) /* [out] associated CLSID */
+HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid)
{
static const WCHAR clsidW[] = { '\\','C','L','S','I','D',0 };
char buf2[80];
@@ -1001,9 +1111,20 @@
/***********************************************************************
******
* CoGetPSClsid [OLE32.@]
*
- * This function returns the CLSID of the proxy/stub factory that
- * implements IPSFactoryBuffer for the specified interface.
+ * Retrieves the CLSID of the proxy/stub factory that implements
+ * IPSFactoryBuffer for the specified interface.
*
+ * PARAMS
+ * riid [I] Interface whose proxy/stub CLSID is to be returned.
+ * pclsid [O] Where to store returned proxy/stub CLSID.
+ *
+ * RETURNS
+ * S_OK
+ * E_OUTOFMEMORY
+ * REGDB_E_IIDNOTREG if no PSFactoryBuffer is associated with the
IID, or it could not be parsed
+ *
+ * NOTES
+ *
* The standard marshaller activates the object with the CLSID
* returned and uses the CreateProxy and CreateStub methods on its
* IPSFactoryBuffer interface to construct the proxies and stubs for a
@@ -1014,17 +1135,15 @@
* in the registry and any interface id registered by
* CoRegisterPSClsid within the current process.
*
- * FIXME: We only search the registry, not ids registered with
+ * BUGS
+ *
+ * We only search the registry, not ids registered with
* CoRegisterPSClsid.
- *
- * RETURNS
- * S_OK
- * E_OUTOFMEMORY
- * E_INVALIDARG if no PSFactoryBuffer is associated with the IID, or
it could not be parsed
+ * Also, native returns S_OK for interfaces with an key in
HKCR\Interface, but
+ * without a ProxyStubClsid32 key and leaves garbage in pclsid. This
should be
+ * considered a bug in native unless an application depends on this
(unlikely).
*/
-HRESULT WINAPI CoGetPSClsid(
- REFIID riid, /* [in] Interface whose proxy/stub CLSID is
to be returned */
- CLSID *pclsid ) /* [out] Where to store returned proxy/stub
CLSID */
+HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
{
char *buf, buf2[40];
DWORD buf2len;
@@ -1038,9 +1157,7 @@
(length of iid string plus constant length of static text */
buf = HeapAlloc(GetProcessHeap(), 0, strlen(buf2)+27);
if (buf == NULL)
- {
- return (E_OUTOFMEMORY);
- }
+ return E_OUTOFMEMORY;
/* Construct the registry key we want */
sprintf(buf,"Interface\\%s\\ProxyStubClsid32", buf2);
@@ -1048,9 +1165,9 @@
/* Open the key.. */
if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
{
- WARN("No PSFactoryBuffer object is registered for this IID\n");
- HeapFree(GetProcessHeap(),0,buf);
- return (E_INVALIDARG);
+ WARN("No PSFactoryBuffer object is registered for IID %s\n",
debugstr_guid(riid));
+ HeapFree(GetProcessHeap(),0,buf);
+ return REGDB_E_IIDNOTREG;
}
HeapFree(GetProcessHeap(),0,buf);
@@ -1060,19 +1177,18 @@
buf2len = sizeof(buf2);
if ( (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) )
{
- RegCloseKey(xhkey);
- return E_INVALIDARG;
+ RegCloseKey(xhkey);
+ return REGDB_E_IIDNOTREG;
}
RegCloseKey(xhkey);
/* We have the CLSid we want back from the registry as a string, so
lets convert it into a CLSID structure */
- if ( (__CLSIDFromStringA(buf2,pclsid)) != NOERROR) {
- return E_INVALIDARG;
- }
+ if ( (__CLSIDFromStringA(buf2,pclsid)) != NOERROR)
+ return REGDB_E_IIDNOTREG;
TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
- return (S_OK);
+ return S_OK;
}
@@ -1080,7 +1196,15 @@
/***********************************************************************
* WriteClassStm (OLE32.@)
*
- * This function write a CLSID on stream
+ * Writes a CLSID to a stream.
+ *
+ * PARAMS
+ * pStm [I] Stream to write to.
+ * rclsid [I] CLSID to write.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: HRESULT code.
*/
HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid)
{
@@ -1095,7 +1219,15 @@
/***********************************************************************
* ReadClassStm (OLE32.@)
*
- * This function read a CLSID from a stream
+ * Reads a CLSID from a stream.
+ *
+ * PARAMS
+ * pStm [I] Stream to read from.
+ * rclsid [O] CLSID to read.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: HRESULT code.
*/
HRESULT WINAPI ReadClassStm(IStream *pStm,CLSID *pclsid)
{
@@ -1196,6 +1328,13 @@
* files use this method instead of exporting DllGetClassObject to
allow
* other code to connect to their objects.
*
+ * PARAMS
+ * rclsid [I] CLSID of the object to register.
+ * pUnk [I] IUnknown of the object.
+ * dwClsContext [I] CLSCTX flags indicating the context in which to
run the executable.
+ * flags [I] REGCLS flags indicating how connections are made.
+ * lpdwRegister [I] A unique cookie that can be passed to
CoRevokeClassObject.
+ *
* RETURNS
* S_OK on success,
* E_INVALIDARG if lpdwRegister or pUnk are NULL,
@@ -1209,11 +1348,11 @@
* can't do that with our current implementation.
*/
HRESULT WINAPI CoRegisterClassObject(
- REFCLSID rclsid, /* [in] CLSID of the object to register
*/
- LPUNKNOWN pUnk, /* [in] IUnknown of the object */
- DWORD dwClsContext, /* [in] CLSCTX flags indicating the
context in which to run the executable */
- DWORD flags, /* [in] REGCLS flags indicating how
connections are made */
- LPDWORD lpdwRegister) /* [out] A unique cookie that can be
passed to CoRevokeClassObject */
+ REFCLSID rclsid,
+ LPUNKNOWN pUnk,
+ DWORD dwClsContext,
+ DWORD flags,
+ LPDWORD lpdwRegister)
{
RegisteredClass* newClass;
LPUNKNOWN foundObject;
[truncated at 1000 lines; 5300 more skipped]
- Initialize the Lock value of a stream file object.
Modified: trunk/reactos/ntoskrnl/io/create.c
_____
Modified: trunk/reactos/ntoskrnl/io/create.c
--- trunk/reactos/ntoskrnl/io/create.c 2005-02-13 15:38:56 UTC (rev
13526)
+++ trunk/reactos/ntoskrnl/io/create.c 2005-02-13 17:09:10 UTC (rev
13527)
@@ -245,6 +245,7 @@
// shouldn't we initialize the lock event, and several other things
here too?
KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent,
FALSE);
+ KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent,
TRUE);
return CreatedFileObject;
}