diff options
Diffstat (limited to 'private/ole32/dcomss/objex/shrmem')
64 files changed, 14240 insertions, 0 deletions
diff --git a/private/ole32/dcomss/objex/shrmem/client/clt.cxx b/private/ole32/dcomss/objex/shrmem/client/clt.cxx new file mode 100644 index 000000000..cd2c094e5 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/client/clt.cxx @@ -0,0 +1,227 @@ + +#include <or.hxx> +#include <simpleLL.hxx> + +handle_t SMTBinding; + +DECLARE_INFOLEVEL(Cairole) + +void +ClientSetup() +{ + WCHAR other[10]; + RPC_STATUS status = 1; + RPC_NS_HANDLE ImportContext = NULL; + TCHAR * pszStringBinding = NULL; + + /* + + printf("Other = "); + scanf("%S",other); + + WCHAR* entryName = catenate(TEXT("/.:/ShareTest"),other); + + status = RpcNsBindingImportBegin( + NULL, + entryName, + SharedMemoryTest_ClientIfHandle, + NULL, + &ImportContext + ); + + printf("RpcNsBindingImportBegin returned 0x%x\n", status); + if (status) + exit(status); + + if (!ImportContext) { + printf("No Import Context Available", status); + exit(1); + } + + status = RpcNsBindingImportNext( + ImportContext, + &SMTBinding); + + printf("RpcNsBindingImportNext returned 0x%x\n", status); + + if (!status) { + RpcBindingToStringBinding( + SMTBinding, + &pszStringBinding + ); + + printf("Binding = %S\n",pszStringBinding); + RpcStringFree(&pszStringBinding); + } + */ + + status = RpcStringBindingCompose( + NULL, + TEXT("ncalrpc"), + NULL, + NULL, + NULL, + &pszStringBinding + ); + + if (!status) { + RpcBindingFromStringBinding( + pszStringBinding, + &SMTBinding + ); + } + + if (status || !SMTBinding) + { + printf("No Binding Handle Available", status); + exit(1); + } + + /* + status = RpcNsBindingImportDone(&ImportContext); + */ +} + + +void +TestSimple() +{ + long *x = (long*) OrMemAlloc(sizeof(long)); + *x = rand(); + + printf("Calling the remote procedure 'RemoteRead'\n"); + + long answer; + + RpcTryExcept { + RemoteRead((ULONG)OR_OFFSET(x), &answer); // make call with user message + } + RpcExcept(1) { + RPC_STATUS ulCode = RpcExceptionCode(); + printf("Runtime reported exception 0x%lx \n", ulCode); + exit(ulCode); + } + RpcEndExcept + + if (answer == *x) printf("Simple Success!\n"); + else printf("Failure!\n"); +} + +void +TestList() +{ + CSimpleLinkList OR_BASED *pList = NEW_OR_BASED_SIMPLE(CSimpleLinkList); + + unsigned long i; + + for (i = 0; i < 10; i++) + { + unsigned long next = rand(); + pList->insert((void*)next); + printf("Inserted %d\n",next); + } + + CSimpleLinkListIterator Iter(*OR_FULL_POINTER(CSimpleLinkList,pList)); + + SendList((based_ptr) pList); + + unsigned long answer; + + for (i = 0; i < 10; i++) + { + ReadNext(&answer); + if (answer == (unsigned long)Iter.next()) printf("List Success for %d\n",answer); + } +} + +void +TestLocalResolverAPI() +{ + HPROCESS hProcess; + DWORD dwTimeoutInSeconds; + MID LocalMid, Mid; + BOOL DisableDCOM; + DWORD AuthnLevel; + DWORD ImpLevel; + BOOL MutualAuth; + DWORD cServerSvc; + USHORT *aServerSvc; + DWORD cClientSvc; + USHORT *aClientSvc; + + ID Oxid; + + ID aOids[2]; + + long Status; + + OXID_INFO oxidInfo; + + Status = ConnectDCOM( + &hProcess, + &dwTimeoutInSeconds, + &LocalMid, + &DisableDCOM, + &AuthnLevel, + &ImpLevel, + &MutualAuth, + &cServerSvc, + &aServerSvc, + &cClientSvc, + &aClientSvc + ); + + GetIds(&Oxid,&aOids[0]); + + Status = ResolveOXID( + hProcess, + Oxid, + NULL, + FALSE, + oxidInfo, + Mid + ); + + Status = ClientAddOID( + hProcess, + aOids[0], + Oxid, + Mid + ); + + Status = ClientDropOID( + hProcess, + aOids[0], + Mid + ); + + ShutDown(); +} + + +void __cdecl +main() +{ + srand(GetCurrentTime()); + + ClientSetup(); + TestLocalResolverAPI(); + + RPC_STATUS status = RpcBindingFree(&SMTBinding); + printf("RpcBindingFree returned 0x%x\n", status); + if (status) + exit(status); +} + + +/* MIDL allocate and free */ + +void __RPC_FAR * __RPC_API midl_user_allocate(size_t len) +{ + return(malloc(len)); +} + +void __RPC_API midl_user_free(void __RPC_FAR * ptr) +{ + free(ptr); +} diff --git a/private/ole32/dcomss/objex/shrmem/client/makefile b/private/ole32/dcomss/objex/shrmem/client/makefile new file mode 100644 index 000000000..14f79b701 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/client/makefile @@ -0,0 +1 @@ +!include $(NTMAKEENV)\makefile.def diff --git a/private/ole32/dcomss/objex/shrmem/client/sources b/private/ole32/dcomss/objex/shrmem/client/sources new file mode 100644 index 000000000..6df535a1c --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/client/sources @@ -0,0 +1,109 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David Plummer (davepl) 19-Mar-94 + + Modifed by via awk to include global project include file + and to wrap precompiled header line within a conditional + that can be set in this include file. + + Drew Bliss (DrewB) 21-Dec-1993 + +!ENDIF + +!IF "$(NTDEBUG)" != "ntsd" +CXXCPP_OPTIONS=-DDBG=0 +!else +CXXCPP_OPTIONS=-DDBG=1 +DEBUG_DEFINES=-DLDEBUG +MSC_OPTIMIZATION=/Od +!endif + +MAJORCOMP= cairole +MINORCOMP= stg + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= clt + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= ..\bin + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= PROGRAM + +PRECOMPILED_INCLUDE= ..\or.hxx + +# +# The following includes a global include file defined at the +# base of the project for all components +# + +!include \nt\private\ole32\daytona.inc + +INCLUDES=..;..\dcom95;..\stg;C:\nt\private\ole32\dcomss;\nt\private\ole32\ih;\nt\private\ole32\com\inc;\nt\private\ole32\common\daytona;\nt\private\ole32\stg\docfile;\nt\private\ole32\stg\h;C:\nt\private\dcomidl\obj;C:\nt\private\ole32\stg\exp + + +C_DEFINES= \ + $(C_DEFINES) \ + -DMULTIHEAP + +SOURCES= \ + clt.cxx \ + test_c.c + +LIBDIR=$(_NTDRIVE)\nt\public\sdk\lib + +OLEDIR=$(_NTDRIVE)\nt\private\ole32 + +LINKLIBS=$(LIBDIR)\*\Rpcrt4.lib \ + $(LIBDIR)\*\RpcNdr.lib \ + $(LIBDIR)\*\ntdll.lib \ + $(LIBDIR)\*\uuid.lib \ + $(LIBDIR)\*\user32.lib \ + $(LIBDIR)\*\security.lib \ + $(LIBDIR)\*\ole32.lib \ + $(OLEDIR)\common\daytona\obj\*\common.lib \ + $(OLEDIR)\com\inc\daytona\obj\*\inc.lib \ + ..\lib\*\stg.lib \ + ..\lib\*\dcom95.lib \ + ..\lib\*\special.lib + +USE_LIBCMT=1 + +UMTYPE= console +UMAPPL= +UMTEST= +UMLIBS= + +PRECOMPILED_OPTION= +#PRECOMPILED_TARGET=..\obj\*\$(PRECOMPILED_PCH) +PRECOMPILED_CXX= + diff --git a/private/ole32/dcomss/objex/shrmem/daytona.inc b/private/ole32/dcomss/objex/shrmem/daytona.inc new file mode 100644 index 000000000..e6bcee983 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/daytona.inc @@ -0,0 +1,39 @@ +!IF "$(NTDEBUG)" != "ntsd" +CXXCPP_OPTIONS=-DDBG=0 +!else +CXXCPP_OPTIONS=-DDBG=1 +DEBUG_DEFINES=-DLDEBUG +MSC_OPTIMIZATION=/Od +!endif + +MAJORCOMP= cairole +MINORCOMP= dcom95 + + +# +# The following includes a global include file defined at the +# base of the project for all components +# + +OLEDIR= $(_NTDRIVE)\nt\private\ole32 + +!include $(OLEDIR)\daytona.inc + +INCLUDES= ..; \ + ..\..; \ + ..\..\dcom95; \ + $(_NTDRIVE)\nt\private\ole32\ih; \ + $(_NTDRIVE)\nt\private\ole32\com\inc; \ + $(_NTDRIVE)\nt\private\ole32\common\daytona; \ + $(_NTDRIVE)\nt\private\ole32\stg\h; \ + $(_NTDRIVE)\nt\private\dcomidl\obj; \ + $(_NTDRIVE)\nt\private\ole32\stg\exp; \ + $(_NTDRIVE)\nt\private\ole32\com\dcomrem; \ + $(_NTDRIVE)\nt\private\ole32\dcomss + +C_DEFINES= \ + $(C_DEFINES) \ + -D_REMOTE_OR_ \ + -DSHRMEM_OBJEX + +PRECOMPILED_INCLUDE= ..\..\or.hxx diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/base.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/base.hxx new file mode 100644 index 000000000..efb1784c0 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/base.hxx @@ -0,0 +1,240 @@ +#ifndef __SHARE_HXX__ +#define __SHARE_HXX__ + +#include <memory.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> + +extern void DfReleaseSharedMemBase (); + +#define olAssert(exp) Win4Assert(exp) + +#include <sem.hxx> +#include <smcreate.hxx> +#include <entry.hxx> +#include <smalloc.hxx> +#include <df32.hxx> + +#ifdef _CHICAGO_ +#define gSharedAllocator g_smAllocator +#else // _CHICAGO_ +#define gSharedAllocator gsmDCOMAllocator +#endif // _CHICAGO_ + +extern CSmAllocator gSharedAllocator; // global shared memory allocator + +extern void *pSharedBase; + +HRESULT InitDCOMSharedAllocator(ULONG,void*&); + +typedef unsigned long based_ptr; + + +//+------------------------------------------------------------------- +// +// Function: OrMemAlloc for Memphis +// +// Synopsis: Allocate some shared memory from the storage heap. +// +// Notes: Also used in an NT version for debugging purposes +// +//-------------------------------------------------------------------- +inline void *OrMemAlloc(size_t size) +{ + return gSharedAllocator.Alloc(size); +} + +//+------------------------------------------------------------------- +// +// Function: OrMemFree for Memphis +// +// Synopsis: Free shared memory from the storage heap. +// +// Notes: Also used in an NT version for debugging purposes +// +//-------------------------------------------------------------------- +inline void OrMemFree(void * pv) +{ + gSharedAllocator.Free(pv); +} + + +//+------------------------------------------------------------------- +// +// Macros: OR_FULL_POINTER, OR_OFFSET, NEW_OR_BASED, +// DELETE_OR_BASED and OR_BASED +// +// Synopsis: Typeful pointer arithmetic to adjust based pointers, and +// satisfy the needs of new and delete operator prototypes. +// +// Notes: As a general policy, we do not use based pointers in +// interfaces -- their use is confined to private members +// of shared objects only. This policy is dictated by +// the need to work around certain apparent compiler bugs +// in casting based pointers, and also makes for simplicity. +// The pragma is also part of the workaround, but disabled for now. +// +//-------------------------------------------------------------------- + + +//#pragma warning(error: 4795 4796) + +#ifndef _CHICAGO_ + +#define OR_BASED __based(pSharedBase) + +#define OR_FULL_POINTER(TYPE,BASEDPTR) \ + ((TYPE*) (((BASEDPTR) != 0) ? (BASEDPTR) : 0)) + +/* + +inline +void OR_BASED * +OR_OFFSET(void *pv) +{ + if (pv) return (void OR_BASED *)pv; + else return 0; +} + +*/ + +// the following could be a template function when templates support based pointer types +// it could also use the inline function above when the compiler loses a related bug +// WARNING: This macro uses and hence evaluates its second parameter twice! +#define OR_BASED_POINTER(TYPE,PTR) \ + ((TYPE OR_BASED *) (ULONG) (((ULONG)(PTR) != 0) ? \ + (ULONG)((ULONG)(PTR) - (ULONG)pSharedBase) : 0)) + +#else // _CHICAGO_ -- Uses absolute pointers in the system heap + +#define OR_BASED + +#define OR_FULL_POINTER(TYPE,BASEDPTR) BASEDPTR + +#define OR_BASED_POINTER(TYPE,PTR) PTR + +#endif // _CHICAGO_ + +inline ULONG +OR_OFFSET(void *pv) +{ + return (ULONG) (OR_BASED_POINTER(void,pv)); +} + + +#define NEW_OR_BASED(VAR,CLASS,PARAMS) \ +{ \ + CLASS *nonbased_temp = new CLASS##PARAMS; \ + VAR = OR_BASED_POINTER(CLASS, nonbased_temp); \ +} + +#define NEW_OR_BASED_ARRAY(VAR,CLASS,SIZE) \ +{ \ + CLASS *nonbased_temp = new (InSharedHeap) CLASS[SIZE]; \ + VAR = OR_BASED_POINTER(CLASS, nonbased_temp); \ +} + +#define DELETE_OR_BASED(TYPE,BASEDPTR) \ + (delete OR_FULL_POINTER(TYPE,BASEDPTR)) + +#define ALLOC_OR_BASED(VAR,TYPE,SIZE) \ +{ \ + TYPE *nonbased_temp = (TYPE*)OrMemAlloc(SIZE); \ + VAR = OR_BASED_POINTER(TYPE, nonbased_temp); \ +} + +#define DEALLOC_OR_BASED(TYPE,BASEDPTR) \ + OrMemFree(OR_FULL_POINTER(TYPE,BASEDPTR)); + + +// WARNING: THIS IS A COMPILER-SPECIFIC HACK +// The VC++ compiler keeps the array size in the first 4 bytes +// and passes us a pointer displaced 4 bytes from the true +// allocated block, causing misalignment and other grief + +#define DELETE_OR_BASED_ARRAY(TYPE,OFFSET,COUNT) \ +{ \ + TYPE *arr = OR_FULL_POINTER(TYPE,OFFSET); \ + for (USHORT i = 0; i < COUNT; i++) arr[i].~TYPE(); \ + OrMemFree(((BYTE*)arr)-4); \ +} + + +#if DBG + +// +// Some simple sanity checking in non-stress conditions +// +// The assumption is that based pointers should not get +// too big unless something goes wrong +// + +#define MAX_OFFSET 0x100000 // for DBG validation checking only + +inline +void IsGoodBasedPtr(void OR_BASED *pv) +{ +#ifndef _CHICAGO_ // on Chicago, we use absolute addresses + ULONG offset = (ULONG)pv; + ASSERT((offset >= 0) && (offset < MAX_OFFSET)); +#endif // _CHICAGO_ +} + +// +// A validation class template and macros +// +// The constructor and destructor for the ValidityCheck template call +// a function "IsValid" on the current object of class TYPE, which is the +// template parameter. This is meant to validate the object at entry to +// each method and also at all exit points of the method. +// +// + +template <class TYPE> +class ValidityCheck +{ +private: + + TYPE *thisPtr; + +public: + + ValidityCheck(void * pv) + { + thisPtr = (TYPE *) pv; + thisPtr->IsValid(); + } + + ~ValidityCheck() + { + thisPtr->IsValid(); + } +}; + +// +// To use the template defined above for guarding methods in a class, +// use the following steps +// +// 1. Define a public method (possibly conditionally compiled #if DBG) +// with the name "IsValid" and no parameters. This will typically +// ASSERT in case something is wrong. +// +// 2. In the private part of the class, call the macro DECLARE_VALIDITY_CLASS +// with the name of the class as the parameter. +// +// 3 In each method to be guarded for validity, call the macro VALIDATE_METHOD at +// the beginning. +// + +#define DECLARE_VALIDITY_CLASS(TYPE) \ + typedef ValidityCheck<TYPE> MyValidityCheckerClass; + +#define VALIDATE_METHOD \ + MyValidityCheckerClass ValidityCheckerObject(this); \ + +#endif // DBG + +#endif __SHARE_HXX__ diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx new file mode 100644 index 000000000..866d373aa --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx @@ -0,0 +1,113 @@ +/*++ + +Copyright (c) 1996 Microsoft Corporation + +Module Name: + + callid.cxx + +Abstract: + + Implements a cache of callids used for running down OIDs + + This is almost twice as fast as UuidCreate() but that doesn't + mean much. UuidCreate takes 3 microseconds, this 1.4 (hit) or + 4.2 (miss) on a P90. + + This codes real advantage would be on MP machines. But it is + not performance critical and is probably overkill. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 1/18/1996 Bits 'n pieces + +--*/ + +#include <or.hxx> + +enum CacheState { CallidEmpty = 0, + CallidAllocated = 1, + CallidFree = -1 }; + +struct CacheElement + { + CacheState _state; + UUID _callid; + }; + +CacheElement CallidCache[4] = { CallidEmpty, {0}, + CallidEmpty, {0}, + CallidEmpty, {0}, + CallidEmpty, {0} }; + + +INT +AllocateCallId( + OUT UUID &Callid + ) +{ + INT i; + LONG l; + RPC_STATUS status; + + for (i = 0; i < 4; i++) + { + if (CallidCache[i]._state != CallidAllocated) + { + l = InterlockedExchange((PLONG)&CallidCache[i]._state, CallidAllocated); + + switch(l) + { + case CallidAllocated: + continue; + + case CallidFree: + Callid = CallidCache[i]._callid; + return(i); + + case CallidEmpty: + status = UuidCreate(&Callid); + VALIDATE((status, RPC_S_OK, RPC_S_UUID_LOCAL_ONLY, 0)); + CallidCache[i]._callid = Callid; + return(i); + } + } + } + status = UuidCreate(&Callid); + VALIDATE((status, RPC_S_OK, RPC_S_UUID_LOCAL_ONLY, 0)); + return(-1); + } + + +void +FreeCallId( + IN INT hint + ) +/*++ + +Routine Description: + + Frees a callid previously allcoated with AllocateCallId(). + +Arguments: + + hint - The hint value returned by the previous call to AllocateCallId(). + +Return Value: + + None + +--*/ +{ + ASSERT(hint > -2 & hint < 4); + + if (hint >= 0) + { + CallidCache[hint]._state = CallidFree;; + } +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx new file mode 100644 index 000000000..52406961c --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 1996 Microsoft Corporation + +Module Name: + + callid.hxx + +Abstract: + + Implements a cache of callids used for running down OIDs + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 1/18/1996 Bits 'n pieces + +--*/ + +#ifndef __CALLID_HXX +#define __CALLID_HXX + +INT AllocateCallId( + OUT UUID &Callid + ); + +void FreeCallId( + IN INT hint + ); + +#endif // __CALLID_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile new file mode 100644 index 000000000..14f79b701 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile @@ -0,0 +1 @@ +!include $(NTMAKEENV)\makefile.def diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def new file mode 100644 index 000000000..701c851ce --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def @@ -0,0 +1,37 @@ +LIBRARY resolver + +DESCRIPTION 'Microsoft (R) Local OR interface Shared Memory Development' + +EXPORTS + + + pSharedBase + ConnectDCOM + ClientAddOID + ClientDropOID + ResolveClientOXID + ServerAllocateOXID + ServerAllocateOID + ServerFreeOXID + RundownTimerProc + + Connect + Disconnect + AllocateReservedIds + ClientResolveOXID + ServerAllocateOXIDAndOIDs + ServerAllocateOIDs + ServerFreeOXIDAndOIDs + + gpNextThreadID + ComputeSecurity + ScmObjexGetThreadId + PingThread + SCMGetBindingHandle + OrResolveOxid + _ComplexPing + _SimplePing + GetRegisteredProtseqs + GetLocalORBindings + SCMRemoveClassReg + SCMAddClassReg diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources new file mode 100644 index 000000000..824322f52 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources @@ -0,0 +1,99 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David Plummer (davepl) 19-Mar-94 + + Modifed by via awk to include global project include file + and to wrap precompiled header line within a conditional + that can be set in this include file. + + Drew Bliss (DrewB) 21-Dec-1993 + +!ENDIF + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= resolver + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= ..\..\lib + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= DYNLINK + +!include ..\..\daytona.inc + +SOURCES= \ + ..\scmfuns.cxx \ + ..\iface.cxx \ + ..\globals.cxx \ + ..\manager.cxx \ + ..\misc.cxx \ + ..\mid.cxx \ + ..\process.cxx \ + ..\callid.cxx \ + ..\oxid.cxx \ + ..\objex.cxx \ + ..\epts.c \ + ..\dsa.cxx \ + ..\string.cxx \ + ..\gentable.cxx \ + ..\linklist.cxx \ + ..\set.cxx + + +DLLENTRY= _DllMainCRTStartup + +DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,kerberos + +LIBDIR=$(_NTDRIVE)\nt\public\sdk\lib + +LINKLIBS= \ + ..\..\lib\*\stg.lib \ + $(BASEDIR)\private\dcomidl\obj\*\dcomidl.lib \ + $(OLEDIR)\common\daytona\obj\*\common.lib \ + $(OLEDIR)\com\inc\daytona\obj\*\inc.lib \ + $(LIBDIR)\*\ole32.lib \ + $(LIBDIR)\*\rpcrt4.lib \ + $(LIBDIR)\*\security.lib \ + $(LIBDIR)\*\netapi32.lib \ + $(LIBDIR)\*\advapi32.lib \ + $(LIBDIR)\*\ntdll.lib \ + $(LIBDIR)\*\nt.lib \ + $(LIBDIR)\*\kernel32.lib \ + $(LIBDIR)\*\uuid.lib \ + $(LIBDIR)\*\user32.lib \ + +USE_LIBCMT=1 + +UMTYPE= console +UMAPPL= +UMTEST= +UMLIBS= diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx new file mode 100644 index 000000000..3f585e4d0 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx @@ -0,0 +1,54 @@ +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + debug.cxx + +Abstract: + + This file contains the implementations for non inline member functions + used for debugging output via the CDbgStr class, as well as debug + and retail versions of midl_user_{allocate,free}. + +Author: + + Satish Thatte (SatishT) 08/15/95 Created all the code below except where + otherwise indicated. + +--*/ + + +#include <or.hxx> + +#if DBG + +CDbgStr debugOut; + +typedef struct _tagDoubleS +{ + ULONG first; + ULONG second; +} *PIDT; + + +CDbgStr& +CDbgStr::operator<<( + ID id + ) +{ + PIDT p = (PIDT)&id; + +#ifndef _CHICAGO_ + DbgPrint("%x ",p->second); + DbgPrint("%x ",p->first); +#else // BUGBUG: Do something about this! +#endif + + return *this; +} + +#endif + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx new file mode 100644 index 000000000..26e6aa0ef --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx @@ -0,0 +1,110 @@ +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + debug.hxx + +Abstract: + + This module contains + + 1. a definition of the CDbgStr class which is used to + produce debugging output. + +Author: + + Satish Thatte (SatishT) 08/16/95 Created all the code below except where + otherwise indicated. + +--*/ + + +#ifndef _DEBUG_HXX_ +#define _DEBUG_HXX_ + +#define TRACE 1 +#define DETAIL 2 +#define SUPER_DETAIL 4 +#define RUNDOWN 8 + +extern UINT debugLevel; + +#if DBG + +#define DBGOUT(LEVEL,MESSAGE) \ + if ((debugLevel | LEVEL) == debugLevel) debugOut << MESSAGE + + +/*++ + +Class Definition: + + CDbgStr + +Abstract: + + This is similar to the standard ostream class, except that the + output goes to the debugger. + +--*/ + +#define WSTRING(STR) L##STR + +class CDbgStr { + +public: + + CDbgStr& operator<<(ULONG ul) { + WCHAR buffer[20]; + swprintf(buffer, WSTRING(" %d "), ul); + OutputDebugStringW(buffer); + return *this; + } + + CDbgStr& operator<<(void *ptr) { + WCHAR buffer[20]; + swprintf(buffer, WSTRING(" %x "), (ULONG)ptr); + OutputDebugStringW(buffer); + return *this; + } + + CDbgStr& operator<<(void OR_BASED *ptr) { + WCHAR buffer[20]; + swprintf(buffer, WSTRING(" %x "), (ULONG)ptr); + OutputDebugStringW(buffer); + return *this; + } + + CDbgStr& operator<<(char *sz) { + if (!sz) return *this; + + WCHAR buffer[200]; + swprintf(buffer, WSTRING(" %S "), sz); + OutputDebugStringW(buffer); + return *this; + } + + CDbgStr& operator<<(WCHAR * sz) { + if (!sz) return *this; + + OutputDebugStringW(sz); + return *this; + } + + CDbgStr& operator<<(ID id); +}; + +extern CDbgStr debugOut; + +#else + +#define DBGOUT(LEVEL,MESSAGE) + +#endif + + + +#endif _DEBUG_HXX_ diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx new file mode 100644 index 000000000..c8873471b --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx @@ -0,0 +1,4 @@ +BOOL WINAPI DllMain ( + HANDLE hInst, + ULONG ul_reason_for_call, + LPVOID lpReserved); diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dirs b/private/ole32/dcomss/objex/shrmem/dcom95/dirs new file mode 100644 index 000000000..a41d4d88e --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/dirs @@ -0,0 +1,28 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Steve Wood (stevewo) 17-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS= + +OPTIONAL_DIRS= \ + \ + daytona + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx new file mode 100644 index 000000000..59099dd93 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx @@ -0,0 +1,126 @@ +#include <or.hxx> + +// +// CBindingIterator methods +// + +PWSTR +CBindingIterator::Next() +{ + if (_iCurrentIndex == 0xffff) // fresh iterator, use starting index + { + _iCurrentIndex = _iStartingIndex; // not fresh any more + return &_dsa->aStringArray[_iStartingIndex]; + } + + PWSTR pwstrT = &_dsa->aStringArray[_iCurrentIndex]; + + pwstrT = OrStringSearch(pwstrT, 0) + 1; + + if (*pwstrT == 0) // the end of the string bindings was reached + { + PWSTR pwstrT = _dsa->aStringArray; // wrap around + } + + _iCurrentIndex = pwstrT - _dsa->aStringArray; + + if (_iStartingIndex != _iCurrentIndex) + { + return pwstrT; + } + else + { + return NULL; + } +} + +// +// CDSA methods +// + +ORSTATUS +CDSA::copyDSA(DUALSTRINGARRAY *pdsa) +{ + VALIDATE_METHOD + + DUALSTRINGARRAY *pdsaT = NULL; + _fOwnDSA = FALSE; + + if (pdsa != NULL) + { + pdsaT = (DUALSTRINGARRAY *) + OrMemAlloc(pdsa->wNumEntries + * sizeof(WCHAR) + + sizeof(DUALSTRINGARRAY) + ); + + if (!pdsaT) + { + return OR_NOMEM; + } + + dsaCopy(pdsaT, pdsa); + } + + _pdsa = OR_BASED_POINTER(DUALSTRINGARRAY,pdsaT); + if (_pdsa != NULL) _fOwnDSA = TRUE; + + return OR_OK; +} + +ORSTATUS +CDSA::copyDSAEx(DUALSTRINGARRAY *pdsa, BOOL fCompressed) +{ + VALIDATE_METHOD + + ORSTATUS status = OR_OK; + + if (fCompressed) + { + status = copyDSA(pdsa); + } + else + { + DUALSTRINGARRAY *pdsaT = CompressStringArray(pdsa,TRUE); + + if (pdsaT) + { + Assign(pdsaT); // no copying + } + else + { + status = OR_NOMEM; + _pdsa = NULL; + } + } + + return status; +} + + +ORSTATUS +CDSA::ExtractRemote(CDSA &dsaLocal) // pick out remote protseqs only + //.this is a kind of assignment +{ + VALIDATE_METHOD + + DUALSTRINGARRAY *pdsaT; + + ORSTATUS status = ::ConvertToRemote( + OR_FULL_POINTER(DUALSTRINGARRAY,dsaLocal._pdsa), + &pdsaT + ); + + if (status == OR_OK) + { + status = copyDSA(pdsaT); + delete pdsaT; + } + else + { + _pdsa = NULL; + } + + return status; +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx new file mode 100644 index 000000000..13bf2c8b2 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx @@ -0,0 +1,312 @@ +class CDSA : public ISearchKey // BUGBUG: this is overly complex +{ +private: + + friend class BindingIterator; + + DUALSTRINGARRAY OR_BASED * _pdsa; // always compressed + // and in shared memory + + BOOL _fOwnDSA; // our own copy? + + ORSTATUS copyDSA(DUALSTRINGARRAY *pdsa); // local helpers + +#ifndef _CHICAGO_ + ORSTATUS copyDSA(DUALSTRINGARRAY OR_BASED *pdsa) + { + return copyDSA(OR_FULL_POINTER(DUALSTRINGARRAY,pdsa)); + } +#endif // _CHICAGO_ + + ORSTATUS copyDSAEx(DUALSTRINGARRAY *pdsa, BOOL fCompressed); + +public: + +#if DBG + + void IsValid() + { + IsGoodBasedPtr(_pdsa); + if (_pdsa) ASSERT(Valid()); + ASSERT(_fOwnDSA==TRUE || _fOwnDSA==FALSE); + } + + DECLARE_VALIDITY_CLASS(CDSA) +#endif + + CDSA() // default constructor + { + _pdsa = NULL; + _fOwnDSA = FALSE; + } + + CDSA(const CDSA& cdsa, ORSTATUS& status); // copy constructor + ORSTATUS Assign(const CDSA& cdsa); // assignment method + + CDSA( // copying constructor + DUALSTRINGARRAY* pdsa, + BOOL fCompressed, // is it compressed? + ORSTATUS& status + ); + + ORSTATUS Assign( // corresponding assignment + DUALSTRINGARRAY* pdsa, + BOOL fCompressed // is it compressed? + ); + + CDSA(DUALSTRINGARRAY *pdsa); // noncopying constructors + +#ifndef _CHICAGO_ + CDSA(DUALSTRINGARRAY OR_BASED *pdsa); // param must be compressed + // and in shared memory +#endif // _CHICAGO_ + + void Assign(DUALSTRINGARRAY *pdsa); // corresponding assignments + +#ifndef _CHICAGO_ + void Assign(DUALSTRINGARRAY OR_BASED *pdsa); // param must be compressed + // and in shared memory +#endif // _CHICAGO_ + + // never destroyed as base object hence destructor need not be virtual + ~CDSA(); + + BOOL Valid(); // Integrity checking + + DWORD Hash(); + BOOL Compare(ISearchKey &tk); + + BOOL Compare(DUALSTRINGARRAY *pdsa); // alternate compare + + BOOL operator==(CDSA& dsa); + + BOOL Empty(); // is DSA NULL? + + operator DUALSTRINGARRAY*(); // auto conversion + + DUALSTRINGARRAY* operator->(); // smart pointer + + ORSTATUS ExtractRemote(CDSA &dsaLocal); // pick out remote protseqs only + //.this is a kind of assignment + + CDSA *MergeSecurityBindings( // return a new CDSA object in which + CDSA security, // we replace existing security part + ORSTATUS status); // with that of the parameter +}; + + +class CBindingIterator // this assumes a stable _dsa +{ +public: + + CBindingIterator(USHORT iStart, CDSA& dsa); + PWSTR Next(); + USHORT Index(); + +private: + + // 0xffff == _iCurrentIndex iff the iterator has not been used + // This is not portable, but for Win95, who cares? + + USHORT _iStartingIndex, _iCurrentIndex; + CDSA& _dsa; +}; + + +// +// Inline CBindingIterator methods +// + +inline +CBindingIterator::CBindingIterator( + USHORT iStart, + CDSA& dsa + ) + : _dsa(dsa), _iStartingIndex(iStart), _iCurrentIndex(0xffff) +{} + +inline +USHORT +CBindingIterator::Index() +{ + return _iCurrentIndex; +} + + +// +// Inline CDSA methods +// + +inline // copy constructor +CDSA::CDSA( + const CDSA& cdsa, + ORSTATUS& status) +{ +#if DBG // make valid to start with + _pdsa = NULL; + _fOwnDSA = FALSE; +#endif + + status = copyDSA(cdsa._pdsa); + IsValid(); +} + +inline +ORSTATUS +CDSA::Assign( // assignment method + const CDSA& cdsa) // preferred over operator +{ // since it returns status + VALIDATE_METHOD + DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa); + _pdsa = NULL; + + return copyDSA(cdsa._pdsa); +} + + +inline +CDSA::CDSA( // copying constructor + DUALSTRINGARRAY* pdsa, + BOOL fCompressed, // is it compressed? + ORSTATUS& status) +{ +#if DBG // make valid to start with + _pdsa = NULL; + _fOwnDSA = FALSE; +#endif + + status = copyDSAEx(pdsa,fCompressed); + IsValid(); +} + +inline ORSTATUS +CDSA::Assign( // Alternate assignment + DUALSTRINGARRAY* pdsa, + BOOL fCompressed) // is it compressed? +{ + VALIDATE_METHOD + DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa); + _pdsa = NULL; + return copyDSAEx(pdsa,fCompressed);; +} + +inline +CDSA::CDSA( // noncopying constructor + DUALSTRINGARRAY *pdsa) // param must be compressed + // and in shared memory +{ + _pdsa = OR_BASED_POINTER(DUALSTRINGARRAY,pdsa); + _fOwnDSA = FALSE; + IsValid(); +} + +#ifndef _CHICAGO_ + +inline +CDSA::CDSA( // noncopying constructor + DUALSTRINGARRAY OR_BASED *pdsa) // param must be compressed + // and in shared memory +{ + _fOwnDSA = FALSE; + _pdsa = pdsa; + IsValid(); +} + +#endif // _CHICAGO_ + +inline void +CDSA::Assign(DUALSTRINGARRAY *pdsa) // noncopying assignment +{ // param must be compressed + VALIDATE_METHOD // and in shared memory + DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa); + _pdsa = OR_BASED_POINTER(DUALSTRINGARRAY,pdsa); + +} + +#ifndef _CHICAGO_ + +inline void +CDSA::Assign(DUALSTRINGARRAY OR_BASED *pdsa) // noncopying assignment +{ // param must be compressed + VALIDATE_METHOD // and in shared memory + DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa); + _pdsa = pdsa; +} + +#endif // _CHICAGO_ + +inline +CDSA::~CDSA() +{ + if (_fOwnDSA) + { + DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa); + } +} + + +inline +CDSA::operator DUALSTRINGARRAY*() // auto conversion +{ + return OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa); +} + + +inline DUALSTRINGARRAY* +CDSA::operator->() // smart pointer +{ + return OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa); +} + + +inline BOOL +CDSA::Valid() // Integrity checking +{ + return dsaValid(OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa)); +} + + +inline DWORD +CDSA::Hash() +{ + return dsaHash(OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa)); +} + + +inline BOOL +CDSA::Compare(ISearchKey &tk) +{ + VALIDATE_METHOD + CDSA& dsaK = (CDSA&) tk; // same type of parameter + // must be assumed + return dsaCompare( + OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa), + OR_FULL_POINTER(DUALSTRINGARRAY,dsaK._pdsa) + ); +} + + +inline BOOL +CDSA::Compare(DUALSTRINGARRAY *pdsa) // alternative direct compare +{ + VALIDATE_METHOD + return dsaCompare( + OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa), + pdsa + ); +} + + +inline BOOL // REVIEW: replace Compare by == and != +CDSA::operator==(CDSA& dsa) +{ + return Compare(dsa); +} + + +inline BOOL +CDSA::Empty() // is DSA NULL? +{ + return _pdsa == NULL; +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/epts.c b/private/ole32/dcomss/objex/shrmem/dcom95/epts.c new file mode 100644 index 000000000..a7b82a272 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/epts.c @@ -0,0 +1,461 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Epts.c + +Abstract: + + Common code to listen to endpoints in the DCOM service. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 6/16/1995 Bits 'n pieces + +--*/ + +#ifdef _CHICAGO_ +#define ASSERT( exp ) if (! (exp) ) DebugBreak(); +#endif + +#define WSTR(s) L##s + +#include <dcomss.h> + +// Globals + +// BUGBUG - this info should be read from the registry. + +// The index is the protseq tower id. + + +PROTSEQ_INFO +gaProtseqInfo[] = + { + /* 0x00 */ { STOPPED, 0, 0 }, + /* 0x01 */ { STOPPED, 0, 0 }, + /* 0x02 */ { STOPPED, 0, 0 }, + /* 0x03 */ { STOPPED, 0, 0 }, + /* 0x04 */ { STOPPED, L"ncacn_dnet_dsp", L"#69" }, + /* 0x05 */ { STOPPED, 0, 0 }, + /* 0x06 */ { STOPPED, 0, 0 }, + /* 0x07 */ { STOPPED, L"ncacn_ip_tcp", L"135" }, + /* 0x08 */ { STOPPED, L"ncadg_ip_udp", L"135" }, + /* 0x09 */ { STOPPED, L"ncacn_nb_tcp", L"135" }, + /* 0x0a */ { STOPPED, 0, 0 }, + /* 0x0b */ { STOPPED, 0, 0 }, + /* 0x0c */ { STOPPED, L"ncacn_spx", L"34280" }, + /* 0x0d */ { STOPPED, L"ncacn_nb_ipx", L"135" }, + /* 0x0e */ { STOPPED, L"ncadg_ipx", L"34280" }, + /* 0x0f */ { STOPPED, L"ncacn_np", L"\\pipe\\epmapper" }, + /* 0x10 */ { STOPPED, L"ncalrpc", L"epmapper" }, + /* 0x11 */ { STOPPED, 0, 0 }, + /* 0x12 */ { STOPPED, 0, 0 }, + /* 0x13 */ { STOPPED, L"ncacn_nb_nb", L"135" }, + /* 0x14 */ { STOPPED, 0, 0 }, + /* 0x15 */ { STOPPED, 0, 0 }, // was ncacn_nb_xns - unsupported. + /* 0x16 */ { STOPPED, L"ncacn_at_dsp", L"Endpoint Mapper" }, + /* 0x17 */ { STOPPED, L"ncadg_at_ddp", L"Endpoint Mapper" }, + /* 0x18 */ { STOPPED, 0, 0 }, + /* 0x19 */ { STOPPED, 0, 0 }, + /* 0x1A */ { STOPPED, L"ncacn_vns_spp", L"385"} + }; + +#define PROTSEQ_IDS (sizeof(gaProtseqInfo)/sizeof(PROTSEQ_INFO)) + + +RPC_STATUS +UseProtseqIfNecessary( + IN USHORT id + ) +/*++ + +Routine Description: + + Listens to the well known RPC endpoint mapper endpoint + for the protseq. Returns very quickly if the process + is already listening to the protseq. + +Arguments: + + id - the tower id of protseq. See GetProtseqId() if you don't + already have this valud. + +Return Value: + + RPC_S_OK - no errors occured. + RPC_S_OUT_OF_RESOURCES - when we're unable to setup security for the endpoint. + RPC_S_INVALID_RPC_PROTSEQ - if id is unknown/invalid. + + Any error from RpcServerUseProtseqEp. + +--*/ +{ + RPC_STATUS status = RPC_S_OK; + SECURITY_DESCRIPTOR sd, *psd; + + ASSERT(id); + + if (id == 0 || id >= PROTSEQ_IDS) + { + ASSERT(0); + return(RPC_S_INVALID_RPC_PROTSEQ); + } + + if (gaProtseqInfo[id].state == STARTED) + { + return(RPC_S_OK); + } + + if (id == 0x10) + { + // ncalrpc needs a security descriptor. + + psd = &sd; + + InitializeSecurityDescriptor( + psd, + SECURITY_DESCRIPTOR_REVISION + ); + + if ( FALSE == SetSecurityDescriptorDacl ( + psd, + TRUE, // Dacl present + NULL, // NULL Dacl + FALSE // Not defaulted + ) ) + { + status = RPC_S_OUT_OF_RESOURCES; + } + } + else + { + psd = 0; + } + + if (status == RPC_S_OK ) + { + status = RpcServerUseProtseqEpW(gaProtseqInfo[id].pwstrProtseq, + RPC_C_PROTSEQ_MAX_REQS_DEFAULT + 1, + gaProtseqInfo[id].pwstrEndpoint, + psd); + + // No locking is done here, the RPC runtime may return duplicate + // endpoint if two threads call this at the same time. + if (status == RPC_S_DUPLICATE_ENDPOINT) + { + ASSERT(gaProtseqInfo[id].state == STARTED); + status = RPC_S_OK; + } + +#ifdef DEBUGRPC + if (status != RPC_S_OK) + { +#ifndef _CHICAGO_ + DbgPrint("DCOMSS: Unable to listen to %S\n", gaProtseqInfo[id].pwstrProtseq); +#endif + } +#endif + + if (status == RPC_S_OK) + { + gaProtseqInfo[id].state = STARTED; + } + } + + return(status); +} + + +PWSTR +GetProtseq( + IN USHORT ProtseqId + ) +/*++ + +Routine Description: + + Returns the unicode protseq give the protseqs tower id. + +Arguments: + + ProtseqId - Tower id of the protseq in question. + +Return Value: + + NULL if the id is invalid. + + non-NULL if the id is valid - note the pointer doesn't need to be freed. + +--*/ + +{ + ASSERT(ProtseqId); + + if (ProtseqId < PROTSEQ_IDS) + { + return(gaProtseqInfo[ProtseqId].pwstrProtseq); + } + return(0); +} + + +PWSTR +GetEndpoint( + IN USHORT ProtseqId + ) +/*++ + +Routine Description: + + Returns the well known endpoint associated with the protseq. + +Arguments: + + ProtseqId - the id (See GetProtseqId()) of the protseq in question. + +Return Value: + + 0 - Unknown/invalid id. + + !0 - The endpoint associated with the protseq. + note: should not be freed. + +--*/ +{ + ASSERT(ProtseqId); + + if (ProtseqId < PROTSEQ_IDS) + { + return(gaProtseqInfo[ProtseqId].pwstrEndpoint); + } + return(0); +} + + +USHORT +GetProtseqId( + IN PWSTR Protseq + ) +/*++ + +Routine Description: + + Returns the tower id for a protseq. + + This could be changed to a faster search, but remember that + eventually the table will NOT be static. (ie. we can't just + create a perfect hash based on the static table). + +Arguments: + + Protseq - a unicode protseq to lookup. It is assumed + to be non-null. + +Return Value: + + 0 - unknown/invalid protseq + non-zero - the id. + +--*/ +{ + int i; + ASSERT(Protseq); + + for(i = 1; i < PROTSEQ_IDS; i++) + { + if ( 0 != gaProtseqInfo[i].pwstrProtseq + && 0 == wcscmp(gaProtseqInfo[i].pwstrProtseq, Protseq)) + { + return(i); + } + } + return(0); +} + + +USHORT +GetProtseqIdAnsi( + IN PSTR pstrProtseq + ) +/*++ + +Routine Description: + + Returns the tower id for a protseq. + + This could be changed to a faster search, but remember that + eventually the table will NOT be static. (ie. we can't just + create a perfect hash based on the static table). + +Arguments: + + Protseq - an ansi (8 bit char) protseq to lookup. It is assumed + to be non-null. + +Return Value: + + 0 - unknown/invalid protseq + non-zero - the id. + +--*/ +{ + int i; + ASSERT(pstrProtseq); + + for(i = 1; i < PROTSEQ_IDS; i++) + { + if (0 != gaProtseqInfo[i].pwstrProtseq) + { + PWSTR pwstrProtseq = gaProtseqInfo[i].pwstrProtseq; + PSTR pstrT = pstrProtseq; + + while(*pstrT && *pwstrProtseq && *pstrT == *pwstrProtseq) + { + pstrT++; + pwstrProtseq++; + } + if (*pstrT == *pwstrProtseq) + { + return(i); + } + } + } + return(0); +} + + +RPC_STATUS +InitializeEndpointManager( + VOID + ) +/*++ + +Routine Description: + + Called when the dcom service starts. + + BUGBUG: Should read the protseqs, tower IDs and endpoints from the registry. + +Arguments: + + None + +Return Value: + + RPC_S_OUT_OF_MEMORY - if needed + + RPC_S_OUT_OF_RESOURCES - usually on registry failures. + +--*/ +{ + return(RPC_S_OK); +} + + +BOOL +IsLocal( + IN USHORT ProtseqId + ) +/*++ + +Routine Description: + + Determines if the protseq id is local-only. + (ncalrpc or mswmsg). + +Arguments: + + ProtseqId - The id of the protseq in question. + +Return Value: + + TRUE - if the protseq id is local-only + FALSE - if the protseq id invalid or available remotely. + +--*/ +{ + return(ProtseqId == 0x1 || ProtseqId == 0x10); +} + + +RPC_STATUS +DelayedUseProtseq( + IN USHORT id + ) +/*++ + +Routine Description: + + If the protseq is not being used its state is changed + so that a callto CompleteDelayedUseProtseqs() will actually + cause the server to listen to the protseq. + +Arguments: + + id - the id of the protseq you wish to listen to. + +Return Value: + + 0 - normally + + RPC_S_INVALID_RPC_PROTSEQ - if id is invalud. + +--*/ +{ + if (id < PROTSEQ_IDS) + { + if (gaProtseqInfo[id].pwstrProtseq != 0) + { + if (gaProtseqInfo[id].state == STOPPED) + gaProtseqInfo[id].state = START; + return(RPC_S_OK); + } + } + return(RPC_S_INVALID_RPC_PROTSEQ); +} + + +VOID +CompleteDelayedUseProtseqs( + VOID + ) +/*++ + +Routine Description: + + Start listening to any protseqs previously passed + to DelayedUseProtseq(). No errors are returned, + but informationals are printed on debug builds. + +Arguments: + + None + +Return Value: + + None + +--*/ +{ + USHORT i; + + for(i = 1; i < PROTSEQ_IDS; i++) + { + if (START == gaProtseqInfo[i].state) + { + RPC_STATUS status = UseProtseqIfNecessary(i); +#ifdef DEBUGRPC + if (RPC_S_OK == status) + ASSERT(gaProtseqInfo[i].state == STARTED); +#endif + } + } +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx new file mode 100644 index 000000000..890ae5e21 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx @@ -0,0 +1,269 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Table.cxx + +Abstract: + + Implementation of the CResolverHashTable and CTableElement. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-15-95 Bits 'n pieces + MarioGo 12-18-95 Changed from UUID to generic object keys + SatishT 02-12-96 Modified for use with shared memory + +--*/ + +#include<or.hxx> + +#if DBG + +void +CResolverHashTable::IsValid() +{ + IsGoodBasedPtr(_buckets); + + ASSERT(_fInitialized == TRUE || _fInitialized == FALSE); + ASSERT(!_fInitialized || _cBuckets > 0); + ASSERT(_cBuckets > 0 || _cElements == 0); + ASSERT(_cBuckets >=0 && _cBuckets < MAX_BUCKETS); + + if (_fInitialized) + { + for (USHORT i = 0; i < _cBuckets; i++) + { + _buckets[i].IsValid(); + } + } +} + +#endif + +ORSTATUS +CResolverHashTable::PrivAdd( // never called before Init() + IN CTableElement *pElement + ) +{ + VALIDATE_METHOD + + ORSTATUS status = OR_OK; + + ISearchKey& sk = *pElement; // auto conversion to ISearchKey + + DWORD hash = sk.Hash() % _cBuckets; + + ComDebOut((DEB_ITRACE, "Adding %x at hash = %d\n", + OR_OFFSET(pElement),hash)); + + _buckets[hash].Insert(status,pElement); + + _cElements++; + + return status; +} + + + +CResolverHashTable::CResolverHashTable(UINT start_size) +{ + ComDebOut((DEB_ITRACE, "Constructing CResolverHashTable Size = %d\n",start_size)); + + _cBuckets = start_size; + _cElements = 0; + _buckets = NULL; + _fInitialized = FALSE; + + VALIDATE_METHOD +} + + +ORSTATUS +CResolverHashTable::Init() +{ + ORSTATUS status; + + ASSERT(!_fInitialized); + + VALIDATE_METHOD + + NEW_OR_BASED_ARRAY(_buckets,CTableElementList,_cBuckets); + + if (NULL == _buckets) + { + status = OR_NOMEM; + } + else + { + status = OR_OK; + _fInitialized = TRUE; + } + + return status; +} + + +CResolverHashTable::~CResolverHashTable() +{ + RemoveAll(); +} + + +CTableElement * +CResolverHashTable::Lookup( + IN ISearchKey &id + ) +{ + ComDebOut((DEB_ITRACE, "Entering Lookup\n")); + + VALIDATE_METHOD + + if (!_fInitialized) return NULL; // nothing to look in + + DWORD hash = id.Hash(); + hash %= _cBuckets; + + return _buckets[hash].Find(id); +} + +ORSTATUS +CResolverHashTable::Add( + IN CTableElement *pElement + ) +{ + ComDebOut((DEB_ITRACE, "Entering Add for %x in %x\n", + OR_OFFSET(pElement),OR_OFFSET(this))); + + + VALIDATE_METHOD + + ORSTATUS status = OR_OK; + + if (!_fInitialized) status = Init(); // set up buckets + + if (status != OR_OK) return status; + + status = PrivAdd(pElement); // do the basic Add + + if (status != OR_OK) return status; + + if (_cElements > _cBuckets) // now see if the table is overpopulated + { + // Try to grow the table. If the allocation fails no need to worry, + // everything still works but might be a bit slower. + + CTableElementList OR_BASED * psll; + NEW_OR_BASED_ARRAY(psll,CTableElementList,_cBuckets * 2); + + + // The tricky part here is to avoid getting OR_NOMEM error while moving + // between tables. We do that by recycling the links in the old lists + + if (psll) + { + UINT i, uiBucketsOld = _cBuckets; + CTableElement *pte; + CTableElementList::Link *pLink; + CTableElementList OR_BASED *psllOld = _buckets; + + OrDbgDetailPrint(("OR: Growing table: %p\n", this)); + + // Change to the larger array of buckets. + _cBuckets *= 2; + _buckets = psll; + + // Move every element from the old table into the large table. + + for(i = 0; i < uiBucketsOld; i++) + { + while (pLink = psllOld[i].PopLink()) // uses specialized private operations + { // to avoid both memory allocation + // and reference counting problems + + ISearchKey& sk = *pLink->_pData; // auto conversion to ISearchKey + _buckets[sk.Hash() % _cBuckets].PushLink(pLink); + } + } + } + } + + ComDebOut((DEB_ITRACE, "Leaving Add\n")); + + return status; +} + +CTableElement * +CResolverHashTable::Remove( + IN ISearchKey &id + ) +/*++ + +Routine Description: + + Looks up and removes an element from the table. + +Arguments: + + id - The key to match the element to be removed + +Return Value: + + NULL - The element was not in the table + + non-NULL - A pointer to the element which was removed. + +--*/ + +{ + VALIDATE_METHOD + + if (!_fInitialized) return NULL; // nothing to remove + + DWORD hash = id.Hash() % _cBuckets; + + CTableElement *pTE = _buckets[hash].Remove(id); + + if (pTE) + { + _cElements--; + } + + return pTE; +} + + +void +CResolverHashTable::RemoveAll() +{ + VALIDATE_METHOD + + if (!_fInitialized) return; // nothing to remove + + ASSERT(_buckets); + DWORD _currentBucketIndex = 0; + CTableElement *pTE; + + while (_currentBucketIndex < _cBuckets) + { + while (pTE = _buckets[_currentBucketIndex].Pop()) + { + _cElements--; + } + + _currentBucketIndex++; + } + + ASSERT(_cElements==0); + + DELETE_OR_BASED_ARRAY(CTableElementList,_buckets,_cBuckets); + _buckets = NULL; + _fInitialized = FALSE; +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx new file mode 100644 index 000000000..9cede47f7 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx @@ -0,0 +1,297 @@ + +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + GenTable.hxx + +Abstract: + + Generic wrapper for a bucket hash class. + Used for ID, ID[2], ID[3] and string index tables. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 12-13-95 Pulled from uuid index hash table + MarioGo 12-18-95 Changed to use generic keys. + SatishT 03-07-96 Considerably altered for DCOM95 + +--*/ + +#ifndef __GENERIC_TABLE_HXX +#define __GENERIC_TABLE_HXX + +#if DBG +#define MAX_BUCKETS 0x10000 // for DBG validation checking only +#endif + + +struct ISearchKey +{ + virtual DWORD Hash() = 0; + virtual BOOL Compare(ISearchKey &tk) = 0; + + BOOL operator==(ISearchKey &tk) + { + return Compare(tk); + } + + BOOL operator!=(ISearchKey &tk) + { + return !Compare(tk); + } +}; + + +class CTableElement : public CReferencedObject +{ +public: + virtual operator ISearchKey&() = 0; +}; + + +// We don't use DEFINE_LIST here because CTableElement is an abstract class + +#define CTableElementList TCSafeLinkList<CTableElement> +#define CTableElementListIterator TCSafeLinkListIterator<CTableElement> + +/*++ + +Class Definition: + + CResolverHashTable + +Abstract: + + This is a simple hash table class. Items are kept in buckets reached by + hashing. Each bucket is a linked list object. The name is designed to + avoid a clash with the specialized CHashTable in ole32\com\dcomrem\hash.hxx, + with which we must coexist. + +--*/ + +class CResolverHashTable +{ +public: + +#if DBG + void IsValid(); + DECLARE_VALIDITY_CLASS(CResolverHashTable) +#endif + + CResolverHashTable(UINT start_size = 32 ); + + ~CResolverHashTable(); + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + ORSTATUS Add(CTableElement * element); + CTableElement *Lookup(ISearchKey &tk); + CTableElement *Remove(ISearchKey &tk); + void RemoveAll(); + DWORD Size() { return(_cElements); } + +protected: + + DWORD BucketSize() { return _cBuckets; } + +private: + + friend class CResolverHashTableIterator; + + ORSTATUS PrivAdd(CTableElement * element); + ORSTATUS Init(); + + DWORD _cBuckets; + DWORD _cElements; + BOOL _fInitialized; + CTableElementList OR_BASED *_buckets; +}; + + + + +/*++ + +Template Class Definition: + + TCResolverHashTable + +Abstract: + + The usual template wrapper for type safety. Data must be a subtype of + CTableElement. I wish I could express that constraint in the code! + +--*/ + +template <class Data> +class TCSafeResolverHashTable : private CResolverHashTable +{ + friend class TCSafeResolverHashTableIterator<Data>; + +public: + +#if DBG + void IsValid() + { + CResolverHashTable::IsValid(); + } +#endif // DBG + + TCSafeResolverHashTable(UINT start_size = 32 ) + : CResolverHashTable(start_size) + {} + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + ORSTATUS Add(Data * element) + { + return CResolverHashTable::Add(element); + } + + Data *Lookup(ISearchKey &tk) + { + return (Data *) CResolverHashTable::Lookup(tk); + } + + Data *Remove(ISearchKey &tk) + { + return (Data *) CResolverHashTable::Remove(tk); + } + + void RemoveAll() + { + CResolverHashTable::RemoveAll(); + } + + DWORD Size() + { + return CResolverHashTable::Size(); + } + + BOOL IsEmpty() + { + return Size() == 0; + } + +private: + + DWORD BucketSize() { return CResolverHashTable::BucketSize(); } +}; + + + +/*++ + +Class Definition: + + CResolverHashTableIterator + +Abstract: + + This is a simple iterator class for hash tables. + It is assumed that the table is static during iteration. + Note that the iterator performs no memory allocation. + +--*/ + +class CResolverHashTableIterator +{ +private: + + CResolverHashTable& _table; + + DWORD _currentBucketIndex; + + // iterator for the current bucket + CTableElementListIterator _BucketIter; + + void NextBucket(); // helper -- setup next bucket iterator + +public: + + CResolverHashTableIterator(CResolverHashTable& source) + : _table(source), _currentBucketIndex(0) + {} + + IDataItem * Next() + { + if (!_table._fInitialized) + { + return NULL; + } + + while ( + _BucketIter.Finished() + && (_currentBucketIndex < _table._cBuckets) + ) + { + _BucketIter.Init(_table._buckets[_currentBucketIndex]); + _currentBucketIndex++; + } + + return _BucketIter.Next(); + } +}; + + + +/*++ + +Template Class Definition: + + TCSafeResolverHashTableIterator + +Abstract: + + This is the usual template wrapper for CResolverHashTableIterator + for type safety. Data must be a subtype of CTableElement. + +--*/ + +template <class Data> +class TCSafeResolverHashTableIterator : private CResolverHashTableIterator +{ + +public: + + TCSafeResolverHashTableIterator(TCSafeResolverHashTable<Data>& source) + : CResolverHashTableIterator(source) + {} + + Data * Next() + { + return (Data *) CResolverHashTableIterator::Next(); + } +}; + + +#define DEFINE_TABLE(DATA) \ + typedef TCSafeResolverHashTable<DATA> DATA##Table; \ + typedef TCSafeResolverHashTableIterator<DATA> DATA##TableIterator; + + +#endif // __GENERIC_TABLE_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx new file mode 100644 index 000000000..b7cf2701e --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx @@ -0,0 +1,378 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: globals.cxx +// +// Contents: Implementation of Class used to encapsulate shared global +// data structures for DCOM95. +// +// History: 13-Feb-96 SatishT Created +// +//-------------------------------------------------------------------------- +#include <or.hxx> + + +// +// Helper function which initializes local DSA and string of protocol +// sequences, and as a side effect, starts all remote protocols +// + +static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc"; +static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols"; + +ORSTATUS +InitRemoteProtocols( + OUT PWSTR &pwstrProtseqs, + OUT DUALSTRINGARRAY * &pdsaProtseqs, + OUT USHORT &cRemoteProtseqs, + OUT USHORT * &aRemoteProtseqs + ) +{ + ORSTATUS status = OR_OK; + DUALSTRINGARRAY *pdsaPS = NULL; + pwstrProtseqs = NULL; + + DWORD dwType; + DWORD dwLenBuffer = InitialProtseqBufferLength; + HKEY hKey; + + status = + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + gpwstrProtocolsPath, + 0, + KEY_READ, + &hKey); + + if (status != ERROR_SUCCESS) + { + return status; + } + + do + { + OrMemFree(pwstrProtseqs); + pwstrProtseqs = (WCHAR*) OrMemAlloc(dwLenBuffer); + if (pwstrProtseqs) + { + status = RegQueryValueEx(hKey, + gpwstrProtocolsValue, + 0, + &dwType, + (PBYTE)pwstrProtseqs, + &dwLenBuffer + ); + } + else + { + return OR_NOMEM; // BUGBUG: is OR_NOMEM really likely here?? + } + } + while (status == ERROR_MORE_DATA); + + PWSTR pwstr = pwstrProtseqs; + + while(*pwstr) + { + USHORT id = GetProtseqId(pwstr); + + if ((0 != id) && (ID_NP != id) && !IsLocal(id)) + { + status = UseProtseqIfNecessary(id); + } + + pwstr = OrStringSearch(pwstr, 0) + 1; + } + + RPC_BINDING_VECTOR *pbv; + PWSTR pwstrT; + USHORT psaLen = 0; + DWORD i; + + + status = RpcServerInqBindings(&pbv); + + ASSERT(status == RPC_S_NO_BINDINGS || pbv != NULL); + + if (status == RPC_S_NO_BINDINGS) return status; + + PWSTR aBindings[MAX_PROTSEQ_IDS]; + PWSTR aAddresses [MAX_PROTSEQ_IDS]; + USHORT aProtseqs[MAX_PROTSEQ_IDS]; + + // Build array of protseqs id's and addresses we're listening to. + + for(i = 0; i < pbv->Count; i++) + { + PWSTR pwstrStringBinding; + + status = RpcBindingToStringBinding(pbv->BindingH[i], &pwstrStringBinding); + if (status != RPC_S_OK) + { + break; + } + + ASSERT(pwstrStringBinding); + + status = RpcStringBindingParse(pwstrStringBinding, + 0, + &pwstrT, + &aAddresses[i], + 0, + 0); + + if (status != RPC_S_OK) + { + break; + } + + aProtseqs[i] = GetProtseqId(pwstrT);; + aBindings[i] = pwstrStringBinding; + psaLen += OrStringLen(pwstrStringBinding) + 1; + cRemoteProtseqs++; + + status = RpcStringFree(&pwstrT); + ASSERT(status == RPC_S_OK && pwstrT == 0); + } + + status = RpcBindingVectorFree(&pbv); + ASSERT(pbv == 0 && status == RPC_S_OK); + + if (cRemoteProtseqs == 0) + { + // No remote bindings + psaLen = 1; + } + + // string bindings final null, authn and authz service and two final nulls + + psaLen += 1 + 2 + 2; + + pdsaPS = new (psaLen * sizeof(WCHAR)) DUALSTRINGARRAY; + + aRemoteProtseqs = (USHORT *) OrMemAlloc(sizeof(USHORT)*cRemoteProtseqs); + + if (pdsaPS == NULL || aRemoteProtseqs == NULL) + { + for ( i = 0; i < cRemoteProtseqs; i++ ) + { + status = RpcStringFree(&aBindings[i]); + ASSERT(status == RPC_S_OK); + } + + return OR_NOMEM; + } + + pdsaPS->wNumEntries = psaLen; + pdsaPS->wSecurityOffset = psaLen - 4; + pwstrT = pdsaPS->aStringArray; + + for ( i = 0; i < cRemoteProtseqs; i++ ) + { + OrStringCopy(pwstrT, aBindings[i]); + pwstrT += OrStringLen(aBindings[i]) + 1; + aRemoteProtseqs[i] = aProtseqs[i]; + status = RpcStringFree(&aBindings[i]); + ASSERT(status == RPC_S_OK); + } + + if (psaLen == 6) + { + // No remote bindings, put in first null. + pdsaPS->aStringArray[0] = 0; + pwstrT++; + } + + // Zero final terminator + *pwstrT = 0; + + // Security authn service + pwstrT++; + *pwstrT = RPC_C_AUTHN_WINNT; // BUGBUG: need fix for generality + + // Authz service, -1 means none // BUGBUG: -1 causes errors + pwstrT++; + *pwstrT = 0; + + // Final, final NULLS + pwstrT++; + pwstrT[0] = 0; + pwstrT[1] = 0; + + ASSERT(dsaValid(pdsaPS)); + + pdsaProtseqs = CompressStringArray(pdsaPS,TRUE); + delete pdsaPS; + + if (pdsaProtseqs == NULL) + { + return OR_NOMEM; + } + + ASSERT(dsaValid(pdsaProtseqs)); + return status; +} + + + +// +// Helper Macro for constructor below only +// + +#define AssignAndAdvance(Var,Type) \ + Type OR_BASED * *Var = (Type OR_BASED **) pb; \ + pb += sizeof(Type OR_BASED *); + + + +//+------------------------------------------------------------------------- +// +// Member: CSharedGlobals::CSharedGlobals +// +// Synopsis: Create table of globals for DCOM95 +// +// Arguments: [pwszName] - name for shared memory +// +// Algorithm: Create and map in shared memory for the table +// +// History: 13-Feb-96 SatishT Created +// +//-------------------------------------------------------------------------- +CSharedGlobals::CSharedGlobals(WCHAR *pwszName, ORSTATUS &status) +/*--- + + NOTE: This constructor uses the shared allocator. Objects of this class + should not be created before the shared allocator is initialized. + +---*/ +{ + BOOL fCreated; + + _hSm = CreateSharedFileMapping( + pwszName, + GLOBALS_TABLE_SIZE, + GLOBALS_TABLE_SIZE, + NULL, + NULL, + PAGE_READWRITE, + (void **) &_pb, + &fCreated + ); + + Win4Assert(_hSm && _pb && "CSharedGlobals create shared file mapping failed"); + + BYTE * pb = _pb; + + gpIdSequence = (LONG *) pb; + pb += sizeof(LONG); + + gpdwLastCrashedProcessCheckTime = (DWORD *) pb; + pb += sizeof(DWORD); + + gpNextThreadID = (DWORD *) pb; + pb += sizeof(DWORD); + + gpcRemoteProtseqs = (USHORT *) pb; + pb += sizeof(USHORT); + + AssignAndAdvance(DCOMProtseqIds,USHORT) // see macro above + AssignAndAdvance(DCOMProtseqs,WCHAR) + AssignAndAdvance(LocalDSA,DUALSTRINGARRAY) + AssignAndAdvance(LocalMid,CMid) + AssignAndAdvance(PingProcess,CProcess) + AssignAndAdvance(OidTable,COidTable) + AssignAndAdvance(OxidTable,COxidTable) + AssignAndAdvance(MidTable,CMidTable) + AssignAndAdvance(ProcessTable,CProcessTable) + + if (fCreated) // if we got here first, so create the tables + { + memset(_pb, 0, GLOBALS_TABLE_SIZE); + + // Initialize the sequence number for AllocateId, the last time crashed + // processes were detected and the thread ID sequence in shared memory + *gpIdSequence = 1; + + *gpdwLastCrashedProcessCheckTime = 0; + + *gpNextThreadID = 1; + + // I know this is paranoid but I have been bitten before .. + gpRemoteProtseqIds = NULL; + gpwstrProtseqs = NULL; + gpLocalDSA = NULL; + gpLocalMid = NULL; + gpPingProcess = NULL; + gpOxidTable = NULL; + gpOidTable = NULL; + gpMidTable = NULL; + gpProcessTable = NULL; + + // initialize remote protocol strings and + // the DSA bindings of local OR in shared memory + PWSTR pwstr; + DUALSTRINGARRAY *pdsa; + USHORT *aProtseqIds; + + InitRemoteProtocols(pwstr,pdsa,*gpcRemoteProtseqs,aProtseqIds); + + *DCOMProtseqIds = OR_BASED_POINTER(WCHAR,aProtseqIds); + *DCOMProtseqs = OR_BASED_POINTER(WCHAR,pwstr); + *LocalDSA = OR_BASED_POINTER(DUALSTRINGARRAY,pdsa); + + // initialize local Mid object in shared memory + NEW_OR_BASED(*LocalMid,CMid,(OR_FULL_POINTER(DUALSTRINGARRAY,*LocalDSA),status,0)); + if (status != OR_OK) + { + DELETE_OR_BASED(CMid,*LocalMid); + *LocalMid = NULL; + } + + // initialize ping thread's process object in shared memory + NEW_OR_BASED(*PingProcess,CProcess,(0)); + + // Assume 16 exporting processes/threads. + NEW_OR_BASED(*OxidTable,COxidTable,(OXID_TABLE_SIZE)); + + // Assume 11 exported OIDs per process/thread. + NEW_OR_BASED(*OidTable,COidTable,(OID_TABLE_SIZE)); + + // Assume 16 machine locations for OXIDs. + NEW_OR_BASED(*MidTable,CMidTable,(MID_TABLE_SIZE)); + + // Assume 16 simultaneouly active local processes. + NEW_OR_BASED(*ProcessTable,CProcessTable,(PROCESS_TABLE_SIZE)); + + // Add local CMid object to global shared table + if (*LocalMid && *MidTable) + status = (*MidTable)->Add(OR_FULL_POINTER(CMid,*LocalMid)); + } + + gpRemoteProtseqIds = OR_FULL_POINTER(USHORT,*DCOMProtseqIds); + gpwstrProtseqs = OR_FULL_POINTER(WCHAR,*DCOMProtseqs); + gpLocalDSA = OR_FULL_POINTER(DUALSTRINGARRAY,*LocalDSA); + gpLocalMid = OR_FULL_POINTER(CMid,*LocalMid); + gpPingProcess = OR_FULL_POINTER(CProcess,*PingProcess); + gpOxidTable = OR_FULL_POINTER(COxidTable,*OxidTable); + gpOidTable = OR_FULL_POINTER(COidTable,*OidTable); + gpMidTable = OR_FULL_POINTER(CMidTable,*MidTable); + gpProcessTable = OR_FULL_POINTER(CProcessTable,*ProcessTable); +} + + +#ifndef _CHICAGO_ + +/* MIDL allocate and free */ + +void __RPC_FAR * __RPC_API midl_user_allocate(size_t len) +{ + return(PrivMemAlloc(len)); +} + +void __RPC_API midl_user_free(void __RPC_FAR * ptr) +{ + PrivMemFree(ptr); +} + +#endif // _CHICAGO_ diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx new file mode 100644 index 000000000..daa0ce419 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx @@ -0,0 +1,90 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: globals.hxx +// +// Contents: Class used to encapsulate shared global data structures for DCOM95. +// +// Functions: +// +// History: 13-Feb-96 SatishT Created +// +//-------------------------------------------------------------------------- +#ifndef __GLOBALS_HXX__ +#define __GLOBALS_HXX__ + +#define GLOBALS_TABLE_SIZE \ + ( \ + sizeof(USHORT) + \ + sizeof(LONG) + \ + 2 * sizeof(DWORD) + \ + 9 * sizeof(void OR_BASED *) \ + ) + + +//+------------------------------------------------------------------------- +// +// Class: CSharedGlobals +// +// Purpose: Initializing access to shared global data +// +// Interface: InitOK - whether initialization succeeded. +// +// History: 13-Feb-96 SatishT Created +// +// Notes: The constructor for this class uses the shared allocator. Objects of this +// class should not be created before the shared allocator is initialized. +// +// +//-------------------------------------------------------------------------- +class CSharedGlobals +{ +public: + + CSharedGlobals(WCHAR *pwszName, ORSTATUS &status); + + ~CSharedGlobals(); + + BOOL InitOK(void); + + /* add public members for shared tables here */ + +private: + + HANDLE _hSm; + BYTE * _pb; +}; + +//+------------------------------------------------------------------------- +// +// Member: CSharedGlobals::~CSharedGlobals +// +// Synopsis: Clean up hint table object +// +// History: 20-Jan-95 Ricksa Created +// +//-------------------------------------------------------------------------- +inline CSharedGlobals::~CSharedGlobals(void) +{ + CloseSharedFileMapping(_hSm, _pb); +} + + +//+------------------------------------------------------------------------- +// +// Member: CSharedGlobals::InitOK +// +// Synopsis: Whether initialization worked +// +// History: 20-Jan-95 Ricksa Created +// +//-------------------------------------------------------------------------- +inline BOOL CSharedGlobals::InitOK(void) +{ + return _hSm != NULL; +} + + +#endif // __GLOBALS_HXX__ diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx new file mode 100644 index 000000000..25a455a2c --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx @@ -0,0 +1,346 @@ +#include <or.hxx> + + error_status_t Connect( + OUT HPROCESS *pProcess, + OUT ULONG *pdwTimeoutInSeconds, + OUT DUALSTRINGARRAY **ppdsaOrBindings, + OUT MID *pLocalMid, + IN long cIdsToReserve, + OUT ID *pidReservedBase, + OUT ULONG *pfConnectFlags, + OUT DWORD *pAuthnLevel, + OUT DWORD *pImpLevel, + OUT DWORD *pcServerSvc, + OUT USHORT **aServerSvc, + OUT DWORD *pcClientSvc, + OUT USHORT **aClientSvc, + OUT DWORD *pThreadID) + { + + ORSTATUS status; + + status = ConnectDCOM( + pProcess, + pdwTimeoutInSeconds, + pLocalMid, + pfConnectFlags, + pAuthnLevel, + pImpLevel, + pcServerSvc, + aServerSvc, + pcClientSvc, + aClientSvc, + pThreadID + ); + + if (status == OR_OK) + { + status = AllocateReservedIds( + cIdsToReserve, + pidReservedBase + ); + } + + if (status == OR_OK) + { + *ppdsaOrBindings = (DUALSTRINGARRAY *) PrivMemAlloc( + gpLocalDSA->wNumEntries * sizeof(WCHAR) + + sizeof(DUALSTRINGARRAY) ); + + if (*ppdsaOrBindings) + { + dsaCopy(*ppdsaOrBindings, gpLocalDSA); + } + else + { + status = OR_NOMEM; + } + } + + return status; +} + + + error_status_t ClientResolveOXID( + IN HPROCESS phProcess, + IN OXID *poxidServer, + IN DUALSTRINGARRAY *pssaServerObjectResolverBindings, + IN long fApartment, + OUT OXID_INFO *poxidInfo, + OUT MID *pLocalMidOfRemote) + { + return GetOXID( + phProcess, + *poxidServer, + pssaServerObjectResolverBindings, + fApartment, + 0, // wProtseqId not specified + *poxidInfo, + *pLocalMidOfRemote + ); + } + + + + error_status_t ServerAllocateOXIDAndOIDs( + IN HPROCESS hProcess, + OUT OXID *poxidServer, + IN long fApartment, + IN unsigned long cOids, + OUT OID aOid[ ], + OUT unsigned long *pcOidsAllocated, + IN OXID_INFO *pOxidInfo, + IN DUALSTRINGARRAY *pdsaStringBindings, + IN DUALSTRINGARRAY *pdsaSecurityBindings) + { + ComDebOut((DEB_OXID, "Calling ServerAllocateOXIDAndOIDs\n")); + + DUALSTRINGARRAY *pdsaMergedBindings; + + ORSTATUS status = MergeBindings( + pdsaStringBindings, + pdsaSecurityBindings, + &pdsaMergedBindings + ); + + if (status != OR_OK) return status; + + status = ServerAllocateOXID( + hProcess, + fApartment, + pOxidInfo, + pdsaMergedBindings, + *poxidServer + ); + + if (status == OR_OK) + { + ComDebOut((DEB_OXID, "Calling ServerAllocateOIDs\n")); + + status = ServerAllocateOIDs( + hProcess, + poxidServer, + cOids, + aOid, + pcOidsAllocated + ); + } + else + { + ComDebOut((DEB_OXID, "Not Calling ServerAllocateOIDs, status = %d\n", + status)); + } + + return status; + } + + + + error_status_t ServerAllocateOIDs( + IN HPROCESS hProcess, + IN OXID *poxidServer, + IN unsigned long cOids, + OUT OID aOid[ ], + OUT unsigned long *pcOidsAllocated) + { + ComDebOut((DEB_ITRACE, "Entering ServerAllocateOIDs\n")); + + ORSTATUS status; + + *pcOidsAllocated = 0; + + for (ULONG i = 0; i < cOids; i++) + { + status = ServerAllocateOID( + hProcess, + *poxidServer, + aOid[i] + ); + + if (status != OR_OK) + { + *pcOidsAllocated = i; + break; + } + else + { + (*pcOidsAllocated)++; + } + } + + return status; + } + + + + error_status_t ServerFreeOXIDAndOIDs( + IN HPROCESS hProcess, + IN OXID oxidServer, + IN unsigned long cOids, + IN OID aOids[ ]) + { + return ServerFreeOXID( + hProcess, + oxidServer, + cOids, + aOids + ); + } + + + + +VOID CALLBACK RundownTimerProc( + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime // current system time + ) +{ + return; + + if (idEvent != IDT_DCOM_RUNDOWN) return; // shouldn't happen -- this is only + // used as callback for one timer + + // find the OXID for this thread + + COleTls tls; + + ASSERT(((OXIDEntry *)tls->pOXIDEntry)->dwTid == GetCurrentThreadId()); + ASSERT(((OXIDEntry *)tls->pOXIDEntry)->dwPid == GetCurrentProcessId()); + + MOXID Moxid = ((OXIDEntry *)tls->pOXIDEntry)->moxid; + + OXID Oxid; + MID Mid; + + OXIDFromMOXID(Moxid,&Oxid); + MIDFromMOXID(Moxid,&Mid); + + CProtectSharedMemory protector; // locks through rest of lexical scope + + COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid, Mid)); + + ASSERT(pOxid); + + ComDebOut((DEB_OXID, "Attempting Rundown in apartment OXID = %08x PID = %d\n", + Oxid,GetCurrentProcessId())); + + // find the RemUnk for this OXID -- we want only the IRundown interface + + IRundown *pRemUnk = tls->pRemoteUnk; + + // If there is no RemUnk, nothing is marshalled, so forget about rundown + if (!pRemUnk) return; + + ComDebOut((DEB_OXID, "There is a RemUnk for apartment OXID = %08x PID = %d\n", + Oxid,GetCurrentProcessId())); + + // go and check your OIDs here + + pOxid->RundownOidsIfNecessary(pRemUnk); +} + + +DWORD _stdcall +RundownThread(void *self) +{ + return 0; + + DWORD dwLoopCount = 0; + + COxid *pSelf = (COxid*) self; // store away "this" pointer + + while (TRUE) + { + ::Sleep(RUNDOWN_TIMER_INTERVAL); // BUGBUG: use Sleep() from CTime? + + dwLoopCount++; + + ComDebOut((DEB_OXID, "Attempting Rundown in PID = %d\n", + GetCurrentProcessId())); + + CProtectSharedMemory protector; // locks through rest of lexical scope + + IRundown *pRemUnk = gpMTARemoteUnknown; + + // If there is no RemUnk, nothing is marshalled, so forget about rundown + if (!pRemUnk) return OR_OK; + + ComDebOut((DEB_OXID, "There is a RemUnk for free OXID = %08x PID = %d\n", + pSelf->GetOXID(),GetCurrentProcessId())); + + ASSERT(!IsBadWritePtr(pRemUnk,sizeof(CRemoteUnknown))); + + pSelf->RundownOidsIfNecessary(pRemUnk); + } + + return OR_OK; +} + + +DWORD _stdcall +PingThread(void) // BUGBUG: need another thread to watch over this one? +{ + return 0; + + while (TRUE) + { + Sleep(BasePingInterval); + + { + CProtectSharedMemory protector; // locks through rest of scope except where + // temporarily released + + ORSTATUS status; + + // First do rundown detection -- this may cause deletes from ping sets + + COxidTableIterator OxidIter(gpPingProcess->_MyOxids); + + for (COxid *pOxid = OxidIter.Next(); pOxid != NULL; pOxid = OxidIter.Next()) + { + pOxid->RundownOidsIfNecessary(NULL); // No IRundown param needed + } + + // Then do pinging + + CMidTableIterator MidIter(*gpMidTable); + + for (CMid *pMid = MidIter.Next(); pMid != NULL; pMid = MidIter.Next()) + { + if (pMid != gpLocalMid) + { + status = pMid->PingServer(); + } + } + } + } + + return OR_OK; +} + + +error_status_t +ResolveClientOXID( + handle_t hClient, + void *hProcess, + OXID *poxidServer, + DUALSTRINGARRAY *pdsaServerBindings, + LONG fApartment, + USHORT wProtseqId, + OXID_INFO *poxidInfo, + MID *pDestinationMid + ) +{ + return GetOXID( + (CProcess*)hProcess, + *poxidServer, + pdsaServerBindings, + fApartment, + wProtseqId, + *poxidInfo, + *pDestinationMid + ); +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx new file mode 100644 index 000000000..715c38a64 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx @@ -0,0 +1,173 @@ + +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + linklist.cxx + +Abstract: + + This module contains definitions of non inline member functions for the + basic implementation class CLinkList. + +Author: + + Satish Thatte (SatishT) 08/16/95 Created all the code below except where + otherwise indicated. + +--*/ + +#include <or.hxx> + + +USHORT +CLinkList::Size() +{ + USHORT result = 0; + + for (Link OR_BASED *pL = _pLnkFirst; pL != NULL; pL = pL->_pNext) + { + result++; + } + + return result; +} + + + +void +CLinkList::Insert(ORSTATUS& status, IDataItem * pData) +{ + ASSERT(pData != NULL); // do not allow inssertion of NULL pointers + + status = OR_OK; + + NEW_OR_BASED( + _pLnkFirst, + Link, + (OR_BASED_POINTER(IDataItem,pData), _pLnkFirst) + ); + + if (!_pLnkFirst) + { + status = OR_NOMEM; + } + else + { + pData->Reference(); + } +} + + +void +CLinkList::Clear() { // deletes all links but not the data + + Link OR_BASED * pLnkCurr = _pLnkFirst; + + while (pLnkCurr) + { + Link OR_BASED * pLnkDel = pLnkCurr; + pLnkCurr = pLnkCurr->_pNext; + pLnkDel->_pData->Release(); + DELETE_OR_BASED(Link,pLnkDel); + } + + _pLnkFirst = NULL; +} + + +IDataItem* +CLinkList::Pop() + +/*++ +Routine Description: + + Delete first item in the CLinkList and return it + +--*/ + +{ + if (!_pLnkFirst) return NULL; + + IDataItem* pResult = OR_FULL_POINTER(IDataItem,_pLnkFirst->_pData); + Link OR_BASED * oldFirst = _pLnkFirst; + _pLnkFirst = _pLnkFirst->_pNext; + DELETE_OR_BASED(Link,oldFirst); + + pResult->Release(); + return pResult; +} + +IDataItem * +CLinkList::Remove(ISearchKey& di) + +/*++ +Routine Description: + + Remove the specified item and return it. + +--*/ + +{ + if (!_pLnkFirst) return NULL; // empty list + + if (di == *OR_FULL_POINTER(IDataItem,(_pLnkFirst->_pData))) // Remove first item + { + return Pop(); + } + + Link OR_BASED * pLnkPrev = _pLnkFirst, + OR_BASED * pLnkCurr = _pLnkFirst->_pNext; + + while (pLnkCurr && di != (*OR_FULL_POINTER(IDataItem,(pLnkCurr->_pData)))) + { + pLnkPrev = pLnkCurr; + pLnkCurr = pLnkCurr->_pNext; + } + + if (!pLnkCurr) return NULL; // not found + + /* pLnkCurr contains the item to be removed and it is not the only + item in the list since it is not the first item */ + + pLnkPrev->_pNext = pLnkCurr->_pNext; + + IDataItem * pResult = OR_FULL_POINTER(IDataItem,pLnkCurr->_pData); + DELETE_OR_BASED(Link,pLnkCurr); + + pResult->Release(); + return pResult; +} + + +IDataItem* +CLinkList::Find(ISearchKey& di) // item to Find + + +/*++ +Routine Description: + + Unlike Remove, this method is designed to use a client-supplied + comparison function instead of pointer equality. The comparison + function is expected to behave like strcmp (returning <0 is less, + 0 if equal and >0 if greater). + +--*/ + +{ + if (!_pLnkFirst) return NULL; // empty list + + Link OR_BASED * pLnkCurr = _pLnkFirst; + + while (pLnkCurr && di != (*OR_FULL_POINTER(IDataItem,(pLnkCurr->_pData)))) + pLnkCurr = pLnkCurr->_pNext; + + if (!pLnkCurr) return NULL; // not found + else return OR_FULL_POINTER(IDataItem,pLnkCurr->_pData); +} + + + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx new file mode 100644 index 000000000..ba937dd88 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx @@ -0,0 +1,389 @@ + +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + linklist.hxx + +Abstract: + + This module contains definitions of class CLinkList, and templates derived + from it for type safety.Multithreading safety is assumed to be enforced + by external locking. + +Author: + + Satish Thatte (SatishT) 03/12/96 Created all the code below except where + otherwise indicated. + + +--*/ + + + +#ifndef __LINKLIST_HXX_ +#define __LINKLIST_HXX_ + +#include <or.hxx> + +// For the moment, we only permit linked lists of hash table items. +// This may be restructured in future. + +struct ISearchKey; +class CTableElement; + +typedef CTableElement IDataItem; + + +/*++ + +Class Definition: + + CLinkList + +Abstract: + + This is a simple linked list class. It has a private Link class. + +--*/ + + +class CLinkList +{ + + friend class CLinkListIterator; + + protected: + + struct Link + { + Link OR_BASED * _pNext; + IDataItem OR_BASED * _pData; + +#if DBG + void IsValid() + { + IsGoodBasedPtr(_pNext); + //IsGoodBasedPtr(_pData); + if (_pNext) _pNext->IsValid(); + } + + DECLARE_VALIDITY_CLASS(CLinkList) +#endif + + Link(IDataItem OR_BASED * a, Link OR_BASED * n); + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + }; + + Link OR_BASED * _pLnkFirst; + + // two protected functions for specialized use when reshuffling + // lists -- among other things, reference counts are not changed + // since the reference is deemed to be held by the link + + Link * PopLink() + { + Link * pResult = OR_FULL_POINTER(Link,_pLnkFirst); + + if (pResult != NULL) + { + _pLnkFirst = _pLnkFirst->_pNext; + pResult->_pNext = NULL; + } + + return pResult; + } + + void + PushLink(Link * pLink) + { + ASSERT(pLink != NULL); + + pLink->_pNext = _pLnkFirst; + _pLnkFirst = OR_BASED_POINTER(Link,pLink); + } + + public: + +#if DBG + void IsValid() + { + IsGoodBasedPtr(_pLnkFirst); + if (_pLnkFirst) _pLnkFirst->IsValid(); + } + + DECLARE_VALIDITY_CLASS(CLinkList) +#endif + + CLinkList() + { + _pLnkFirst = NULL; + } + + + ~CLinkList() + { + Clear(); + } + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + // Is there anything in this list? + + BOOL IsEmpty(); + + // Insert at the beginning + + USHORT Size(); + + void Insert(ORSTATUS& status, IDataItem * pData); + + // Remove first item and return it + + IDataItem * Pop(); + + // Remove the specified item and return it + + IDataItem * Remove(ISearchKey&); + + // Find the specified item and return it + + IDataItem * Find(ISearchKey&); + + // delete all links, but not the data items + + void Clear(); +}; + + +/*++ + +Class Definition: + + CLinkListIterator + +Abstract: + + An iterator class for traversing a CLinkList. + +--*/ + + +class CLinkListIterator { + + CLinkList::Link OR_BASED * _pIter; // the current link + + public: + + CLinkListIterator() : _pIter(NULL) {} + + void Init(CLinkList& source); + + IDataItem * Next(); // advance the iterator and return _pNext IDataItem + + BOOL Finished(); // anything further coming? +}; + + + +/*++ + +Template Class Definition: + + TCSafeLinkList + +Abstract: + + The template TCSafeLinkList make it easy to produce "type safe" incarnations of + the CLinkList classe, avoiding the use of casts in client code. + + Note that Data must be a subtype of IDataItem. + +--*/ + +template <class Data> +class TCSafeLinkList : private CLinkList +{ + + friend class TCSafeLinkListIterator<Data>; + friend class CResolverHashTable; + + public: + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + void IsValid() + { + CLinkList::IsValid(); + } + + + BOOL IsEmpty() + { + return CLinkList::IsEmpty(); + } + + USHORT Size() + { + return CLinkList::Size(); + } + + void Insert(ORSTATUS& status, Data * pData) + { + CLinkList::Insert(status, pData); + } + + Data * Pop() + { + return (Data *) CLinkList::Pop(); + } + + Data * Remove(ISearchKey& sk) + { + return (Data *) CLinkList::Remove(sk); + } + + Data * Find(ISearchKey& sk) + { + return (Data *) CLinkList::Find(sk); + } + + void Clear() + { + CLinkList::Clear(); + } + + void Transfer(TCSafeLinkList& target) + { + target._pLnkFirst = _pLnkFirst; + _pLnkFirst = NULL; + } +}; + + + +/*++ + +Template Class Definition: + + TCSafeLinkListIterator + +Abstract: + + The iterator for TCSafeLinkLists. + +--*/ + +template <class Data> +class TCSafeLinkListIterator : private CLinkListIterator { + + public: + + void Init(TCSafeLinkList<Data>& l) + { + CLinkListIterator::Init(l); + } + + Data * Next() + { + return (Data *) CLinkListIterator::Next(); + } + + BOOL Finished() + { + return CLinkListIterator::Finished(); + } + +}; + + +#define DEFINE_LIST(DATA) \ + typedef TCSafeLinkList<DATA> DATA##List; \ + typedef TCSafeLinkListIterator<DATA> DATA##ListIterator; + + + +// +// Inline methods for CLinkList +// + +inline +CLinkList::Link::Link(IDataItem OR_BASED * a, Link OR_BASED * n) +{ + _pData = a; + _pNext = n; +} + + + +inline +BOOL +CLinkList::IsEmpty() +{ + return _pLnkFirst == NULL; +} + + +// +// Inline methods for CLinkListIterator +// + + +inline +void +CLinkListIterator::Init(CLinkList& source) +{ + _pIter = source._pLnkFirst; +} + + + +inline +IDataItem* +CLinkListIterator::Next() { // advance the iterator and return _pNext IDataItem + + if (!_pIter) return NULL; + + IDataItem* result = OR_FULL_POINTER(IDataItem,_pIter->_pData); + _pIter = _pIter->_pNext; + + return result; +} + +inline +BOOL +CLinkListIterator::Finished() +{ + return _pIter == NULL; +} + + +#endif // __LINKLIST_HXX_ diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx new file mode 100644 index 000000000..1391a4e85 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx @@ -0,0 +1,766 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Manager.cxx + +Abstract: + + InProc OR interface + +Author: + + Satish Thatte [SatishT] Feb-07-1996 + +Revision Hist: + + SatishT 02-07-96 Created + +--*/ + + +#include <or.hxx> + + +// +// Manager (server-side) calls to the local OR interface. lclor.idl +// + +error_status_t +ConnectDCOM( + IN OUT HPROCESS *phProcess, + OUT ULONG *pdwTimeoutInSeconds, + OUT MID *pLocalMid, + OUT ULONG *pfConnectFlags, + OUT DWORD *pAuthnLevel, + OUT DWORD *pImpLevel, + OUT DWORD *pcServerSvc, + OUT USHORT **aServerSvc, + OUT DWORD *pcClientSvc, + OUT USHORT **aClientSvc, + OUT DWORD *pThreadID + ) +{ + ORSTATUS status = OR_OK; + CProcess *hProcess; + + StartDCOM(); + + *pdwTimeoutInSeconds = BaseTimeoutInterval; + *pLocalMid = gLocalMID; + + // Fill in security parameters. + + *pfConnectFlags = 0; + + if (s_fEnableDCOM == FALSE) *pfConnectFlags |= CONNECT_DISABLEDCOM; + if (s_fMutualAuth) *pfConnectFlags |= CONNECT_MUTUALAUTH; + if (s_fSecureRefs) *pfConnectFlags |= CONNECT_SECUREREF; + + *pAuthnLevel = s_lAuthnLevel; + *pImpLevel = s_lImpLevel; + *pcServerSvc = s_cServerSvc; + *aServerSvc = CopyArray(s_cServerSvc,s_aServerSvc,&status); + *pcClientSvc = s_cClientSvc; + *aClientSvc = CopyArray(s_cClientSvc,s_aClientSvc,&status); + + if (status != OR_OK) return status; + + CProtectSharedMemory protector; // locks through rest of lexical scope + + *pThreadID = (*gpNextThreadID)++; + + hProcess = new CProcess((long) *phProcess); // BUGBUG: this is a temp ID + // coming from bridge.cxx + + if (hProcess) + { + gpProcess = *phProcess = hProcess; + gpProcessTable->Add(hProcess); // BUGBUG: and rundown an old process, + // if there is one, with the same _processID + } + else + { + status = OR_NOMEM; + } + + OrDbgDetailPrint(("OR: Client connected\n")); + + return(status); +} + + +error_status_t Disconnect( + IN OUT HPROCESS *phProcess + ) +{ + // ASSERT(*phProcess!=NULL); // BUGBUG: the right thing to do + if (*phProcess == NULL) return OR_OK; + + CProcess *hProcess = *phProcess; + + CProtectSharedMemory protector; // locks through rest of lexical scope + + hProcess->Rundown(); + gpProcessTable->Remove(*hProcess); + *phProcess = NULL; + DCOM_Started = FALSE; + return OR_OK; +} + + + +error_status_t +AllocateReservedIds( + IN LONG cIdsToReserve, + OUT ID *pidReservedBase + ) +/*++ + +Routine Description: + + Called by local clients to reserve a range of IDs which will + not conflict with any other local IDs. + +Arguments: + + cIdsToReserve - Number of IDs to reserve. + + pidReservedBase - Starting value of the reserved IDs. The + lower DWORD of this can be increatmented to generate + cIdsToReserve unique IDs. + +Return Value: + + OR_OK + +--*/ +{ + UINT type; + + if (cIdsToReserve > 10 || cIdsToReserve < 0) + { + cIdsToReserve = 10; + } + + CProtectSharedMemory protector; // locks through rest of lexical scope + + *pidReservedBase = AllocateId(cIdsToReserve); + return(OR_OK); +} + + +error_status_t +GetOXID( + IN HPROCESS hProcess, + IN OXID Oxid, + IN DUALSTRINGARRAY *pdsaServerObjectResolverBindings, + IN long fApartment, + IN USHORT wProtseqId, + OUT OXID_INFO& OxidInfo, + OUT MID &Mid + ) +/*++ + +Routine Description: + + Discovers the OXID_INFO for an oxid. Will find local + OXIDs without any help from resolver process. + + It needs OR bindings in order to resolve remote OXIDs. + REVIEW: Should the resolver process be involved in this? + +Arguments: + + hProcess - The context handle of the process. + + Oxid - The OXID (a uuid) to resolve. + + pdsaServerObjectResolverBindings - Compressed string bindings to + the OR on the server's machine. + + fApartment - non-zero if the client is aparment model. + + OxidInfo - If successful this will contain information about the oxid and + an expanded string binding to the server oxid's process. + + Mid - The machine ID assigned locally for the remote machine. + This is obviously meaningful only for remote OXIDs. + +Return Value: + + OR_NOMEM - Common. + + OR_BADOXID - Unable to resolve it. + + OR_OK - Success. + +--*/ +{ + ComDebOut((DEB_OXID, "ResolveClientOXID OXID = %08x\n",Oxid)); + + COxid *pOxid; + CMid *pMid; + ORSTATUS status = OR_OK; + BOOL fNewMID = FALSE; + + if (wProtseqId == 0) // Normal (non SCM) call + { + // In case of failure, zero out param pointers. + OxidInfo.psa = NULL; + } + + if (!pdsaServerObjectResolverBindings) + pdsaServerObjectResolverBindings = gpLocalDSA; + + ASSERT(dsaValid(pdsaServerObjectResolverBindings)); + + CProtectSharedMemory protector; // locks through rest of lexical scope + +#if DBG + if (hProcess) hProcess->IsValid(); // don't validate for fake SCM calls +#endif + + if (dsaCompare(gpLocalDSA,pdsaServerObjectResolverBindings)) // local OXID + { + pMid = gpLocalMid; + } + else + { + // Attempt to lookup MID + + // CMidKey makes a copy of the bindings to maintain validity + + CMidKey midkey(pdsaServerObjectResolverBindings,TRUE,status); + + if (status != OR_OK) return status; + + pMid = gpMidTable->Lookup(midkey); + + if (NULL == pMid) + { + pMid = new(pdsaServerObjectResolverBindings->wNumEntries * sizeof(WCHAR)) + CMid(pdsaServerObjectResolverBindings, status, wProtseqId); + + // We initialize local MID autologically, + // therefore this has to be a remote MID + + if (pMid && status == OR_OK) + { + status = gpMidTable->Add(pMid); + if (status != OR_OK) + { + delete pMid; + return status; + } + + fNewMID = TRUE; + } + else + { + return (status == OR_OK) ? OR_NOMEM : status; + } + } + } + + ASSERT(pMid); // otherwise we would have returned by now + + Mid = pMid->GetMID(); + + pOxid = gpOxidTable->Lookup(CId2Key(Oxid, Mid)); + + if (pMid->IsLocal()) + { + ASSERT(!fNewMID); + + if (pOxid) + { + return pOxid->GetInfo(&OxidInfo); + } + else // local OXIDs should be registered by server + { + return OR_BADOXID; + } + } + + if (NULL == pOxid) + { + // Need to allocate the OXID. First step is to resolve it remotely. + + if ( OxidInfo.psa == NULL ) // genuine resolve request rather + // than a phoney one from the SCM + { + status = pMid->ResolveRemoteOxid( // This op will also replace the + Oxid, // psa with one in shared memory + &OxidInfo + ); + + wProtseqId = pMid->ProtseqOfServer(); + } + + ASSERT( (status != OR_OK) || (OxidInfo.psa != NULL) ); + + if (status == OR_OK) + { + DUALSTRINGARRAY *pdsaT = dsaSMCopy(OxidInfo.psa); + + if (!pdsaT) + { + return OR_NOMEM; + } + + MIDL_user_free(OxidInfo.psa); // free the original and replace + OxidInfo.psa = pdsaT; // with shared memory compressed copy + + pOxid = new COxid( + Oxid, + pMid, + wProtseqId, + OxidInfo + ); + + // remote OXID belongs to ping process .. + + if ((NULL != pOxid) && (gpPingProcess->OwnOxid(pOxid) == OR_OK)) + { + status = gpOxidTable->Add(pOxid); + } + else + { + OrMemFree(OxidInfo.psa); + delete pOxid; + return status; + } + } + else + { + MIDL_user_free(OxidInfo.psa); + return OR_BADOXID; + } + } + + ASSERT( (status == OR_OK) && pOxid ); + + return pOxid->GetInfo(&OxidInfo); +} + + +error_status_t +ClientAddOID( + IN HPROCESS hProcess, + IN OID Oid, + IN OXID Oxid, + IN MID Mid + ) + +/*++ + +Routine Description: + + Updates the set of OIDs in use by a process. + + +Arguments: + + hProcess - Context handle for the process. + + Oid - OID to add. + + Oxid - OXID to which OID belongs. + + Mid - MID for location of OXID server. + +Return Value: + + OR_OK - All updates completed ok. + + OR_BADOXID - The Oxid was not found + + OR_BADOID - The Oid could not be created or found + +Notes: + + Unlike the NT resolver, there is no possibility that the Oxid + is not in the gpOxidTable (since client and server Oxid objects + are in the same table). + +--*/ +{ + ComDebOut((DEB_OXID, "ClientAddOID\nOID = %08x\nOXID = %08x\nMID = %08x\n", + Oid,Oxid,Mid)); + + ORSTATUS status = OR_OK; + + // Lookup up the oxid owning this new oid. + + COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,Mid)); + + if (NULL == pOxid) + { + return OR_BADOXID; + } + + CProtectSharedMemory protector; // locks through rest of lexical scope + +#if DBG + hProcess->IsValid(); +#endif + + CMid *pMid = pOxid->GetMid(); + + // Find or create the oid. + + COid *pOid = gpOidTable->Lookup(CId2Key(Oid,Mid)); + + if (NULL == pOid) + { + ASSERT(!pMid->IsLocal()); // Local OID should be registered by server + + pOid = new COid(Oid,pOxid); + + if (NULL == pOid) + { + return OR_NOMEM; + } + + status = gpOidTable->Add(pOid); + if (status != OR_OK) + { + delete pOid; + return status; + } + + status = pMid->AddClientOid(pOid); + } + + if (status == OR_OK) status = hProcess->AddOid(pOid); + + return status; +} + + +error_status_t +ClientDropOID( + IN HPROCESS hProcess, + IN OID Oid, + IN MID Mid + ) + +/*++ + +Routine Description: + + Updates the set of remote OIDs in use by a process. + + +Arguments: + + hProcess - Context handle for the process. + + Oid - OID to be removed. + + Mid - MID to which Oid belongs. + +Return Value: + + OR_OK - All updates completed ok. + + OR_BADOID - The Oid could not be found + + +--*/ +{ + ComDebOut((DEB_OXID, "ClientDropOID\nOID = %08x\nMID = %08x\n", + Oid,Mid)); + + CProtectSharedMemory protector; // locks through rest of lexical scope + +#if DBG + hProcess->IsValid(); +#endif + + COid * pOid = gpOidTable->Lookup(CId2Key(Oid,Mid)); + + if (pOid) + { + COid *pRemove = hProcess->DropOid(pOid); + + if (pRemove == NULL) + { + +#if DBG + { + GUID Moid; + MOIDFromOIDAndMID(Oid,Mid,&Moid); + ComDebOut((DEB_OXID,"OR: Client process %d tried to remove moid %I which \ + it didn't own\n", hProcess->GetProcessID(), &Moid)); + } +#endif // DBG + + return OR_BADOID; + } + else + { + ASSERT(pRemove == pOid); + return OR_OK; + } + } + else + { + +#if DBG + { + GUID Moid; + MOIDFromOIDAndMID(Oid,Mid,&Moid); + ComDebOut((DEB_OXID,"OR: Client process %d tried to remove moid %I which \ + doesn't exist\n", hProcess->GetProcessID(), &Moid)); + } +#endif // DBG + + return OR_BADOID; + } +} + + +error_status_t +ServerAllocateOXID( + IN HPROCESS hProcess, + IN long fApartment, + IN OXID_INFO *pOxidInfo, + IN DUALSTRINGARRAY *pdsaStringBindings, + OUT OXID &Oxid + ) +/*++ + +Routine Description: + + Allocates an OXID and 0 or more OIDs from the OR. + +Arguments: + + hProcess - The context handle of the process containing the OXID. + + fApartment - is the server threading model apartment or free + + OxidInfo - The OXID_INFO structure for the OXID without bindings. + + pdsaStringBindings - Expanded string binding of the server. + + Oxid - The OXID registered and returned. + +Return Value: + + OR_OK - success. + + OR_NOMEM - Allocation of OXID failed. + +--*/ +{ + ComDebOut((DEB_OXID, "ServerAllocateOXID\n")); + + ORSTATUS status = OR_OK; + + COxid *pNewOxid; + + // Save the string bindings back to the process + + ASSERT(dsaValid(pdsaStringBindings)); + + CProtectSharedMemory protector; // locks through rest of lexical scope + +#if DBG + hProcess->IsValid(); +#endif + + status = hProcess->ProcessBindings(pdsaStringBindings); + + if (status != OR_OK) + { + return(status); + } + + pNewOxid = new COxid( + hProcess, + *pOxidInfo, + fApartment + ); + + if (NULL == pNewOxid) + { + return(OR_NOMEM); + } + + Oxid = pNewOxid->GetOXID(); + + // Add to process and lookup table. + + status = hProcess->OwnOxid(pNewOxid); + + VALIDATE((status, OR_NOMEM, 0)); + + if (OR_OK == status) + { + status = gpOxidTable->Add(pNewOxid); + if (status != OR_OK) + { + delete pNewOxid; + return status; + } + + ComDebOut((DEB_OXID, "OXID successfully allocated: %08x\n", Oxid)); + } + + return(status); +} + + +error_status_t +ServerAllocateOID( + IN HPROCESS hProcess, + IN OXID Oxid, + OUT OID &Oid + ) +/*++ + +Routine Description: + + Registers an OID on behalf of an existing OXID. + +Arguments: + + hProcess - The context handle of the process containing the OXID and OIDs. + + Oxid - The OXID associated with the OID (assumed local of course). + + Oid - The OID to be allocated and returned. + +Return Value: + + OR_OK (0) - Success. + + OR_NOMEM - OXID or one or more OIDs + +--*/ +{ + ComDebOut((DEB_OXID, "ServerAllocateOID, OXID = %08x\n", Oxid)); + + CProtectSharedMemory protector; // locks through rest of lexical scope + +#if DBG + hProcess->IsValid(); +#endif + + COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,gLocalMID)); + + ORSTATUS status; + + if (NULL == pOxid) + { + return(OR_BADOXID); + } + + COid *pOid = new COid(pOxid); + + if (NULL == pOid) + { + return OR_NOMEM; + } + + status = pOxid->OwnOid(pOid); + + if (status == OR_OK) + { + Oid = pOid->GetOID(); // out parameter + + status = gpOidTable->Add(pOid); + if (status != OR_OK) + { + delete pOid; + return status; + } + + // If the server doesn't want to keep the OID alive, + // this OID may rundown in six minutes unless + // someone references it in the meantime... + + ComDebOut((DEB_OXID, "OID successfully allocated: %08x at offset = %x\n", + Oid,OR_OFFSET(pOid))); + + pOxid->StartRundownThreadIfNecessary(); + + return OR_OK; + } + else + { + return OR_NOMEM; + } +} + +error_status_t +ServerFreeOXID( + IN HPROCESS hProcess, + IN OXID Oxid, + IN ULONG cOids, + IN OID aOids[]) +/*++ + +Routine Description: + + Delete an OXID registered by the server, and all OIDs belonging to this OXID. + +Arguments: + + hProcess - The context handle of the process containing the OXID and OIDs. + + Oxid - The OXID to be deleted (assumed local). + + cOids - The number of OIDs to be deleted. + + aOids - array of OIDs to be deleted. + +Return Value: + + OR_OK (0) - Success. + + OR_BADOXID - OXID does not exist. + + OR_NOACCESS - OXID does not belong to this process. + + OR_BADOID - OID does not exist or does not belong to this OXID. + +--*/ +{ + ComDebOut((DEB_OXID, "ServerFreeOXID: %08x MID = %x\n", + Oxid,gLocalMID)); + + CProtectSharedMemory protector; // locks through rest of lexical scope + +#if DBG + hProcess->IsValid(); +#endif + + COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,gLocalMID)); + + if (NULL != pOxid) + { +#if DBG + OXID Oxid = pOxid->GetOXID(); // get this before pOxid potentially disappears +#endif + + hProcess->DisownOxid(pOxid,TRUE); // this call is on the server's thread + // in the apartment case and in the server's + // process in both threading cases + + ComDebOut((DEB_OXID, "OXID successfully removed: %08x\n", + Oxid)); + + return OR_OK; + } + else + { + return OR_BADOXID; + } +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx new file mode 100644 index 000000000..2a47c20f9 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx @@ -0,0 +1,398 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Mid.cxx + +Abstract: + + Implements the CMid class. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + SatishT 04-13-96 Reworked from MarioGo's code + +--*/ + +#include<or.hxx> + + +// +// A table for cached resolver handles +// BUGBUG: Right now, the buckets and links for this are being +// created in shared memory -- on Chicago, it would be +// easy to make the allocator a parameter for tables and lists +// + +CResolverHandleTable HandleTable(MID_TABLE_SIZE); + + +// +// BindingIterator methods +// + + +COrBindingIterator::COrBindingIterator( + CMid *pMid, + ORSTATUS& status + ) + : _pMid(pMid), + _bIter(pMid->_iStringBinding,pMid->_dsa) +{ + if (_pMid->IsLocal()) + { + ASSERT(0); // should never call + } + + status = OR_OK; + RPC_BINDING_HANDLE hMachine = NULL; + + _pCurrentHandle = HandleTable.Lookup(CIdKey(pMid->GetMID())); + + if (_pCurrentHandle == NULL) // never talked to this OR before + { + BOOL fSecure = FALSE; + PWSTR pwstrT; + + // REVIEW : The OR explictly uses RPC_C_AUTHN_WINNT only for secure pinging. + + pwstrT = &_pMid->_dsa->aStringArray[_pMid->_dsa->wSecurityOffset]; + + while(*pwstrT) + { + if (*pwstrT == RPC_C_AUTHN_WINNT) + { + fSecure = TRUE; + break; + } + } + + // make a new handle and Add it to the HandleTable + + _pCurrentHandle = new CResolverHandle(pMid->GetMID(),fSecure); + + if (!_pCurrentHandle || HandleTable.Add(_pCurrentHandle) != OR_OK) + { // couldn't allocate or couldn't Add + delete _pCurrentHandle; + _pCurrentHandle = NULL; + status = OR_NOMEM; + } + } +} + + + +RPC_BINDING_HANDLE +COrBindingIterator::Next() +/*++ + +Method Description: + + Gets the next possible RPC binding handle to the remote machine. + We get here only if First finds no handle in _pCurrentHandle + which happens only if + + 1. At the first contact with this OR. + + 2. At subsequent contacts, a current handle failed (some service needed by + that protseq may have failed, or we have a network partition). + This includes the possibility that we never successfully talk to this OR. + +Arguments: + + None + +Return Value: + + NULL - resource allocation or connection failure + + non-NULL - A binding to the machine. + +--*/ +{ + _pCurrentHandle->Clear(); // This is either not initialized or has already failed + + PWSTR pwstrT; + RPC_BINDING_HANDLE hMachine = NULL; + + while(*(pwstrT = _bIter.Next())) + { + hMachine = GetBindingToOr(pwstrT); // BUGBUG: need dynamic endpoint fallback? + + if (hMachine) + { + break; + } + } + + if (NULL == hMachine) // did we get anything? + { + _pCurrentHandle->Clear(); // no we did not + _pMid->_fBindingWorking = FALSE; // so remember that + } + else + { + _pCurrentHandle->Reset(hMachine); // OK we have it, copy it in + RpcBindingFree(&hMachine); // this is already copied + _pMid->_iStringBinding = _bIter.Index(); // remember the one that worked + _pMid->_fBindingWorking = TRUE; // mark this Mid as functional + } + + return *_pCurrentHandle; +} + + +// +// CMid methods +// + +ORSTATUS +CMid::ResolveRemoteOxid( + IN OXID Oxid, + OUT OXID_INFO *poxidInfo + ) +{ + // Remote OXID, call ResolveOxid + + // BUGBUG: Only sending the protseq we're calling OR on, + // this should be fixed to send in the whole list if + // it includes the protseq we're calling on. + + // BUGBUG: ASSERT that the shared memory lock is held? + +#ifndef _REMOTE_OR_ + + return OR_BADOXID; + +#else + + ORSTATUS status; + + USHORT tmpProtseq; + RPC_BINDING_HANDLE hRemoteOr; + + poxidInfo->psa = NULL; + + COrBindingIterator bindIter(this,status); + + if (status != OR_OK) return status; + + for (hRemoteOr = bindIter.First(); + hRemoteOr != NULL; + hRemoteOr = bindIter.Next() + ) + { + tmpProtseq = ProtseqOfServer(); + + { + CTempReleaseSharedMemory temp; + + poxidInfo->dwTid = poxidInfo->dwPid = 0; // marks a remote OXID + + status = ::ResolveOxid( + hRemoteOr, + &Oxid, + 1, + &tmpProtseq, + &poxidInfo->psa, + &poxidInfo->ipidRemUnknown, + &poxidInfo->dwAuthnHint + ); + } + + if ((status == OR_OK) || (status == OR_BADOXID)) + { + break; + } + } + + if (status == OR_OK) + { + ASSERT(poxidInfo->psa && "Remote resolve succeeded but no bindings returned"); + } + + return status; + +#endif// _REMOTE_OR_ + +} + + + +ORSTATUS +CMid::PingServer() +{ + + // BUGBUG: ASSERT that the shared memory lock is held? + +#ifndef _REMOTE_OR_ + + return OR_NOSERVER; + +#else // _REMOTE_OR_ + + if (_addOidList.IsEmpty() && _dropOidList.IsEmpty() && _pingSet.IsEmpty()) + { + return OR_OK; // nothing to do + } + + ORSTATUS status; + RPC_BINDING_HANDLE hRemoteOr; + + COrBindingIterator bindIter(this,status); + + if (status != OR_OK) return status; + + if (!_addOidList.IsEmpty() || !_dropOidList.IsEmpty()) + { + // need complex ping + + USHORT cAddToSet = _addOidList.Size(); + USHORT cDelFromSet = _dropOidList.Size(); + COidList addOidListSent, dropOidListSent; + + OID *aAddToSet = NULL; + OID *aDelFromSet = NULL; + + if (cAddToSet > 0) + { + aAddToSet = new OID[cAddToSet]; + if (aAddToSet == NULL) + { + return OR_NOMEM; + } + + COidListIterator AddIter; + AddIter.Init(_addOidList); + USHORT i = 0; + + for (COid *pOid = AddIter.Next(); pOid != NULL; pOid = AddIter.Next()) + { + aAddToSet[i++] = pOid->GetOID(); + } + } + + if (cDelFromSet > 0) + { + aDelFromSet = new OID[cDelFromSet]; + if (aDelFromSet == NULL) + { + delete aAddToSet; + return OR_NOMEM; + } + + COidListIterator DropIter; + DropIter.Init(_dropOidList); + USHORT i = 0; + + for (COid *pOid = DropIter.Next(); pOid != NULL; pOid = DropIter.Next()) + { + aDelFromSet[i++] = pOid->GetOID(); + } + } + + { + // Transfer the current _addOidList and _dropOidList and set them to + // empty since we are releasing the shared memory lock. + + _addOidList.Transfer(addOidListSent); + _dropOidList.Transfer(dropOidListSent); + + // We will have to deal with failure scenarios appropriately. + + // Now release the lock and ping. + + // CTempReleaseSharedMemory temp; + + for (hRemoteOr = bindIter.First(); + hRemoteOr != NULL; + hRemoteOr = bindIter.Next() + ) + { + status = ::ComplexPing( + hRemoteOr, + &_setID, + _sequenceNum++, + cAddToSet, + cDelFromSet, + aAddToSet, + aDelFromSet, + &_pingBackoffFactor + ); + + if (status == OR_OK || status == OR_BADSET || status == OR_BADOID) + { + break; + } + } + } + + COidListIterator AddIter; + AddIter.Init(addOidListSent); + + for (COid *pOid = AddIter.Next(); pOid != NULL; pOid = AddIter.Next()) + { + status = _pingSet.Add(pOid); + if (status != OR_OK) break; + } + + delete aAddToSet; + delete aDelFromSet; + dropOidListSent.Clear(); + + if (_pingSet.IsEmpty()) + { + _setID = 0; // server OR will delete the set + } + + + // BUGBUG: several contingencies have not been handled + // some of these apply to simple ping as well + // + // 1. OR_BADSET, OR_BADOID, OR_NOMEM + // 2. RPC_S_UNKNOWN_IF (dynamic endpoints) + // 3. General RPC failure (binding failure) + // 4. RPC blocked forever -- how to detect and correct + // the hang, and what to do with this Mid subsequently + // 5. Someone wants to modify the _addOidList/_dropOidList + // while we are waiting for the RPC to complete + + // Note that _pingSet.IsEmpty() <=> _setID == 0 + // This must be ensured by code that deals with failures. + } + + else if (_setID != 0) + { + // need simple ping + { + CTempReleaseSharedMemory temp; + + for (hRemoteOr = bindIter.First(); + hRemoteOr != NULL; + hRemoteOr = bindIter.Next() + ) + { + status = ::SimplePing( + hRemoteOr, + &_setID + ); + + if (status == OR_OK || status == OR_BADSET || status == OR_BADOID) + { + break; + } + } + } + } + + return status; + +#endif // _REMOTE_OR_ + +} diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx new file mode 100644 index 000000000..b16526e98 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx @@ -0,0 +1,331 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Mid.hxx + +Abstract: + + Class representing string bindings and security bindings for a particular + machine. Provides a mapping between the bindings and a local machine + unique ID for that machine. + + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 12-13-95 Bits 'n pieces + +--*/ + +#ifndef __MID_HXX +#define __MID_HXX + +class CResolverHandle : public CTableElement +{ +public: + + CResolverHandle(MID id, BOOL fSecure) + { + _Key.Init(id); + _hOR = NULL; + _fSecure = fSecure; + } + + ~CResolverHandle() + { + Clear(); + } + + void Clear() + { + if (_hOR != NULL) + { + RpcBindingFree(&_hOR); + _hOR = NULL; + } + } + + ORSTATUS Reset(RPC_BINDING_HANDLE hIn) + { + ASSERT(hIn != NULL); + Clear(); + + if (_fSecure) + { + RPC_STATUS status = RpcBindingSetAuthInfo(hIn, + 0, + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_AUTHN_WINNT, + 0, + 0); + + if (status != RPC_S_OK) + { + ComDebOut((DEB_OXID,"OR: RpcBindingSetAuthInfo failed for OR handle with %d\n", + status)); + + // Just fall back on unsecure. + } + } + + return RpcBindingCopy(hIn,&_hOR); + } + + virtual operator ISearchKey&() + { + return _Key; + } + + operator RPC_BINDING_HANDLE&() + { + return _hOR; + } + +private: + + CIdKey _Key; + RPC_BINDING_HANDLE _hOR; + BOOL _fSecure; +}; + + + +DEFINE_TABLE(CResolverHandle) + +typedef CDSA CMidKey; + +class CMid : public CTableElement +/*++ + +Class Description: + + Represents the local and remote machines. Each unique (different) + set of string bindings and security bindings are assigned a unique + local ID. This ID is used along with the OID and OXID of the remote + machine objects index these objects locally. Instances of this class + are referenced by COids. + + This class is indexed by string and security bindings. There is no + index by MID. + +Members: + + _id - The locally unique ID of this set of bindings. + + _iStringBinding - Index into _dsa->aStringArray of the + compressed string binding used to create a handle. + + _iSecurityBinding - Index into _dsaSecurityArray of the + + _dsa - The set of compressed bindings. + +--*/ +{ + +public: + + CMid( + DUALSTRINGARRAY *pdsa, + ORSTATUS& status, + USHORT wProtSeq // if the SCM tells us what to use + ) : + _id(AllocateId()), + _iStringBinding(0), + _iSecurityBinding(0), + _fBindingWorking(FALSE), + _dsa(pdsa,TRUE,status), + _setID(0) + { + if (wProtSeq > 0) + { + PWSTR pwstr = FindMatchingProtseq(wProtSeq,pdsa->aStringArray); + + if (NULL != pwstr) + { + _iStringBinding = pwstr - pdsa->aStringArray; + } + } + } + + ~CMid() + { + if (gpMidTable != NULL) // this might happen during initialization + { // of globals, e.g., gpLocalMid + gpMidTable->Remove(*this); + } + } + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void * operator new(size_t s, size_t extra) + { + return OrMemAlloc(s+extra); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + operator ISearchKey&() // allows us to be a ISearchKey + { + return _dsa; + } + + virtual BOOL + Compare(ISearchKey &tk) + { + return(_dsa.Compare(tk)); + } + + + DUALSTRINGARRAY * + GetStrings() + { + return(_dsa); + } + + USHORT ProtseqOfServer() + { + if (_fBindingWorking) + { + return(_dsa->aStringArray[_iStringBinding]); + } + else + { + return(0); + } + } + + BOOL IsLocal() + { + return (_id == gLocalMID); + } + + MID GetMID() + { + return(_id); + } + + ORSTATUS PingServer(); + + ORSTATUS AddClientOid(COid *pOid) + { + ORSTATUS status = OR_OK; + + // this way, we have the same number of refs on the Oid + // as we would if we were already pinging it. The ref is + // held by the _addOidList instead of the _pingSet + + if (_pingSet.Lookup(*pOid) == NULL) + { + _addOidList.Insert(status,pOid); + } + + return status; + } + + ORSTATUS DropClientOid(COid *pOid) + { + ORSTATUS status = OR_OK; + COid *pt; + + // this way, we have the same number of refs on the Oid + // as we would if we were already pinging it. The ref is + // held by the _addOidList instead of the _pingSet + + if ((pt = _pingSet.Remove(*pOid)) == pOid) + { + _dropOidList.Insert(status,pOid); + } + else if (pt == NULL) + { + ComDebOut((DEB_OXID,"Trying to stop pinging OID not belonging to MID=%08x",_id)); + ASSERT(0); + } + else + { + ComDebOut((DEB_OXID,"Trying to stop pinging bogus COid object at MID=%08x",_id)); + ASSERT(0); + } + + return status; + } + + ORSTATUS ResolveRemoteOxid( + OXID Oxid, + OXID_INFO *poxidInfo + ); + +#if DBG + PWSTR PrintableName() + { + return(&_dsa->aStringArray[_iStringBinding + 1]); + } +#endif + +private: + + friend class COrBindingIterator; + + ID _id; + USHORT _iStringBinding; + USHORT _iSecurityBinding; + CDSA _dsa; + BOOL _fBindingWorking; + + COidTable _pingSet; + COidList _addOidList; + COidList _dropOidList; + ID _setID; + USHORT _sequenceNum; + USHORT _pingBackoffFactor; + +}; + +DEFINE_TABLE(CMid) + + +class COrBindingIterator +{ +public: + + COrBindingIterator( + CMid *pMid, + ORSTATUS &status + ); + + RPC_BINDING_HANDLE First() + { + RPC_BINDING_HANDLE hMachine = *_pCurrentHandle; // auto conversion + + if (hMachine != NULL) + { + return hMachine; // Already have one, so try it + } + else + { + return Next(); + } + } + + RPC_BINDING_HANDLE Next(); + +private: + + CMid *_pMid; + CBindingIterator _bIter; + CResolverHandle *_pCurrentHandle; +}; + +#endif // __MID_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx new file mode 100644 index 000000000..3e176f4bf --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx @@ -0,0 +1,189 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Misc.cxx + +Abstract: + + Initalization, Heap, debug, thread manager for OR + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-11-95 Bits 'n pieces + +--*/ + +#include <or.hxx> + +// +// +// + +WCHAR* +catenate( + WCHAR* pszPrefix, + WCHAR* pszSuffix + ) +/*++ + +Routine Description: + + Concatenate the two given strings into a new string + +Arguments: + + pszPrefix - prefix of result + + pszSuffix - suffix of result + +Returns: + + A newly allocated string. + +--*/ +{ + long prefixLen = wcslen(pszPrefix); + long suffixLen = wcslen(pszSuffix); + + WCHAR* pszResult = new WCHAR[(prefixLen+suffixLen+1)*sizeof(WCHAR)]; + wcscpy(pszResult,pszPrefix); + wcscpy(pszResult+prefixLen,pszSuffix); + return pszResult; +} + + +// +// Local ID allocation +// + + +ID +AllocateId( + IN LONG cRange + ) +/*++ + +Routine Description: + + Allocates a unique local ID. + + This id is 64bits. The low 32 bits are a sequence number which + is incremented with each call. The high 32bits are seconds + since 1980. The ID of 0 is not used. + +Limitations: + + No more then 2^64 IDs can be generated in a given second without + a duplicate. After 2^32 there becomes a much higher change of + overflow. + + When the time stamp overflows, once every >126 years, the sequence + numbers are likely to be generated in such a way as to collide + with those from 126 years ago. + + There is no prevision in the code to deal with duplications. + +Arguments: + + cRange - Number to allocate in sequence, default is 1. + +Return Value: + + A 64bit id. + +Note: This must be called under shared memory lock! + +--*/ +{ + FILETIME ft; + LARGE_INTEGER id; + + ASSERT(cRange > 0 && cRange < 11); + + do + { + id.HighPart = GetTickCount(); + id.LowPart = *gpIdSequence; + *gpIdSequence += cRange; + } + while (id.QuadPart == 0 ); + + return(id.QuadPart); +} + +// +// Debug helper(s) +// + +#if DBG + +int __cdecl __RPC_FAR ValidateError( + IN ORSTATUS Status, + IN ...) +/*++ +Routine Description + + Tests that 'Status' is one of an expected set of error codes. + Used on debug builds as part of the VALIDATE() macro. + +Example: + + VALIDATE( (Status, + OR_BADSET, + // more error codes here + OR_OK, + 0) // list must be terminated with 0 + ); + + This function is called with the OrStatus and expected errors codes + as parameters. If OrStatus is not one of the expected error + codes and it not zero a message will be printed to the debugger + and the function will return false. The VALIDATE macro ASSERT's the + return value. + +Arguments: + + Status - Status code in question. + + ... - One or more expected status codes. Terminated with 0 (OR_OK). + +Return Value: + + TRUE - Status code is in the list or the status is 0. + + FALSE - Status code is not in the list. + +--*/ +{ + RPC_STATUS CurrentStatus; + va_list(Marker); + + if (Status == 0) return(TRUE); + + va_start(Marker, Status); + + while(CurrentStatus = va_arg(Marker, RPC_STATUS)) + { + if (CurrentStatus == Status) + { + return(TRUE); + } + } + + va_end(Marker); + + OrDbgPrint(("OR Assertion: unexpected failure %lu (0lx%08x)\n", + (unsigned long)Status, (unsigned long)Status)); + + return(FALSE); +} + +#endif + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx new file mode 100644 index 000000000..a56598d66 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx @@ -0,0 +1,120 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Misc.hxx + +Abstract: + + Header for random helpers functions. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-11-95 Bits 'n pieces + +--*/ + +#ifndef __MISC_HXX +#define __MISC_HXX + +extern ID AllocateId(LONG cRange = 1); + +#ifndef _CHICAGO_ + +inline +void * _CRTAPI1 +operator new ( + IN size_t size + ) +{ + return PrivMemAlloc(size); +} + +inline +void _CRTAPI1 +operator delete ( + IN void * obj + ) +{ + PrivMemFree(obj); +} + +#endif _CHICAGO_ + +enum AllocType +{ + InSharedHeap, + InProcessHeap +}; + + +// REVIEW: Do we want separate Object and Set heaps to avoid page faults? +// probably not worthwhile for Chicago +// + + +inline +void * _CRTAPI1 +operator new ( + IN size_t size, + IN size_t extra + ) +{ + return(PrivMemAlloc(size + extra)); +} + +inline +void * _CRTAPI1 +operator new ( + IN size_t size, + AllocType type + ) +{ + if (type == InSharedHeap) return OrMemAlloc(size); + else return PrivMemAlloc(size); +} + +inline void +Raise(unsigned long ErrorCode) { + RaiseException( + ErrorCode, + EXCEPTION_NONCONTINUABLE, + 0, + NULL + ); +} + +template <class TYPE> +TYPE * CopyArray( + IN DWORD size, + IN TYPE *pArr, + ORSTATUS *pStatus + ) +{ + TYPE *pNew = new TYPE[size]; + if (!pNew) + { + *pStatus = OR_NOMEM; + return NULL; + } + else + { + *pStatus = OR_OK; + } + + for (DWORD i = 0; i < size; i++) + { + pNew[i] = pArr[i]; + } + + return pNew; +} + +#endif // __MISC_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx new file mode 100644 index 000000000..a371b59c0 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx @@ -0,0 +1,104 @@ +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + mutex.cxx + +Abstract: + + This file contains the implementations for non inline member functions of + CReadWriteSection and CGlobalMutex, which implement a readers/writers + mutex and a multi-owner mutex, respectively. + +Author: + + Satish Thatte (SatishT) 09/01/95 Created all the code below except where + otherwise indicated. + +--*/ + +#define NULL 0 + +extern "C" { +#include <windows.h> +} + +#include <mutex.hxx> + + +CGlobalMutex::CGlobalMutex( + long lMaxCount + ) +/*++ + +Routine Description: + + create a semaphore and initialize the handle member pNTSem. + +--*/ +{ + hGlobalMutex = CreateMutex( + NULL, // LPSECURITY_ATTRIBUTES lpsa + FALSE, // BOOL fInitialOwner + GLOBAL_CS // LPCTSTR lpszMutexName + ); + + // + // If the mutex create/open failed, then bail + // + + if ( !hGlobalMutex ) + { + return LAST_SCODE; + } + + if ( GetLastError() == ERROR_ALREADY_EXISTS ) + { + } +} + + + +CGlobalMutex::~CGlobalMutex() +/*++ + +Routine Description: + + close the semaphore handle. + +--*/ +{ + CloseHandle(pNTSem); +} + + +void +CGlobalMutex::Enter() +/*++ + +Routine Description: + + Wait for the semaphore count to become nonzero. + +--*/ +{ + WaitForSingleObject(pNTSem,INFINITE); +} + + +void +CGlobalMutex::Leave(long lIncrement) +/*++ + +Routine Description: + + Increment the semaphore count by lIncrement to release lIncrement "slots". + +--*/ +{ + ReleaseSemaphore(pNTSem,lIncrement,NULL); +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx new file mode 100644 index 000000000..90bff5821 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx @@ -0,0 +1,239 @@ +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + mutex.hxx + +Abstract: + + This file contains definitions of classes which provide mutual exclusion. + At the moment, only an InterlockedInteger and a simple (interprocess) + Mutex are defined, but in future, a readers/writers version may be added. + +Author: + + Satish Thatte (SatishT) 02/22/96 Created all the code below except where + otherwise indicated. + +--*/ + +#ifndef __MUTEX_HXX__ +#define __MUTEX_HXX__ + +class CInterlockedInteger // created by MarioGo + { + private: + LONG i; + + public: + + CInterlockedInteger(LONG i = 0) : i(i) {} + + LONG operator++(int) + { + return(InterlockedIncrement(&i)); + } + + LONG operator--(int) + { + return(InterlockedDecrement(&i)); + } + + operator LONG() + { + return(i); + } + }; + + + +/*++ + +Class Definition: + + CGlobalMutex + +Abstract: + + This class implements an inter process mutex which controls + access to resources and data in shared memory. + +--*/ + +class CGlobalMutex { + + HANDLE _hMutex; // Reference to system mutex object + // we are impersonating + + +public: + + CGlobalMutex(ORSTATUS &status); + + ~CGlobalMutex(); + + void Enter() ; + + void Leave(); +}; + + + + + +/*++ + +Class Definition: + + CProtectSharedMemory + +Abstract: + + A convenient way to acquire and release a lock on a CGlobalMutex. + Entry occurs on creation and exit on destruction of this object, and hence + can be made to coincide with a local scope. Especially convenient when + there are multiple exit points from the scope (returns, breaks, etc.). + + +--*/ + +extern CGlobalMutex *gpMutex; // global mutex to protect shared memory + +class CProtectSharedMemory { + +public: + + CProtectSharedMemory() { + gpMutex->Enter(); + } + + ~CProtectSharedMemory() { + gpMutex->Leave(); + } +}; + + + +class CTempReleaseSharedMemory { + +public: + + CTempReleaseSharedMemory() { + gpMutex->Leave(); + } + + ~CTempReleaseSharedMemory() { + gpMutex->Enter(); + } +}; + + + +/******** inline methods ********/ + + +inline +CGlobalMutex::CGlobalMutex(ORSTATUS &status) +/*++ + +Routine Description: + + create a mutex and initialize the handle member _hMutex. + +--*/ +{ + SECURITY_DESCRIPTOR sd; + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) + { + status = GetLastError(); + ComDebOut((DEB_OXID,"InitializeSecurityDescriptor Failed with %d\n",status)); + return; + } + + if (! SetSecurityDescriptorDacl( + &sd, // address of security descriptor + TRUE, // flag for presence of discretionary ACL + NULL, // address of discretionary ACL + FALSE // flag for default discretionary ACL + ) + ) + { + status = GetLastError(); + ComDebOut((DEB_OXID,"SetSecurityDescriptorDacl Failed with %d\n",status)); + return; + } + + SECURITY_ATTRIBUTES sa; + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &sd; + sa.bInheritHandle = FALSE; + + _hMutex = CreateMutex( + &sa, // LPSECURITY_ATTRIBUTES lpsa + FALSE, // BOOL fInitialOwner + GLOBAL_MUTEX_NAME // LPCTSTR lpszMutexName + ); + + // + // Did the mutex create/open fail? + // + + if ( !_hMutex ) + { + status = GetLastError(); + ComDebOut((DEB_OXID,"Global Mutex Creation Failed with %d\n",status)); + } + else + { + status = OR_OK; + } +} + + +inline +CGlobalMutex::~CGlobalMutex() +/*++ + +Routine Description: + + close the mutex handle. + +--*/ +{ + CloseHandle(_hMutex); +} + + +inline void +CGlobalMutex::Enter() +/*++ + +Routine Description: + + Wait for the mutex to be signalled. + +--*/ +{ + WaitForSingleObject(_hMutex,INFINITE); +} + + +inline void +CGlobalMutex::Leave() +/*++ + +Routine Description: + + Signal the mutex + +--*/ +{ + ReleaseMutex(_hMutex); +} + + +#endif // __MUTEX_HXX__ diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx new file mode 100644 index 000000000..2bfcda32d --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx @@ -0,0 +1,402 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + ObjEx.cxx + +Abstract: + + Main entry point for the object exporter service. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-28-95 Bits 'n pieces + +--*/ + + +#include <or.hxx> + +#ifndef _CHICAGO_ + +DECLARE_INFOLEVEL(Cairole) // BUGBUG: strictly for private memory stuff from storage + // elide ASAP +#endif // _CHICAGO_ + +#if DBG +#include <fstream.h> +#endif + +extern "C" +{ +#define SECURITY_WIN32 // Used by sspi.h +#include <sspi.h> // EnumerateSecurityPackages +} + +// +// Process globals - read-only except during init. +// + +// MID of the string bindings for this machine -- the bindings are phoney +// for this shared memory version of the resolver. + +DUALSTRINGARRAY *gpLocalDSA; +MID gLocalMID; +CMid *gpLocalMid; +CProcess *gpProcess; // pointer to our process object +CProcess *gpPingProcess; // pointer to pinging process +// +// Process globals - read-write +// + +void * pSharedBase; +CSharedGlobals *GlobalBlock; + +#ifndef _CHICAGO_ +CSmAllocator gsmDCOMAllocator; +#endif // _CHICAGO_ + +COxidTable * gpOxidTable; +COidTable * gpOidTable; +CMidTable * gpMidTable; +CProcessTable * gpProcessTable; + +USHORT *gpcRemoteProtseqs; // count of remote protseqs +USHORT *gpRemoteProtseqIds; // array of remote protseq ids +PWSTR gpwstrProtseqs; // remote protseqs strings catenated +DUALSTRINGARRAY *gpdsaMyBindings; // DUALSTRINGARRAY of local OR's bindings + +LONG * gpIdSequence; + +FILETIME MyCreationTime; +DWORD MyProcessId; + +DWORD *gpdwLastCrashedProcessCheckTime; +DWORD *gpNextThreadID; + +CGlobalMutex *gpMutex; // global mutex to protect shared memory + +BOOL DCOM_Started = FALSE; +ID ProcessMarker; // sanity checking marker for the process object + +CResolverHashTable *gpClientSetTable = 0; + +//+------------------------------------------------------------------------- +// +// Function: ComputeSecurity +// +// Synopsis: Looks up some registry keys and enumerates the security +// packages on this machine. +// +//-------------------------------------------------------------------------- +// These variables hold values read out of the registry and cached. +// s_fEnableDCOM is false if DCOM is disabled. The others contain +// authentication information for legacy applications. +BOOL s_fEnableDCOM; +DWORD s_lAuthnLevel; +DWORD s_lImpLevel; +BOOL s_fMutualAuth; +BOOL s_fSecureRefs; + +// s_sServerSvc is a list of security providers that OLE servers can use. +// s_aClientSvc is a list of security providers that OLE clients can use. +// The difference is that Chicago only supports the client side of some +// security providers and OLE servers must know how to determine the +// principal name for the provider. Clients get the principal name from +// the server. +DWORD s_cServerSvc = 0; +USHORT *s_aServerSvc = NULL; +DWORD s_cClientSvc = 0; +USHORT *s_aClientSvc = NULL; +BOOL fSecurityComputed = FALSE; + +void ComputeSecurity() +{ + SecPkgInfo *pAllPkg; + SecPkgInfo *pNext; + HRESULT hr; + DWORD i; + DWORD lMaxLen; + HKEY hKey; + DWORD lType; + DWORD lData; + DWORD lDataSize; + + if (fSecurityComputed) return; + + fSecurityComputed = TRUE; + + // Get the list of security packages. + hr = EnumerateSecurityPackages( &lMaxLen, &pAllPkg ); + if (hr == 0) + { + // Allocate memory for both service lists. + s_aServerSvc = new USHORT[lMaxLen]; + s_aClientSvc = new USHORT[lMaxLen]; + if (s_aServerSvc == NULL || s_aClientSvc == NULL) + { + hr = E_OUTOFMEMORY; + delete s_aServerSvc; + delete s_aClientSvc; + s_aServerSvc = NULL; + s_aClientSvc = NULL; + } + else + { + // Check all packages. + ASSERT((s_cClientSvc == 0) && (s_cServerSvc == 0)); + pNext = pAllPkg; + for (i = 0; i < lMaxLen; i++) + { + // Determine if clients can use the package. + if ((pNext->fCapabilities & (SECPKG_FLAG_DATAGRAM | + SECPKG_FLAG_CONNECTION))) + { + s_aClientSvc[s_cClientSvc++] = pNext->wRPCID; + } + + // BUGBUG - Add flag for NT principal names + // Determine is servers can use the package. + if ( (pNext->fCapabilities & (SECPKG_FLAG_DATAGRAM | + SECPKG_FLAG_CONNECTION)) && + ~(pNext->fCapabilities & (SECPKG_FLAG_CLIENT_ONLY))) + { + s_aServerSvc[s_cServerSvc++] = pNext->wRPCID; + } + pNext++; + } + } + + // Release the list of security packages. + FreeContextBuffer( pAllPkg ); + } + + // Set all the security flags to their default values. +#ifdef _CAIRO_ + s_fEnableDCOM = TRUE; +#else + s_fEnableDCOM = FALSE; +#endif + s_lAuthnLevel = RPC_C_AUTHN_LEVEL_NONE; // BUGBUG: temp workaround + s_lImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; + s_fMutualAuth = FALSE; + s_fSecureRefs = FALSE; + + // Open the security key. + hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\OLE", + NULL, KEY_QUERY_VALUE, &hKey ); + if (hr != ERROR_SUCCESS) + return; + + // Query the value for DisableDCOM. + lDataSize = sizeof(lData ); + hr = RegQueryValueEx( hKey, L"EnableDCOM", NULL, &lType, + (unsigned char *) &lData, &lDataSize ); + if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0) + { + if (*((WCHAR *) &lData) == L'y' || + *((WCHAR *) &lData) == L'Y') + s_fEnableDCOM = TRUE; + } + + // Query the value for the authentication level. + lDataSize = sizeof(lData ); + hr = RegQueryValueEx( hKey, L"LegacyAuthenticationLevel", NULL, + &lType, (unsigned char *) &lData, &lDataSize ); + if (hr == ERROR_SUCCESS && lType == REG_DWORD) + { + s_lAuthnLevel = lData; + } + + // Query the value for the impersonation level. + lDataSize = sizeof(lData ); + hr = RegQueryValueEx( hKey, L"LegacyImpersonationLevel", NULL, + &lType, (unsigned char *) &lData, &lDataSize ); + if (hr == ERROR_SUCCESS && lType == REG_DWORD) + { + s_lImpLevel = lData; + } + + // Query the value for mutual authentication. + lDataSize = sizeof(lData ); + hr = RegQueryValueEx( hKey, L"LegacyMutualAuthentication", NULL, + &lType, (unsigned char *) &lData, &lDataSize ); + if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0) + { + if (*((WCHAR *) &lData) == L'y' || + *((WCHAR *) &lData) == L'Y') + s_fMutualAuth = TRUE; + } + + // Query the value for secure interface references. + lDataSize = sizeof(lData ); + hr = RegQueryValueEx( hKey, L"LegacySecureReferences", NULL, + &lType, (unsigned char *) &lData, &lDataSize ); + if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0) + { + if (*((WCHAR *) &lData) == L'y' || + *((WCHAR *) &lData) == L'Y') + s_fSecureRefs = TRUE; + } + + // Close the registry key. + RegCloseKey( hKey ); +} + + +// +// Startup +// + +//+------------------------------------------------------------------------- +// +// Function: InitDCOMSharedAllocator +// +// Synopsis: Initialises a shared memory region for this process for DCOM use. +// +// Returns: status code +// +// History: 20-Nov-95 HenryLee Created (SatishT modifiied) +// +// Notes: This routine is called indirectly by DfCreateSharedAllocator +// such a way that in most circumstances it will be executed +// exactly once per docfile open. +// +//-------------------------------------------------------------------------- + +HRESULT InitDCOMSharedAllocator(ULONG DCOMSharedHeapName, void * &pSharedBase) +{ + HRESULT hr = S_OK; + + CSmAllocator *pMalloc = &gSharedAllocator; + + if (pSharedBase == NULL) // allocate a new heap + { +#ifdef MULTIHEAP + // reset the allocator state to initialize it properly + pMalloc->SetState (NULL, NULL, NULL, NULL, 0); +#endif // MULTIHEAP + + hr = pMalloc->Init ( +#ifdef MULTIHEAP + DCOMSharedHeapName, FALSE +#else + L"DCOMResolverSharedHeap" +#endif // MULTIHEAP + ); + if ( SUCCEEDED(hr) ) + { + pMalloc->AddRef(); + pSharedBase = pMalloc->GetBase(); + pMalloc->Alloc(8); // avoid using NULL value for based pointer + } + } + + return hr; +} + +static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc"; +static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols"; +HRESULT MallocInitialize(BOOL fForceLocalAlloc); + +ORSTATUS StartDCOM( + void + ) +/*++ + +Routine Description: + + Primes the distributed object mechanisms, in particular by initializing + shared memory access and structures. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + ORSTATUS status = OR_OK; + + if (DCOM_Started) + { + return OR_REPEAT_START; + } + + // initialize process identity variables + MyProcessId = GetCurrentProcessId(); + + // create or find the global mutex + gpMutex = new CGlobalMutex(status); + + Win4Assert((status == OR_OK) && "CSharedGlobals create global mutex failed"); + + { + CProtectSharedMemory protector; // locks throughout lexical scope + + // Lookup security data. + ComputeSecurity(); + +#if DBG // read names from sm.ini to avoid reboot +#ifndef _CHICAGO_ + + ULONG DCOMSharedHeapName = GetProfileInt( + TEXT("DCOM95 Test"), // section name + TEXT("SharedHeapName"), // key name + 1111 // default name + ); + + WCHAR SharedGlobalBlockName[10]; + swprintf(SharedGlobalBlockName,TEXT("DCOMB%d"),DCOMSharedHeapName); +#else + WCHAR *SharedGlobalBlockName = DCOMSharedGlobalBlockName; +#endif // _CHICAGO_ +#endif // DBG + + // Allocate tables, but only if we are in first + + ComDebOut((DEB_ITRACE,"DCOMSharedHeapName = %d\n", DCOMSharedHeapName)); + ComDebOut((DEB_ITRACE,"SharedGlobalBlockName = %ws\n", SharedGlobalBlockName)); + + InitDCOMSharedAllocator(DCOMSharedHeapName,pSharedBase); + + CSharedGlobals *GlobalBlock + = new CSharedGlobals(SharedGlobalBlockName,status); + } + + // BUGBUG: check status, and if not good, do what?? + + // Allocate lists + gLocalMID = gpLocalMid->GetMID(); + + // initialize timestamp for crash checking + *gpdwLastCrashedProcessCheckTime = 0; + + if ( status != OR_OK + || !gpOxidTable + || !gpOidTable + || !gpMidTable + || !gpLocalDSA + || !gpLocalMid + || !gpPingProcess + || !gpIdSequence + ) + { + return(OR_NOMEM); + } + + + DCOM_Started = TRUE; + return(OR_OK); +} + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx new file mode 100644 index 000000000..3ffdab181 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx @@ -0,0 +1,521 @@ +/*++ + +Copyright (c) 1995-1996 Microsoft Corporation + +Module Name: + + ids.cxx + +Abstract: + + Object resolver client side class implementations. COxid, COid + classes are implemented here. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 04-03-95 Combined many smaller .cxx files + MarioGo 01-05-96 Locally unique IDs + +--*/ + +#include<or.hxx> + + +// +// COid methods +// + +void +COid::Rundown() +{ + COid *pRemoved = gpOidTable->Remove(*this); + ASSERT(pRemoved==this); + + if (!_pOxid->IsLocal()) + { + _pOxid->_pMid->DropClientOid(this); + } +} + + +// +// COxidInfo methods +// + + +ORSTATUS // BUGBUG: perhaps this should have OXID_INFO as the parameter type +COxidInfo::Assign( + const COxidInfo& Info + ) +/*++ + +Routine Desciption + + Makes a copy of the incoming info, including the DUALSTRINGARRAY. + +Arguments: + + Info - COxidInfo object to be cpied + +Return Values: + + OR_OK + OR_NOMEM + +--*/ +{ + _dwTid = Info._dwTid; + _dwPid = Info._dwPid; + _dwAuthnHint = Info._dwAuthnHint; + _ipidRemUnknown = Info._ipidRemUnknown; + + return _dsaBindings.Assign(Info._dsaBindings); +} + + +// +// COxid methods. +// + + +COxid::COxid( + OXID Oxid, // constructor for remote OXIDs + CMid *pMid, + USHORT wProtseq, + OXID_INFO &OxidInfo + ) : + _Key(Oxid, pMid->GetMID()), + _pProcess(OR_BASED_POINTER(CProcess,gpPingProcess)), + _protseq(wProtseq), + _fApartment(FALSE), + _fRunning(TRUE), + _fRundownThreadStarted(FALSE), + _pMid(OR_BASED_POINTER(CMid,pMid)), + _fLocal(FALSE), + _hRundownThread(NULL), + _info(OxidInfo) + { + _pMid->Reference(); + } + + +COxid::COxid( // constructor for local OXIDs + CProcess *pProcess, + OXID_INFO &OxidInfo, + BOOL fApartment + ) : + _Key(AllocateId(), gLocalMID), + _pProcess(OR_BASED_POINTER(CProcess,pProcess)), + _pMid(OR_BASED_POINTER(CMid,gpLocalMid)), + _protseq(0), + _fApartment(fApartment), + _fRunning(TRUE), + _fRundownThreadStarted(FALSE), + _fLocal(TRUE), + _hRundownThread(NULL), + _info(OxidInfo) + { + _pProcess->Reference(); + } + + +COxid::~COxid() +{ + // this works even if executed by nonowner thread + StopRundownThreadIfNecessary(); + + // Don't release the local CMid! + if (!IsLocal()) _pMid->Release(); +} + + + +COid * +COxid::DisownOid(COid *pOid) +{ + COid *pMyOid = _MyOids.Remove(*pOid);// releases our reference + + if (pMyOid) + { + ASSERT(pMyOid == pOid); + return pOid; + } + + return NULL; +} + + +void +COxid::StopRunning() +{ + ReleaseAllOids(); + _fRunning = FALSE; +} + + +void +COxid::ReleaseAllOids() +{ + if (_MyOids.Size()) + { + COidTableIterator Oids(_MyOids); + COid *pOid; + + while(pOid = Oids.Next()) + { + pOid->Rundown(); + } + + _MyOids.RemoveAll(); + } +} + + +ORSTATUS +COxid::GetInfo( + OUT OXID_INFO *pInfo + ) +/*++ + +Routine Description: + + Returns the OXID_INFO structure for this oxid for local. + +Arguments: + + pInfo - Will contain the standard info, a single _expanded_ + string binding and complete security bindings. + +Return Value: + + OR_NOMEM - Unable to allocate a parameter. + + OR_OK - Normally. + +--*/ + +{ + USHORT protseq; + PWSTR pwstrT; + CDSA dsaBindings; + + if (!IsRunning()) + { + return OR_NOSERVER; + } + + if (_fLocal) + { + dsaBindings.Assign(_pProcess->GetLocalBindings()); + +#ifndef _CHICAGO_ + protseq = ID_LPC; +#else // always use WMSG on Win95 for local servers + protseq = ID_WMSG; +#endif // _CHICAGO_ + + } + else + { + protseq = _protseq; // use the one we set when this was created + DUALSTRINGARRAY *pdsa = _info._dsaBindings; // auto conversion + dsaBindings.Assign(pdsa); // noncopying assignment + } + + pwstrT = FindMatchingProtseq(protseq, dsaBindings->aStringArray); + + ASSERT(pwstrT != NULL && "OR: Didn't find a matching binding for oxid"); + + pInfo->psa = + GetStringBinding( + pwstrT, + dsaBindings->aStringArray + dsaBindings->wSecurityOffset + ); + + if (0 == pInfo->psa) + { + return OR_NOMEM; + } + + pInfo->dwTid = _info._dwTid; + pInfo->dwPid = _info._dwPid; + pInfo->dwAuthnHint = _info._dwAuthnHint; + pInfo->ipidRemUnknown = _info._ipidRemUnknown; + + return(OR_OK); +} + + + +ORSTATUS +COxid::GetRemoteInfo( + IN USHORT cClientProtseqs, + IN USHORT *aClientProtseqs, + IN USHORT cInstalledProtseqs, + IN USHORT *aInstalledProtseqs, + OUT OXID_INFO *pInfo + ) +/*++ + +Routine Description: + + Returns the OXID_INFO structure for this oxid for remote clients. + +Arguments: + + pInfo - Will contain the standard info, a single _expanded_ + string binding and complete security bindings. + +Return Value: + + OR_NOMEM - Unable to allocate a parameter. + + OR_OK - Normally. + +--*/ + +{ + PWSTR pwstrT; + ORSTATUS status = OR_OK; + + if (!IsRunning()) + { + return OR_NOSERVER; + } + + ASSERT(_fLocal); // Do not resolve remote servers for remote clients! + + DUALSTRINGARRAY * pdsaBindings = _pProcess->GetLocalBindings(); + + pwstrT = FindMatchingProtseq( + cClientProtseqs, + aClientProtseqs, + pdsaBindings->aStringArray + ); + + if ( pwstrT == NULL ) // try lazy use of protseq(s) + { + status = _pProcess->UseProtseqIfNeeded( + cClientProtseqs, + aClientProtseqs, + cInstalledProtseqs, + aInstalledProtseqs + ); + + pdsaBindings = _pProcess->GetLocalBindings(); + + pwstrT = FindMatchingProtseq( + cClientProtseqs, + aClientProtseqs, + pdsaBindings->aStringArray + ); + + if ( status != OR_OK || pwstrT == NULL ) + { + ComDebOut((DEB_OXID,"OR: Didn't find a matching binding for oxid %08x in mid %08x\n", + GetOXID(), GetMID())); + + return OR_I_NOPROTSEQ; + } + } + + DUALSTRINGARRAY *pdsaT = + GetStringBinding( + pwstrT, + pdsaBindings->aStringArray + pdsaBindings->wSecurityOffset + ); + + if (pdsaT != NULL) + { + pInfo->psa = CompressStringArray(pdsaT,FALSE); + MIDL_user_free(pdsaT); + } + + + if (NULL == pdsaT || NULL == pInfo->psa) + { + return OR_NOMEM; + } + + pInfo->dwTid = 0; + pInfo->dwPid = 0; + pInfo->dwAuthnHint = _info._dwAuthnHint; + pInfo->ipidRemUnknown = _info._ipidRemUnknown; + + return(status); +} + + + +ORSTATUS +COxid::StartRundownThreadIfNecessary() +{ + DWORD dwThrdId; + + if (_fApartment || !IsLocal()) // rundown timer is attached to window + // or rundown handled by ping server + { + ASSERT(!_hRundownThread); + return OR_OK; + } + + if (_fRundownThreadStarted) // BUGBUG: We do not want a rundown + // thread for each remote OXID + { + ASSERT(_hRundownThread); + return OR_OK; + } + + _hRundownThread = CreateThread( + NULL, 0, + RundownThread, + this, 0, &dwThrdId); + + if (_hRundownThread) + { + _fRundownThreadStarted = TRUE; + return OR_OK; + } + else + { + return GetLastError(); + } +} + + + + +ORSTATUS +COxid::StopRundownThreadIfNecessary() +{ + if (_fRundownThreadStarted) + { + ASSERT(_hRundownThread); + + if (CloseHandle(_hRundownThread)) + { + _fRundownThreadStarted = FALSE; + _hRundownThread = NULL; + return OR_OK; + } + else + { + return GetLastError(); + } + } + else + { + ASSERT(!_hRundownThread); + return OR_OK; + } +} + + +ORSTATUS +COxid::StopTimerIfNecessary() // must be called by owner thread +{ + ORSTATUS status = OR_OK; + + if (_fApartment) + { + // find the HWND for this thread + + COleTls tls; + HWND hWindow = (HWND)((OXIDEntry *)tls->pOXIDEntry)->hServerSTA; + + if (!KillTimer(hWindow,IDT_DCOM_RUNDOWN)) + { + status = GetLastError(); + } + } + + return status; +} + +void +CheckForCrashedProcessesIfNecessary() +{ + CTime CurrentTime; + + // don't check too often + if (CurrentTime - CTime(*gpdwLastCrashedProcessCheckTime) < BasePingInterval) + { + return; + } + + // timestamp the check + *gpdwLastCrashedProcessCheckTime = CurrentTime; + + CProcessTableIterator procIter(*gpProcessTable); + + CProcess *pNextProcess; + + while (pNextProcess = procIter.Next()) + { + if (pNextProcess->HasCrashed()) + { + // ASSERT(0); + + ComDebOut((DEB_OXID,"Process PID = %d has crashed\n", + pNextProcess->_processID)); + gpProcessTable->Remove(*pNextProcess); + pNextProcess->Rundown(); + } + else + { + ComDebOut((DEB_OXID,"Process PID = %d is running\n", + pNextProcess->_processID)); + } + } +} + + +void +COxid::RundownOidsIfNecessary( + IRundown *pRemUnk + ) +{ + ::CheckForCrashedProcessesIfNecessary(); + + if (_MyOids.Size() == 0) return; + + COidTableIterator Oids(_MyOids); + COid *pOid; + + while(pOid = Oids.Next()) + { + if (pOid->OkToRundown()) + { + // ASSERT(0); // BUGBUG: to debug Rundown + + // COid object says OK to run down. Try to run it down. + + OID Oid = pOid->GetOID(); + unsigned char fOkToRundown; + + if (IsLocal()) + { + pRemUnk->RundownOid(1,&Oid,&fOkToRundown); + } + else + { + fOkToRundown = TRUE; + } + + // If marshaller says OK to run down, get rid of it + + if (fOkToRundown) + { + pOid->Rundown(); + COid *pRemoved = _MyOids.Remove(*pOid); + ASSERT(pRemoved == pOid); + + // At this point, the references for pOid should drop to zero + } + } + } +} diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx new file mode 100644 index 000000000..fc318a8a9 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx @@ -0,0 +1,437 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + oxid.hxx + +Abstract: + + COxid objects represent OXIDs which are in use by processes on this machine. + These always contain a pointer to a process object and a ping set. + +Author: + + Satish Thatte [SatishT] + +Revision History: + + SatishT 02-07-96 Merged and simplified Client and Server Oxid classes + +--*/ + +#ifndef __OXID_HXX +#define __OXID_HXX + + +struct COxidInfo +{ + DWORD _dwTid; + DWORD _dwPid; + IPID _ipidRemUnknown; + DWORD _dwAuthnHint; + CDSA _dsaBindings; + + COxidInfo(const OXID_INFO& OxidInfo) + : _dwTid(OxidInfo.dwTid), + _dwPid(OxidInfo.dwPid), + _ipidRemUnknown(OxidInfo.ipidRemUnknown), + _dwAuthnHint(OxidInfo.dwAuthnHint), // BUGBUG: global setting OK? + _dsaBindings(OxidInfo.psa) // bindings are process-wide, except for remote OXIDs + {} + + operator OXID_INFO() + { + OXID_INFO result; + result.dwTid = _dwTid; + result.dwPid = _dwPid; + result.ipidRemUnknown = _ipidRemUnknown; + result.dwAuthnHint = _dwAuthnHint; + result.psa = _dsaBindings; + + return result; + } + + ORSTATUS Assign(const COxidInfo& Info); + + +}; + + + + +class CId2Key : public ISearchKey +{ +public: + + CId2Key(const ID id1, const ID id2) : _id1(id1), _id2(id2) { } + + virtual DWORD + Hash() + { + return( (DWORD)_id2 ^ (*((DWORD *)&_id2 + 1)) + ^ (DWORD)_id1 ^ (*((DWORD *)&_id1 + 1)) ); + } + + virtual BOOL + Compare(ISearchKey &tk) + { + CId2Key &idk = (CId2Key &)tk; + + return(idk._id2 == _id2 + && idk._id1 == _id1); + } + + ID Id1() + { + return _id1; + } + + ID Id2() + { + return _id2; + } + +protected: + + ID _id1,_id2; +}; + + + + + +class COid : public CTableElement, public CTime // the time of last release, implicitly + // set to creation time by constructor +/*++ + +Class Description: + + Each instance of this class represents an OID registered + by a client or a server on this machine. + +Members: + + _pOxid - A pointer to the OXID to which this OID belongs. + We own a reference. + +--*/ + +{ + private : + + COxid OR_BASED * _pOxid; + CId2Key _Key; + + public : + + COid( // complete constructor for remote OIDs + OID Oid, + COxid *pOxid + ); + + COid( // simpler constructor for local server allocation + COxid *pOxid + ); + + ~COid(); + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + operator ISearchKey&() // this allows us to be a ISearchKey as well + { + return _Key; + } + + virtual DWORD Release() + { + SetNow(); // timestamp the release + return CReferencedObject::Release(); + } + + OXID GetOID() + { + return _Key.Id1(); + } + + BOOL Match(COid *pOid) // BUGBUG: ?? + { + return(pOid->_pOxid == _pOxid); + } + + BOOL OkToRundown(); + + void Rundown(); + + COxid *GetOxid() + { + return(_pOxid); + } +}; + + +DEFINE_TABLE(COid) +DEFINE_LIST(COid) + +class COxid : public CTableElement +/*++ + +Class Description: + + Each instance of this class represents an OXID (object exporter, + a process or an apartment model thread). + + BUGBUG: ?? + + Each OXID is owned, + referenced, by the owning process and the OIDs registered by + that process for this OXID. + + +Members: + + _pProcess - Pointer to the process instance which owns this oxid. + + _info - Info registered by the process for this oxid. + + _pMid - Pointer to the machine ID for this OXID, we + own a reference. + + _fApartment - Server is aparment model if non-zero + + _fRunning - Process has not released this oxid if non-zero. + +--*/ +{ + friend class CProcess; + friend class COid; + +private: + + CProcess OR_BASED *_pProcess; + COxidInfo _info; + CMid OR_BASED *_pMid; + BOOL _fApartment:1; + BOOL _fRunning:1; + BOOL _fLocal:1; + BOOL _fRundownThreadStarted:1; + HANDLE _hRundownThread; + CId2Key _Key; + USHORT _protseq; + + COidTable _MyOids; + +public: + + COxid( + OXID Oxid, // constructor for remote OXIDs + CMid *pMid, + USHORT wProtseq, + OXID_INFO &OxidInfo + ); + + COxid( // constructor for local OXIDs + CProcess *pProcess, + OXID_INFO &OxidInfo, + BOOL fApartment + ); + + + + ~COxid(); + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + operator ISearchKey&() // this allows us to be a ISearchKey as well + { + return _Key; + } + + DWORD GetTid() + { + return(_info._dwTid); + } + + BOOL IsRunning() + { + return(_fRunning); + } + + BOOL IsLocal() + { + return(_fLocal); + } + + BOOL Apartment() + { + return(_fApartment); + } + + MID GetMID() + { + return _Key.Id2(); + } + + OXID GetOXID() + { + return _Key.Id1(); + } + + CMid *GetMid() + { + return(OR_FULL_POINTER(CMid,_pMid)); + } + + SETID GetSetid(); + + ORSTATUS + COxid::UpdateInfo(OXID_INFO *pInfo) + { + ASSERT(pInfo); + + return _info.Assign(*pInfo); + } + + ORSTATUS GetInfo( + OUT OXID_INFO * + ); + + ORSTATUS GetRemoteInfo( + IN USHORT cClientProtseqs, + IN USHORT *aClientProtseqs, + IN USHORT cInstalledProtseqs, + IN USHORT *aInstalledProtseqs, + OUT OXID_INFO *pInfo + ); + + void RundownOids(USHORT cOids, + OID aOids[], + BYTE aStatus[]); + + ORSTATUS LazyUseProtseq(USHORT, USHORT[]); + + void StopRunning(); + + ORSTATUS StartRundownThreadIfNecessary(); + + ORSTATUS StopRundownThreadIfNecessary(); + + ORSTATUS StopTimerIfNecessary(); // must be called by owner thread + + ORSTATUS OwnOid(COid *pOid) + { + return _MyOids.Add(pOid); // acquires a reference + } + + COid * DisownOid(COid *pOid); + + void ReleaseAllOids(); + +private: + + friend VOID CALLBACK RundownTimerProc( + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime // current system time + ); + + friend DWORD _stdcall RundownThread(void *self); + + friend DWORD _stdcall PingThread(void); + + void RundownOidsIfNecessary(IRundown *); +}; + + +DEFINE_TABLE(COxid) + +// +// decl for rundown thread function -- the parameter is the self pointer +// + +DWORD _stdcall RundownThread(void *pSelf); + + + +// +// Inline COid methods which depend on COxid methods +// + + +inline +COid::COid( // complete constructor for remote OIDs + OID Oid, + COxid *pOxid + ) : + _Key(Oid,pOxid->GetMID()), + _pOxid(OR_BASED_POINTER(COxid,pOxid)) +{ + ASSERT(_pOxid); + _pOxid->Reference(); +} + + +inline +COid::COid( // simpler constructor for local server allocation + COxid *pOxid + ) : + _Key(AllocateId(),pOxid->GetMID()), + _pOxid(OR_BASED_POINTER(COxid,pOxid)) +{ + ASSERT(_pOxid); + _pOxid->Reference(); +} + + +inline +COid::~COid() +{ + ASSERT(_pOxid); + _pOxid->Release(); + + COid *pt = gpOidTable->Remove(*this); // should really not be there + ASSERT(pt == NULL && "Oid object still in global table during destruct"); +} + +inline +BOOL +COid::OkToRundown() +{ + DWORD dwRefs = References(); + ASSERT(dwRefs >= 2); + + if (dwRefs > 2) + { + return FALSE; + } + else + { + // Check if the time since creation or last release is less than timeout + if ((CTime() - *this) < BaseTimeoutInterval) + { + return FALSE; + } + } + + return TRUE; +} + +#endif // __OXID_HXX diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/process.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/process.cxx new file mode 100644 index 000000000..980aa6ee1 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/process.cxx @@ -0,0 +1,453 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Process.cxx + +Abstract: + + Process objects represent local clients and servers. These + objects live as context handles. + + There are relatively few of these objects in the universe. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-20-95 Bits 'n pieces + +--*/ + +#include <or.hxx> + +#if DBG + +void CProcess::IsValid() +{ + _MyOxids.IsValid(); + _UsedOids.IsValid(); + _dsaLocalBindings.IsValid(); + _dsaRemoteBindings.IsValid(); + References() > 0; +} + +#endif // DBG + + +CProcess::CProcess(long ConnectId) + : + _MyOxids(4), // BUGBUG: these constants should be declared elsewhere + _UsedOids(16), + _hProcess(NULL) +{ + _processID = GetCurrentProcessId(); + _Key.Init(ConnectId); +} + + + +RPC_BINDING_HANDLE +CProcess::GetBindingHandle() +{ + VALIDATE_METHOD + + USHORT protseq; + + if (_hProcess) return _hProcess; + +#ifndef _CHICAGO_ + protseq = ID_LPC; +#else + protseq = ID_WMSG; +#endif + + PWSTR pwstrMatch = FindMatchingProtseq(protseq, _dsaLocalBindings->aStringArray); + + ASSERT(pwstrMatch); + + PWSTR pwstrProtseq = GetProtseq(*pwstrMatch); + + int l = OrStringLen(pwstrMatch) + OrStringLen(pwstrProtseq) + 2; + + PWSTR pwstrBinding = (WCHAR *) PrivMemAlloc(l * sizeof(WCHAR)); + + if (!pwstrBinding) + { + return (NULL); + } + + OrStringCopy(pwstrBinding, pwstrProtseq); + OrStringCat(pwstrBinding, L":"); + OrStringCat(pwstrBinding, pwstrMatch + 1); + + RPC_STATUS status = RpcBindingFromStringBinding( + pwstrBinding, + &_hProcess + ); + + ASSERT(status == RPC_S_OK); + + PrivMemFree(pwstrBinding); + + return _hProcess; +} + +void +CProcess::Rundown() +// The process has crashed or disconnected and this object is being cleaned up. +{ + COxid *pOxid; + COid *pOid; + ORSTATUS status; + + CClassReg * pReg; + + while ( (pReg = _RegClasses.Pop()) != NULL ) + { +#ifdef _CHICAGO_ // BUGBUG: not essential, don't bother with on NT shared resolver + SCMRemoveRegistration( pReg->_Clsid, + pReg->_Reg + ); +#endif + // delete pReg; BUGBUG: do not explicitly delete refcounted objects! + } + + if (_MyOxids.Size()) + { + COxidTableIterator Oxids(_MyOxids); + + while(pOxid = Oxids.Next()) + { + DisownOxid(pOxid,FALSE); // not the server thread + } + } + + _UsedOids.RemoveAll(); +} + + +// This thing has 2 kernel traps. Best not done too often. + +BOOL +CProcess::HasCrashed() +{ + VALIDATE_METHOD + + // the process doing the check is definitely alive + + if (_processID == MyProcessId /* && _Key == Key */) + { + return FALSE; + } + + HANDLE hp = OpenProcess( + PROCESS_QUERY_INFORMATION, + FALSE, + _processID + ); + + if (!hp) // we assume the process is terminated and gone + { + return FALSE; // BUGBUG: still not a good choice + } + + // OK, we have a handle. Now do a sanity check to make sure this is + // the same process. + + // BUGBUG: still no good sanity check available -- this means we may + // not have a handle to the right process -- therefore some crashes + // may go undetected. Unlikely, but possible. + + // One possibility is to cache the address of gpProcess in the process + // object and do a ReadProcessMemory on the process handle as a sanity + // check -- crude but workable since Win95 has no security against it + + DWORD dwExitCode; + + GetExitCodeProcess(hp,&dwExitCode); + + if (STILL_ACTIVE == dwExitCode) + { + return FALSE; + } + else + { + return TRUE; + } +} + + +RPC_STATUS +CProcess::ProcessBindings( + IN DUALSTRINGARRAY *pdsaStringBindings + ) +/*++ + +Routine Description: + + Updates the string bindings associated with this process. + +Arguments: + + psaStringBindings - The expanded string bindings of the process + assumed to be allocated with "new" in local (not shared) memory + +Return Value: + + OR_NOMEM - unable to allocate storage for the new string arrays. + + OR_OK - normally. + +--*/ + +{ + VALIDATE_METHOD + + ORSTATUS status = OR_OK; + + ASSERT(pdsaStringBindings && dsaValid(pdsaStringBindings) + && "Process given invalid bindings to store"); + + status = _dsaLocalBindings.Assign(pdsaStringBindings, FALSE); // FALSE = uncompressed + + delete [] (char*)pdsaStringBindings; // Assign makes a compressed copy + + ASSERT(_dsaLocalBindings.Valid()); + + _dsaRemoteBindings.Assign(NULL,TRUE); // wipes it out -- filled again when needed + + return(OR_OK); +} + + + +DUALSTRINGARRAY * +CProcess::GetRemoteBindings(void) +{ + VALIDATE_METHOD + + ORSTATUS Status; + + if (_dsaRemoteBindings.Empty() && !_dsaLocalBindings.Empty()) + { + Status = _dsaRemoteBindings.ExtractRemote(_dsaLocalBindings); + + if (Status != OR_OK) + { + ASSERT(Status == OR_NOMEM); + return(NULL); + } + } + + if (!_dsaRemoteBindings.Empty()) + { + return _dsaRemoteBindings; + } + else return(NULL); +} + + + +void +CProcess::DisownOxid(COxid *pOxid, BOOL fOxidThreadCalling) +{ + VALIDATE_METHOD + + pOxid->StopRunning(); + + if (fOxidThreadCalling) + { + pOxid->StopRundownThreadIfNecessary(); + pOxid->StopTimerIfNecessary(); + } + + COxid *pIt = gpOxidTable->Remove(*pOxid); + ASSERT(pIt==pOxid); + + pIt = _MyOxids.Remove(*pOxid); + ASSERT(pIt==pOxid); + + // pOxid may be an invalid pointer now +} + + + + +COid * +CProcess::DropOid(COid *pOid) + +/*++ + +Routine Description: + + Removes an OID from this list of OID in use by this process. + +Arguments: + + pOid - The OID to remove. + +Return Value: + + non-NULL - the pointer actually removed. (ASSERT(retval == pOid)) + It will be released by the process before return, + so you should not use the pointer unless you know you + have another reference. + + NULL - not in the list + +--*/ + +{ + VALIDATE_METHOD + + COid *pIt = _UsedOids.Remove(*pOid); // releases our reference + + if (pIt) + { + ASSERT(pIt == pOid); + return(pIt); + } + + return(NULL); +} + + +void +CProcess::AddClassReg(GUID Clsid, DWORD Reg) +{ + VALIDATE_METHOD + + CClassReg * pReg = new CClassReg( Clsid, Reg ); + + if (pReg) + { + ORSTATUS status; + + _RegClasses.Insert(status,pReg); + } +} + +void +CProcess::RemoveClassReg(GUID Clsid, DWORD Reg) +{ + VALIDATE_METHOD + + CClassReg * pReg = _RegClasses.Remove(CRegKey(Reg)); + // delete pReg; BUGBUG: do not explicitly delete refcounted objects! +} + + + +ORSTATUS // called only within the SCMOR process +CProcess::UseProtseqIfNeeded( + IN USHORT cClientProtseqs, + IN USHORT aClientProtseqs[], + IN USHORT cInstalledProtseqs, + IN USHORT aInstalledProtseqs[] + ) +{ + VALIDATE_METHOD + + ORSTATUS status; + PWSTR pwstrProtseq = NULL; + + // Another thread may have used the protseq in the mean time. + + ASSERT(!_dsaLocalBindings.Empty()); + + pwstrProtseq = FindMatchingProtseq(cClientProtseqs, + aClientProtseqs, + _dsaLocalBindings->aStringArray + ); + + if (NULL != pwstrProtseq) + { + return(OR_OK); + } + + // No protseq shared between the client and the OXIDs' server. + // Find a matching protseq. + + USHORT i,j; + + for(i = 0; i < cClientProtseqs && pwstrProtseq == NULL; i++) + { + for(j = 0; j < cInstalledProtseqs; j++) + { + if (aInstalledProtseqs[j] == aClientProtseqs[i]) + { + ASSERT(FALSE == IsLocal(aInstalledProtseqs[j])); + + pwstrProtseq = GetProtseq(aInstalledProtseqs[j]); + break; + } + } + } + + if (NULL == pwstrProtseq) + { + // No shared protseq, must be a bug since the client managed to call us. +#if DBG + if (cClientProtseqs == 0) + { + ComDebOut((DEB_OXID,"OR: Client OR not configured to use remote protseqs\n")); + } + else + { + ComDebOut((DEB_OXID,"OR: Client called on an unsupported protocol: \ + %d %p %p \n", cClientProtseqs, aClientProtseqs, aInstalledProtseqs)); + ASSERT(0); + } +#endif + + return(OR_NOSERVER); + } + + DUALSTRINGARRAY *pdsaStringBindings = NULL, + *pdsaSecurityBindings = NULL, + *pdsaMergedBindings = NULL; + + { + CTempReleaseSharedMemory temp; + + if (GetBindingHandle() != NULL) // initialize _hProcess if necessary + { + status = ::UseProtseq(_hProcess, + pwstrProtseq, + &pdsaStringBindings, + &pdsaSecurityBindings + ); + } + else + { + return OR_NOSERVER; // BUGBUG: is that the right code? + } + } + + if (status != RPC_S_OK) return status; + + OrDbgPrint(("OR: Lazy use protseq: %S in process %p - %d\n", + pwstrProtseq, this, status)); + + // Update this process' state to include the new bindings. + + status = MergeBindings( + pdsaStringBindings, + pdsaSecurityBindings, + &pdsaMergedBindings + ); + + ASSERT(status == OR_OK); + status = ProcessBindings(pdsaMergedBindings); + MIDL_user_free(pdsaStringBindings); + MIDL_user_free(pdsaSecurityBindings); + + return(status); +} + + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/process.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/process.hxx new file mode 100644 index 000000000..88c45df86 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/process.hxx @@ -0,0 +1,283 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Process.hxx + +Abstract: + + Process objects represent local clients and servers. These + objects live as context handles. + + There are relativly few of these objects in the universe. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-11-95 Bits 'n pieces + MarioGo 01-06-96 Based on CReferencedObject + +--*/ + +#ifndef __PROCESS_HXX +#define __PROCESS_HXX + + +// At the moment there does not seem to be any reason +// to make this a base class for CId2Key. + +class CIdKey : public ISearchKey +{ +public: + + CIdKey() {} + + CIdKey(const ID Id) + { + Init(Id); + } + + void Init(const ID Id) + { + _id = Id; + } + + virtual DWORD + Hash() + { + return((DWORD)_id ^ (*((DWORD *)&_id + 1)) ); + } + + virtual BOOL + Compare(ISearchKey &tk) + { + CIdKey &idk = (CIdKey &)tk; + + return(idk._id == _id); + } + + ID Id() + { + return _id; + } + +protected: + + ID _id; +}; + + + + +class CRegKey : public ISearchKey +{ +public: + + CRegKey(DWORD reg) + { + _reg = reg; + } + + virtual DWORD // dummy method in this class + Hash() + { + return 0; + } + + virtual BOOL + Compare(ISearchKey &sk) + { + CRegKey &rk = (CRegKey &)sk; + + return(rk._reg == _reg); + } + + operator DWORD() + { + return _reg; + } + +protected: + + DWORD _reg; +}; + + +class CClassReg : public CTableElement +{ +public : + + GUID _Clsid; + CRegKey _Reg; + + CClassReg( GUID clsid, DWORD reg ) : _Clsid(clsid), _Reg(reg) {} + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + virtual DWORD // dummy method in this class + Hash() + { + return _Reg.Hash(); + } + + virtual operator ISearchKey&() + { + return _Reg; + } +}; + + +void SCMRemoveRegistration( // BUGBUG: This should be in a proper header + GUID Clsid, + DWORD Reg + ); + +class CProcess : public CTableElement +/*++ + +Class Description: + + An instance of this class is created for each process + using the OR as either a client or server. + + The process object is referenced by server OXIDs and has + one implicit reference by the actual process (which is + dereferenced during the context rundown). Instances of + these objects are managed by the RPC runtime as context + handles. + +Members: + + _dsaLocalBindings - The string bindings of the process, including + local only protseqs + + _dsaRemoteBindings - A subset of _dsaLocalBindings not containing + any local-only protseqs + + _blistOxids - A CBList containing pointers to the COxid's + owned by this process, if any. + + _blistOids - A CBList of pointers to COid's which this + process is using and referencing, if any. + +--*/ + +{ + +private: + + friend void CheckForCrashedProcessesIfNecessary(); + friend DWORD _stdcall PingThread(void); + + DWORD _processID; + CIdKey _Key; + + CDSA _dsaLocalBindings; + CDSA _dsaRemoteBindings; + + COxidTable _MyOxids; + COidTable _UsedOids; + + RPC_BINDING_HANDLE _hProcess; // for pingserver use only + + TCSafeLinkList<CClassReg> _RegClasses; + +public: + +#if DBG + void IsValid(); + DECLARE_VALIDITY_CLASS(CProcess) +#endif + + CProcess(long); + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + + operator ISearchKey&() + { + return _Key; + } + + DWORD GetProcessID() { return _processID; } + + RPC_STATUS ProcessBindings(DUALSTRINGARRAY *); + + RPC_BINDING_HANDLE GetBindingHandle(); + + DUALSTRINGARRAY *GetLocalBindings(void) + { + VALIDATE_METHOD + + return _dsaLocalBindings; + } + + DUALSTRINGARRAY *GetRemoteBindings(void); + + ORSTATUS OwnOxid(COxid *pOxid) + { + VALIDATE_METHOD + + return _MyOxids.Add(pOxid); // acquires a reference + } + + void DisownOxid(COxid *pOxid, BOOL fOxidThreadCalling); + + BOOL IsOwner(COxid *pOxid) + { + VALIDATE_METHOD + + COxid *pFound = _MyOxids.Lookup(*pOxid); + ASSERT(!pFound || pFound == pOxid); + return pFound == pOxid; + } + + ORSTATUS AddOid(COid *pOid) + { + VALIDATE_METHOD + + return _UsedOids.Add(pOid); // this acquires a reference for us + } + + COid *DropOid(COid *); + + void AddClassReg(GUID Clsid, DWORD Reg); + + void RemoveClassReg(GUID Clsid, DWORD Reg); + + ORSTATUS UseProtseqIfNeeded( + IN USHORT cClientProtseqs, + IN USHORT aClientProtseqs[], + IN USHORT cInstalledProtseqs, + IN USHORT aInstalledProtseqs[] + ); + + void Rundown(); + + BOOL HasCrashed(); +}; + +DEFINE_TABLE(CProcess) + +#endif // __PROCESS_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx new file mode 100644 index 000000000..745b0157c --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx @@ -0,0 +1,82 @@ + +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + RefObj.hxx + +Abstract: + + Generic base class for reference counted objects. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 12-15-95 Bits in the 'ol bucket + +--*/ + +#ifndef __REFERENCED_OBJECTS_HXX +#define __REFERENCED_OBJECTS_HXX + +class CReferencedObject +{ +public: + + CReferencedObject() + : _references(0) + { + } + + virtual ~CReferencedObject() { ASSERT(_references == 0); } + + virtual void Reference() + { + ASSERT(_references >= 0); + _references++; + } + + virtual DWORD Release() + { + if ( 0 == Dereference()) + { + delete this; + return(0); + } + // this pointer maybe invalid here. + return(1); + } + + LONG Dereference() + // Used for objects which override Release(). + { + ASSERT(_references); + return(_references--); + } + + DWORD References() + { + // Must be called an exclusive lock held or it is meaningless. + ASSERT(_references >= 0); + return(_references); + } + + BOOL WillBeDeletedIfReleased() + { + return _references == 1; + } + +private: + + CInterlockedInteger _references; // BUGBUG: no real need for interlocking just now + // since all ops happen under global lock + +}; + +#endif // __REFERENCED_OBJECTS_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx new file mode 100644 index 000000000..8c02d3bd2 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx @@ -0,0 +1,202 @@ +#include <or.hxx> +#include <scmfuns.hxx> + +void +ScmProcessAddClassReg(void * hProcess, REFCLSID rclsid, DWORD dwReg) +{ + ASSERT(hProcess==gpProcess); + ((CProcess*)hProcess)->AddClassReg( rclsid, dwReg ); +} + +void +ScmProcessRemoveClassReg(void * hProcess, REFCLSID rclsid, DWORD dwReg) +{ + ASSERT(hProcess==gpProcess); + ((CProcess*)hProcess)->RemoveClassReg( rclsid, dwReg ); +} + +void +ScmObjexGetThreadId(LPDWORD pThreadID) // BUGBUG: Why not AllocateID?? +{ + CProtectSharedMemory protector; // locks through rest of lexical scope + + *pThreadID = (*gpNextThreadID)++; +} + +RPC_BINDING_HANDLE +SCMGetBindingHandle(long Id) +{ + RPC_BINDING_HANDLE hResult = NULL; + CIdKey Key(Id); + CProcess *pProcess = gpProcessTable->Lookup(Key); + ASSERT(pProcess); + RPC_BINDING_HANDLE hTemp = pProcess->GetBindingHandle(); + + if (hTemp != NULL) + { + RPC_STATUS status = RpcBindingCopy(hTemp,&hResult); + + if (status != RPC_S_OK) + { + return NULL; + } + else + { + return hResult; + } + } + else + { + return NULL; + } +} + +void +SCMRemoveClassReg( + long Id, + GUID Clsid, + DWORD Reg + ) +{ + CIdKey Key(Id); + CProcess *pProcess = gpProcessTable->Lookup(Key); + ASSERT(pProcess); + pProcess->RemoveClassReg(Clsid,Reg); +} + +void +SCMAddClassReg( + long Id, + GUID Clsid, + DWORD Reg + ) +{ + CIdKey Key(Id); + CProcess *pProcess = gpProcessTable->Lookup(Key); + ASSERT(pProcess); + pProcess->AddClassReg(Clsid,Reg); +} + + + +ORSTATUS OrResolveOxid( + IN OXID Oxid, + IN USHORT cRequestedProtseqs, + IN USHORT aRequestedProtseqs[], + IN USHORT cInstalledProtseqs, + IN USHORT aInstalledProtseqs[], + OUT OXID_INFO& OxidInfo + ) +{ + ComDebOut((DEB_OXID, "_ResolveOxid OXID = %08x\n",Oxid)); + + COxid *pOxid; + ORSTATUS status = OR_OK; + + CProtectSharedMemory protector; // locks through rest of lexical scope + + pOxid = gpOxidTable->Lookup(CId2Key(Oxid, gLocalMID)); + + if (pOxid) + { + status = pOxid->GetRemoteInfo( + cRequestedProtseqs, + aRequestedProtseqs, + cInstalledProtseqs, + aInstalledProtseqs, + &OxidInfo + ); + + return status; + } + else // the OXID should already be registered by server + { + return OR_BADOXID; + } +} + + +void GetLocalORBindings( + DUALSTRINGARRAY * &pdsaMyBindings + ) +{ + pdsaMyBindings = gpLocalDSA; +} + +void +GetRegisteredProtseqs( + USHORT &cMyProtseqs, + USHORT * &aMyProtseqs + ) +{ + cMyProtseqs = *gpcRemoteProtseqs; + aMyProtseqs = gpRemoteProtseqIds; +} + +void +ScmGetNextBindingHandleForRemoteScm(WCHAR * pwszServerName, handle_t * phRemoteScm, LPBOOL pbsecure, int * pindex, USHORT * pprotseq, RPC_STATUS * pstatus) +{ + + WCHAR * pStringBinding = NULL; + + *phRemoteScm = NULL; + *pbsecure = FALSE; + +/* + if (*pindex == -1) + { + *pindex = 0; + } + else + { + *pindex += 1; + if (*pindex < cMyProtSeqs) + { + *pindex = -1; + return; + } + } +*/ + + *pindex = -1; + return; + +/* + *pprotseq = aMyProtseqs[*pindex]; + *pstatus = RpcStringBindingCompose( + NULL, + gaProtseqInfo[*pprotseq].pwstrProtseq, + pwszServerName, + gaProtseqInfo[*pprotseq].pwstrEndpoint, + NULL, + &pStringBinding ); + + if ( *pstatus != RPC_S_OK ) + return; + + *pstatus = RpcBindingFromStringBinding( pStringBinding, phRemoteSCM ); + + RpcStringFree( &pStringBinding ); + pStringBinding = NULL; + + if ( *pstatus != RPC_S_OK ) + return; + + *pbsecure = TRUE; + + *pstatus = RpcBindingSetAuthInfo( + phRemoteSCM, + NULL, + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_AUTHN_WINNT, + NULL, + 0 ); + + if ( *pstatus != RPC_S_OK ) + { + *pbsecure = FALSE; + *pstatus = RPC_S_OK; + } + +*/ +} diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx new file mode 100644 index 000000000..d93ec898b --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx @@ -0,0 +1,38 @@ +void +ScmProcessAddClassReg(void * phprocess, REFCLSID rclsid, DWORD dwReg); + +void +ScmProcessRemoveClassReg(void * phprocess, REFCLSID rclsid, DWORD dwReg); + +void +ScmObjexGetThreadId(LPDWORD pThreadID); // BUGBUG: Why not AllocateID?? + + +ORSTATUS OrResolveOxid( + IN OXID Oxid, + IN USHORT cRequestedProtseqs, + IN USHORT aRequestedProtseqs[], + IN USHORT cInstalledProtseqs, + IN USHORT aInstalledProtseqs[], + OUT OXID_INFO& OxidInfo + ); + +void +GetRegisteredProtseqs( + USHORT &cMyProtseqs, + USHORT * &aMyProtseqs + ); + +void GetLocalORBindings( + DUALSTRINGARRAY * &pdsaMyBindings + ); + +void +ScmGetNextBindingHandleForRemoteScm( + WCHAR * pwszServerName, + handle_t * phRemoteScm, + LPBOOL pbsecure, + int * pindex, + USHORT * pprotseq, + RPC_STATUS * pstatus + ); diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/set.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/set.hxx new file mode 100644 index 000000000..5d20fe4ea --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/set.hxx @@ -0,0 +1,104 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Manager.cxx + +Abstract: + + InProc OR interface + +Author: + + Satish Thatte [SatishT] Feb-07-1996 + +Revision Hist: + + SatishT 02-07-96 Created + +--*/ + + + + +class CPingSet : public CTableElement +{ +public: + + CPingSet( + SETID Id, + RPC_AUTHZ_HANDLE hClient, // we keep the string given, make no copy + ULONG AuthnLevel, + ULONG AuthnSvc, + ULONG AuthzSvc + ) + : _setID(Id), + _hClient(hClient), + _AuthnLevel(AuthnLevel), + _AuthnSvc(AuthnSvc), + _AuthzSvc(AuthzSvc) + { + _dwLastPingTime = _dwCreationTime = GetCurrentTime(); + ; + } + + virtual operator ISearchKey&() + { + return _setID; + } + + void + SimplePing() + { + _dwLastPingTime = GetCurrentTime(); + } + + RPC_AUTHZ_HANDLE + GetClient() + { + return _hClient; + } + + BOOL + CheckAndUpdateSequenceNumber(USHORT sequence) + { + // note: this handles overflow cases, too. + USHORT diff = sequence - _sequence; + + if (diff && diff <= BaseNumberOfPings) + { + _sequence = sequence; + return(TRUE); + } + return(FALSE); + } + + ORSTATUS + ComplexPing( + USHORT sequenceNum, + USHORT cAddToSet, + USHORT cDelFromSet, + OID aAddToSet[], + OID aDelFromSet[] + ); + +private: + + COidTable _pingSet; + CIdKey _setID; + USHORT _sequence; + RPC_AUTHZ_HANDLE _hClient; + DWORD _dwLastPingTime; + DWORD _dwCreationTime; + ULONG _AuthnLevel; + ULONG _AuthnSvc; + ULONG _AuthzSvc; +}; + + +DEFINE_TABLE(CPingSet) + + + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/string.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/string.cxx new file mode 100644 index 000000000..84dd0e0b2 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/string.cxx @@ -0,0 +1,685 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + String.cxx + +Abstract: + + Methods of construction of various kinds of DUALSTRINGARRAYs. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 04-01-95 Bits 'n pieces + MarioGO 01-??-96 STIRNGARRYs replaced by DUALSTRINGARRAYs + +--*/ + +#include <or.hxx> +#include <dcomss.h> // GetProtseq et al + +static CONST WCHAR aCallbackSecurity[] = L"Security=Identification Static True"; +static CONST DWORD dwCallbackSecurityLength = sizeof(aCallbackSecurity)/sizeof(WCHAR); + +RPC_BINDING_HANDLE +GetBinding( + IN PWSTR pCompressedBinding + ) +{ + ASSERT(pCompressedBinding); + + PWSTR pwstrStringBinding; + PWSTR pwstrProtseq = GetProtseq(*pCompressedBinding); + PWSTR pwstrT; + RPC_STATUS Status; + RPC_BINDING_HANDLE bhReturn; + BOOL fLocal = FALSE; + + if (!pwstrProtseq) + { + return(0); + } + + int size = OrStringLen(pwstrProtseq) + OrStringLen(pCompressedBinding); + + if (*pCompressedBinding == ID_LPC || *pCompressedBinding == ID_WMSG) + { + fLocal = TRUE; + size += dwCallbackSecurityLength + 1; // +1 for ',' + } + + pwstrStringBinding = (PWSTR) new WCHAR[size]; + if (!pwstrStringBinding) + { + return(0); + } + + OrStringCopy(pwstrStringBinding, pwstrProtseq); + pwstrT = OrStringSearch(pwstrStringBinding, 0); + *pwstrT = L':'; + pwstrT++; + *pwstrT = 0; + OrStringCopy(pwstrT, pCompressedBinding + 1); + + if (fLocal) + { + // We assume we have an endpoint. + + pwstrT = OrStringSearch(pwstrT, 0); + pwstrT--; + if (*pwstrT != L']') + { + OrDbgPrint(("OR: Local string binding missing endpoint %S\n", + pwstrStringBinding)); + ASSERT(0); + return(0); + } + + *pwstrT = L','; + pwstrT++; + OrStringCopy(pwstrT, aCallbackSecurity); + pwstrT = OrStringSearch(pwstrT, 0); + *pwstrT = L']'; + *(pwstrT + 1) = 0; + } + + Status = + RpcBindingFromStringBinding( pwstrStringBinding, + &bhReturn); + +#if DBG + if (Status != RPC_S_OK) + { + OrDbgPrint(("OR: Unable to create binding for %S = %d\n", + pwstrStringBinding, + Status)); + } +#endif + + return(bhReturn); +} + + +RPC_BINDING_HANDLE +GetBindingToOr( + IN PWSTR pwstrCompressedBinding + ) +/*++ + +Routine Description: + + Gets an RPC binding to a remote object resolver given + a compressed string binding to the remote object resolver. + +Arguments: + + pwstrCompressedBinding - a compressed string binding without an endpoint. + +Return Value: + + 0 - failed to allocate memory or RpcBindingFromStringBinding failed. + + non-NULL - completed okay + +--*/ +{ + PWSTR protseq, endpoint; + PWSTR strbinding; + USHORT len; + RPC_BINDING_HANDLE bh = 0; + + ASSERT(pwstrCompressedBinding); + ASSERT(*pwstrCompressedBinding != 0); + + protseq = GetProtseq(*pwstrCompressedBinding); + endpoint = GetEndpoint(*pwstrCompressedBinding); + + if (0 == protseq || 0 == endpoint) + { + ASSERT(0); + return(0); + } + + len = 4; // ':' '[' ']' and '\0' + len += OrStringLen(protseq); + len += OrStringLen(endpoint); + len += OrStringLen(&pwstrCompressedBinding[1]); + + strbinding = new USHORT[len]; + + if (strbinding) + { + PWSTR pwstrT; + + OrStringCopy(strbinding, protseq); // protseq + + pwstrT = OrStringSearch(strbinding, 0); // : + *pwstrT = L':'; + pwstrT++; + *pwstrT = 0; + + OrStringCat(strbinding, &pwstrCompressedBinding[1]); // network address + + pwstrT = OrStringSearch(strbinding, 0); // [ + *pwstrT = L'['; + pwstrT++; + *pwstrT = 0; + + OrStringCat(strbinding, endpoint); // endpoint + + pwstrT = OrStringSearch(strbinding, 0); // ] + *pwstrT = L']'; + pwstrT++; + *pwstrT = 0; + + RPC_STATUS status = RpcBindingFromStringBinding(strbinding, &bh); + + ASSERT(bh == 0 || status == RPC_S_OK); + + delete strbinding; + } + + if (bh == 0) + { + OrDbgDetailPrint(("OR: Unable to bind to %S\n", pwstrCompressedBinding + 1)); + } + + return(bh); +} + + +DUALSTRINGARRAY * +GetStringBinding( + IN PWSTR pwstrCompressed, + IN PWSTR pwstrSecurityBindings + ) +/*++ + +Routine Description: + + Converts the compressed string binding into an expanded + string binding. An enpoint maybe optionally specified. + +Arguments: + + pwstrCompressed - a compressed string binding + + pwstrSecurityBindings - optional security bindings + too be tacked onto the end of the expanded string binding. + Terminated by two nulls. + +Return Value: + + NULL - out of memory + + non-NULL - a string binding. +--*/ +{ + DUALSTRINGARRAY *pT; + PWSTR protseq; + USHORT seccount; + + PWSTR t = pwstrSecurityBindings; + if (t && *t) + { + seccount = 0; + do + { + seccount++; + t++; + + if (*t == 0) + { + seccount++; + t++; + } + } + while(*t); + + seccount++; // final NULL + } + else + { + // Two nulls only. + seccount = 2; + } + + protseq = GetProtseq(*pwstrCompressed); + + int l = OrStringLen(pwstrCompressed) + OrStringLen(protseq) + seccount + 1 + 1; + + pT =(DUALSTRINGARRAY *)midl_user_allocate(sizeof(DUALSTRINGARRAY) + l * sizeof(WCHAR)); + + if (!pT) + { + return (0); + } + + pT->wNumEntries = l; + OrStringCopy(pT->aStringArray, protseq); + OrStringCat(pT->aStringArray, L":"); + OrStringCat(pT->aStringArray, pwstrCompressed + 1); + + if (pwstrSecurityBindings) + { + PWSTR t = pT->aStringArray; + t = OrStringSearch(t, 0); + t++; + *t = 0; // Second NULL on string bindings. + t++; + OrMemoryCopy(t, pwstrSecurityBindings, seccount*sizeof(WCHAR)); + } + else + { + // Add three NULLs, total of four. + PWSTR t = pT->aStringArray; + t = OrStringSearch(t, 0); + t[1] = 0; + t[2] = 0; + t[3] = 0; + } + + pT->wSecurityOffset = pT->wNumEntries - seccount; + + ASSERT(dsaValid(pT)); + + return(pT); +} + + +ORSTATUS +ConvertToRemote( + IN DUALSTRINGARRAY *pdsaLocal, + OUT DUALSTRINGARRAY **ppdsaRemote + ) +/* ++ + +Parameters: + pdsaLocal - An array of string bindings with compressed protseqs. + + ppdsaRemote - Will contain only those string bindings in pdsaLocal + which are not "IsLocal()". + + Note: *ppdsaRemote maybe used as a flag, don't set it to non-NULL + until it is valid. + +-- */ +{ + int iTotalSize; + int iSize; + USHORT *p1, *p2; + DUALSTRINGARRAY *pdsaT; + + // Size remote array + + // Final null terminator + iSize = 1; + + p1 = pdsaLocal->aStringArray; + + while(*p1) + { + if (! IsLocal(*p1) ) + { + iSize += OrStringLen(p1) + 1; + } + p1 = OrStringSearch(p1, 0) + 1; + } + + if (iSize == 1) + { + iSize = 2; // No non-local strings, need two terminators. + } + + iTotalSize = iSize + (pdsaLocal->wNumEntries - pdsaLocal->wSecurityOffset); + + pdsaT = new(iTotalSize * sizeof(WCHAR)) DUALSTRINGARRAY; + + if (!pdsaT) + { + return(OR_NOMEM); + } + + pdsaT->wNumEntries = iTotalSize; + pdsaT->wSecurityOffset = iSize; + + p2 = pdsaT->aStringArray; + + // Copy security bindings + OrMemoryCopy(p2 + iSize, + pdsaLocal->aStringArray + pdsaLocal->wSecurityOffset, + (iTotalSize - iSize) * sizeof(WCHAR)); + + if (iSize == 2) + { + // No non-local strings, fill in terminators and return. + *p2 = 0; + *(p2 + 1) = 0; + *ppdsaRemote = pdsaT; + + ASSERT(dsaValid(pdsaT)); + return(OR_OK); + } + + p1 = pdsaLocal->aStringArray; + + while(*p1) + { + if ( ! IsLocal(*p1) ) + { + OrStringCopy(p2, p1); + p2 = OrStringSearch(p2, 0) + 1; + } + + p1 = OrStringSearch(p1, 0) + 1; + } + + *p2 = 0; // Second terminator. + + *ppdsaRemote = pdsaT; + + ASSERT(dsaValid(pdsaT)); + return(OR_OK); +} + +DUALSTRINGARRAY * +CompressStringArray( + IN DUALSTRINGARRAY *pdsaExpanded, + IN BOOL fSharedMem + ) +/*++ + +Routine Description: + + Converts a stringarray of regular string bindings into a + compressed (protseq's replaced with WORD id's) array of + string bindings. + +Arguments: + + pdsaExpanded - the string array to compress. + Security information is copied. + +Return Value: + + 0 - failed to allocate memory. + + non-0 - compressed string array. + +--*/ +{ + int i, size; + USHORT *p1, *p2, *p3; + PWSTR pwstr; + DUALSTRINGARRAY *pdsaCompressed; + + // Compute size of result. + + p1 = pdsaExpanded->aStringArray; + + size = pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset; + + if (*p1 == 0) + { + size += 2; // two null terminators ONLY. + } + else + { + size += 1; // last null terminator + } + + while(*p1) + { + int sizeT = OrStringLen(p1); + + p2 = OrStringSearch(p1, L':'); // ':' is not valid in protseq. + if (p2) + { + size += sizeT + 1 - (p2 - p1); // proseq len (p2 - p1) become 1 for Id. + } + else + { + ASSERT(p2); + } + + p1 = OrStringSearch(p1, 0) + 1; + } + + if (fSharedMem) + { + pdsaCompressed = (DUALSTRINGARRAY*) + OrMemAlloc(sizeof(DUALSTRINGARRAY) + size * sizeof(WCHAR)); + } + else + { + pdsaCompressed = (DUALSTRINGARRAY*) + midl_user_allocate(sizeof(DUALSTRINGARRAY) + size * sizeof(WCHAR)); + } + + if (0 == pdsaCompressed) + { + return(0); + } + + pdsaCompressed->wNumEntries = size; + pdsaCompressed->wSecurityOffset = size - (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset); + p3 = pdsaCompressed->aStringArray; + *p3 = 0; + + p1 = pdsaExpanded->aStringArray; + + if (*p1 == 0) + { + // Two null terminators only. + *(p3 + 1) = 0; + } + + while(*p1) + { + p2 = OrStringSearch(p1, L':'); + if (p2) + { + *p2 = 0; + *p3 = GetProtseqId(p1); + *p2 = L':'; + if (*p3 != 0) + { + p3++; + p1 = p2 + 1; // Just after ':' + OrStringCopy(p3, p1); + + // Move p3 to start of next string if any. + p3 = OrStringSearch(p3, 0) + 1; + } + } + + // Move p1 to start of next string if any. + p1 = OrStringSearch(p1, 0) + 1; + } + + // Second terminator, p3 already points to it. + *p3 = 0; + + // Copy security bindings + OrMemoryCopy(p3 + 1, + pdsaExpanded->aStringArray + pdsaExpanded->wSecurityOffset, + (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset) * sizeof(WCHAR)); + + ASSERT(dsaValid(pdsaCompressed)); + + return(pdsaCompressed); +} + + +PWSTR +FindMatchingProtseq( + IN USHORT cClientProtseqs, + IN USHORT aClientProtseqs[], + IN PWSTR pwstrServerBindings + ) +/*++ + +Routine Description: + + Finds the first protseq id in aClientProtseqs which appears in any of + the server bindings. + +Arguments: + + cClientProtseqs - the number of entries in aClientProtseqs. + aClientProtseqs - Protseq tower id's support by the client. + pwstrServerBindings - compressed array of bindings supported by the server + terminated by two NULLs. + +Return Value: + + 0 - no match found. + non-0 - a pointer into the pwstrCompressedBindings. + +--*/ + +// Called by server oxid's and processes when checking for lazy use protseq. +{ + ULONG i; + + if (0 == cClientProtseqs) + { + return(0); + } + + while(*pwstrServerBindings) + { + for(i = 0; i < cClientProtseqs; i++) + { + if (aClientProtseqs[i] == *pwstrServerBindings) + { + return(pwstrServerBindings); + } + } + pwstrServerBindings = OrStringSearch(pwstrServerBindings, 0) + 1; + } + + return(NULL); +} + + + +PWSTR +FindMatchingProtseq( + IN USHORT protseq, + IN PWSTR pwstrCompressedBindings + ) +/*++ + +Routine Description: + + Searches a compressed string array for an entry which + matches a particular protseq. + + +Arguments: + + protseq - The protseq to search for. + + pwstrCompressedBindings - The bindings to search. + +Return Value: + + 0 - not found + + non-0 - a pointer into the pwstrCompressedBindings + +--*/ +{ + ASSERT(pwstrCompressedBindings); + + while(*pwstrCompressedBindings) + { + if (*pwstrCompressedBindings == protseq) + { + return(pwstrCompressedBindings); + } + pwstrCompressedBindings = OrStringSearch(pwstrCompressedBindings, 0) + 1; + } + return(0); +} + + + +ORSTATUS +MergeBindings( + IN DUALSTRINGARRAY *pdsaStringBindings, + IN DUALSTRINGARRAY *pdsaSecurityBindings, + OUT DUALSTRINGARRAY **ppdsaMergedBindings + ) +/*++ + +Routine Description: + + Merges the string bindings from the first param with the security + bindings from the second param to create a new dualstring array. + + +Arguments: + + pdsaStringBindings -- The string bindings supplier + + pdsaSecurityBindings -- The security bindings supplier + + ppdsaMergedBindings -- the merged result + +Return Value: + + OR_OK (0) - success + + OR_NOMEM - memory allocation failed + +--*/ +{ + + ASSERT(dsaValid(pdsaStringBindings)); + ASSERT(dsaValid(pdsaSecurityBindings)); + + USHORT wBindingsSize = pdsaStringBindings->wSecurityOffset; + + USHORT wSecuritySize = pdsaSecurityBindings->wNumEntries - + pdsaSecurityBindings->wSecurityOffset; + + USHORT wNumEntries = wBindingsSize + wSecuritySize; + + DUALSTRINGARRAY *pdsa = (DUALSTRINGARRAY *) + new char[ + sizeof(DUALSTRINGARRAY) + + (wNumEntries - 1) * sizeof(WCHAR) + ]; + + if (!pdsa) + { + return OR_NOMEM; + } + + *ppdsaMergedBindings = pdsa; + + pdsa->wNumEntries = wNumEntries; + pdsa->wSecurityOffset = wBindingsSize; + + memcpy( + pdsa->aStringArray, + pdsaStringBindings->aStringArray, + wBindingsSize * sizeof(WCHAR) + ); + + memcpy( + pdsa->aStringArray + pdsa->wSecurityOffset, + pdsaSecurityBindings->aStringArray + pdsaSecurityBindings->wSecurityOffset, + sizeof(WCHAR) * wSecuritySize + ); + + return OR_OK; +} diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/string.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/string.hxx new file mode 100644 index 000000000..93b47970b --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/string.hxx @@ -0,0 +1,159 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + String.hxx + +Abstract: + + Inline Helper functions for DUALSTRINGARRAY's + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-22-95 Bits 'n pieces + +--*/ + +#ifndef __STRING_HXX +#define __STRING_HXX + +inline void dsaCopy(DUALSTRINGARRAY *pdsaDest, DUALSTRINGARRAY *pdsaSrc) +{ + pdsaDest->wNumEntries = pdsaSrc->wNumEntries; + pdsaDest->wSecurityOffset = pdsaSrc->wSecurityOffset; + OrMemoryCopy(pdsaDest->aStringArray, + pdsaSrc->aStringArray, + pdsaSrc->wNumEntries*sizeof(USHORT)); +} + +// make a copy in shared memory +inline DUALSTRINGARRAY * +dsaSMCopy(DUALSTRINGARRAY *pdsa) +{ + ASSERT(NULL != pdsa); + + DUALSTRINGARRAY *pdsaT; + + pdsaT = (DUALSTRINGARRAY *) + OrMemAlloc(pdsa->wNumEntries + * sizeof(WCHAR) + + sizeof(DUALSTRINGARRAY) + ); + + if (NULL != pdsaT) + { + dsaCopy(pdsaT, pdsa); + } + + return pdsaT; +} + + +inline BOOL dsaValid(DUALSTRINGARRAY *pdsa) +{ + BOOL badPtr = IsBadWritePtr(pdsa->aStringArray, pdsa->wNumEntries * sizeof(WCHAR)); + + if ( FALSE == badPtr + && pdsa->wNumEntries >= 4 + && pdsa->wSecurityOffset <= (pdsa->wNumEntries - 2) + && pdsa->aStringArray[(pdsa->wNumEntries - 1)] == 0 + && pdsa->aStringArray[(pdsa->wNumEntries - 2)] == 0 + && pdsa->aStringArray[(pdsa->wSecurityOffset - 1)] == 0 + && pdsa->aStringArray[(pdsa->wSecurityOffset - 2)] == 0 + ) + { + return(TRUE); + } + return(FALSE); +} + +inline DWORD dsaHash(DUALSTRINGARRAY *pdsa) +// PERF WORK: Make sure the hash looks good in real world usage. +{ + int i, count; + DWORD hash, t; + count = i = hash = pdsa->wNumEntries; + hash |= pdsa->wSecurityOffset << 16; + + for(count = 0; count < i/2; count++) + { + t = *(PDWORD)&pdsa->aStringArray[count * 2]; + + hash += hash ^ t; + } + + // we may miss the last word, but it is null anyway. + + return(hash); +} + +inline DWORD dsaCompare(DUALSTRINGARRAY *pdsa, DUALSTRINGARRAY *pdsa2) +{ + return ( pdsa->wNumEntries == pdsa2->wNumEntries + && pdsa->wSecurityOffset == pdsa2->wSecurityOffset + && 0 == OrMemoryCompare(pdsa->aStringArray, + pdsa2->aStringArray, + pdsa->wNumEntries * sizeof(WCHAR)) ); +} + +inline PWSTR OrStringSearch(PWSTR string, USHORT value) +{ + // Faster and smaller then wcschr() for value == 0 + if (value == 0) + { + while(*string) + string++; + return(string); + } + return(wcschr(string, value)); +} + +RPC_BINDING_HANDLE GetBinding( + IN PWSTR pCompressedBinding + ); + +RPC_BINDING_HANDLE GetBindingToOr( + IN PWSTR pCompressedBinding + ); + +DUALSTRINGARRAY *GetStringBinding( + IN PWSTR pwstrCompressed, + IN PWSTR pwstrSecurityBindings + ); + +ORSTATUS ConvertToRemote( + IN DUALSTRINGARRAY * pdsaLocal, + OUT DUALSTRINGARRAY * *pdsaRemote + ); + +DUALSTRINGARRAY *CompressStringArray( + IN DUALSTRINGARRAY *psaExpanded, + IN BOOL fSharedMem + ); + +PWSTR FindMatchingProtseq( + IN USHORT cClientProtseqs, + IN USHORT aClientProtseqs[], + IN PWSTR pwstrServerBindings + ); + +PWSTR FindMatchingProtseq( + IN USHORT protseq, + IN PWSTR pswstrBindings + ); + +ORSTATUS MergeBindings( + IN DUALSTRINGARRAY *pdsaStringBindings, + IN DUALSTRINGARRAY *pdsaSecurityBindings, + OUT DUALSTRINGARRAY **ppdsaMergedBindings + ); + + +#endif // __STRING_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/time.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/time.hxx new file mode 100644 index 000000000..5cbae12c2 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcom95/time.hxx @@ -0,0 +1,113 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + Time.hxx + +Abstract: + + The CTime class represents time for this process. Instances of this class + should be small 4-8 bytes and cheap to create. + + The current implementation is just a wrapper for GetTickCount() which + handles overflow. + (4GB milliseconds is just under 50 days. This implementation is correctly + compare times up to 25 days appart.). + +Note: + This class should return consistent results even if the system time + is set forwards or backwards. + (Use GetTickCount() rather then GetSystemTimeAsFileTime()). + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 02-23-95 Bits 'n pieces + +--*/ + +#ifndef __TIME_HXX +#define __TIME_HXX + +#define TICKS_PER_SECOND (1000) // Ticks are milliseconds + +class CTime + { + private: + DWORD _Time; + + public: + + CTime() { SetNow(); } + + // Used to avoid a call to GetTickCount() + CTime(DWORD time) : _Time(time) { } + + void + SetNow() { + _Time = GetTickCount(); + } + + void + Sleep() + { + DWORD diff = _Time - GetTickCount(); + if ( diff > (2 * BaseTimeoutInterval) * 1000 ) + { + // Maybe overactive under stress. We're trying to sleep until a time + // which has already passed. + OrDbgDetailPrint(("Didn't need to sleep until %d from %d\n", _Time, GetTickCount())); + return; + } + SleepEx(diff, FALSE); + } + + operator DWORD() + { + return _Time; + } + + BOOL operator< (const CTime &Time) + { + // Is _Time less then Time. + DWORD diff = _Time - Time._Time; + return( ((LONG)diff) < 0); + } + + BOOL operator> (const CTime &Time) + { + // Is _Time greater then Time. + DWORD diff = Time._Time - _Time; + return( ((LONG)diff) < 0); + } + + BOOL operator<= (const CTime &Time) + { + return(! operator>(Time)); + } + + BOOL operator>= (const CTime &Time) + { + return(! operator<(Time)); + } + + void operator+=(UINT mSeconds) { _Time += (mSeconds * TICKS_PER_SECOND); } + + void operator-=(UINT mSeconds) { _Time -= (mSeconds * TICKS_PER_SECOND); } + + DWORD operator-(const CTime &Time) + { + return((_Time - Time._Time)/TICKS_PER_SECOND); + } + + // defualt = operator ok. + + }; + +#endif __TIME_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/dcomss.h b/private/ole32/dcomss/objex/shrmem/dcomss.h new file mode 100644 index 000000000..15fe0ee5d --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dcomss.h @@ -0,0 +1,81 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + dcomss.h + +Abstract: + + Common services provided by core the orpcss service. + +Author: + + Mario Goertzel [MarioGo] + +Revision History: + + MarioGo 06-14-95 Bits 'n pieces + +--*/ + +#ifndef __DCOMSS_H +#define __DCOMSS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _CHICAGO_ +#include <nt.h> +#include <ntdef.h> +#include <ntrtl.h> +#include <nturtl.h> +#endif + +#include <windows.h> + +#if DBG && !defined(DEBUGRPC) +#define DEBUGRPC +#endif + +// Endpoint related functions + +USHORT GetProtseqId(PWSTR Protseq); +USHORT GetProtseqIdAnsi(PSTR Protseq); +PWSTR GetProtseq(USHORT ProtseqId); +PWSTR GetEndpoint(USHORT ProtseqId); +RPC_STATUS UseProtseqIfNecessary(USHORT id); +RPC_STATUS DelayedUseProtseq(USHORT id); +VOID CompleteDelayedUseProtseqs(); +BOOL IsLocal(USHORT ProtseqId); +DWORD RegisterAuthInfoIfNecessary(); + + +extern BOOL gfRegisteredAuthInfo; + +extern BOOL s_fEnableDCOM; // Set by StartObjectExporter. + + +// Shared by wrapper\epts.c and olescm\clsdata.cxx. + +typedef enum { + STOPPED = 1, + START, + STARTED + } PROTSEQ_STATE; + +typedef struct { + PROTSEQ_STATE state; + PWSTR pwstrProtseq; + PWSTR pwstrEndpoint; + } PROTSEQ_INFO; + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/private/ole32/dcomss/objex/shrmem/dirs b/private/ole32/dcomss/objex/shrmem/dirs new file mode 100644 index 000000000..c449681f1 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/dirs @@ -0,0 +1,32 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= \ + dcom95 + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= diff --git a/private/ole32/dcomss/objex/shrmem/intor.hxx b/private/ole32/dcomss/objex/shrmem/intor.hxx new file mode 100644 index 000000000..41a99e066 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/intor.hxx @@ -0,0 +1,26 @@ +#ifndef __INTOR_HXX__ +#define __INTOR_HXX__ + +#include <or.h> // for ORSTATUS definition + +error_status_t __declspec(dllexport) +ConnectDCOM( + OUT HPROCESS *phProcess, + OUT ULONG *pdwTimeoutInSeconds, + OUT MID *pLocalMid, + OUT ULONG *pfConnectFlags, + OUT DWORD *pAuthnLevel, + OUT DWORD *pImpLevel, + OUT DWORD *pcServerSvc, + OUT USHORT **aServerSvc, + OUT DWORD *pcClientSvc, + OUT USHORT **aClientSvc, + OUT DWORD *pThreadID + ); + +ORSTATUS __declspec(dllexport) +StartDCOM( + void + ); + +#endif // __INTOR_HXX__ diff --git a/private/ole32/dcomss/objex/shrmem/makefil0 b/private/ole32/dcomss/objex/shrmem/makefil0 new file mode 100644 index 000000000..e6c5a5035 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/makefil0 @@ -0,0 +1,43 @@ +# +# This is the MIDL compile phase of the build process. +# +# The following is where you put the name of your .idl file without +# the .idl extension: +# + +!INCLUDE $(NTMAKEENV)\makefile.plt + +INCS = -I..\runtime\mtrt\nt -I..\runtime\mtrt \ + -I$(_NTDRIVE)\nt\private\dcomidl -I$(_NTDRIVE)\nt\public\sdk\inc + +SHARE_MIDL = \ + .\test.h .\test_c.c .\test_s.c + +TARGETS = test.h + +RPC_FLAGS = -ms_ext -c_ext -error allocation -oldnames -error ref + +CPP = -cpp_cmd "$(MIDL_CPP)" $(MIDL_FLAGS) + + +allidl: $(TARGETS) +!IF "$(BUILDMSG)" != "" + @ech ; $(BUILDMSG) ; +!ENDIF + +clean: delete_source allidl + +delete_source: + -erase $(SHARE_MIDL) + +# +# MIDL COMPILE +# + +SSWITCH=-prefix sstub _ + +test.h : test.idl + midl $(CPP) $(SSWITCH) $(INCS) $(RPC_FLAGS) test.idl \ + -cstub client\test_c.c \ + -sstub server\test_s.c + diff --git a/private/ole32/dcomss/objex/shrmem/or.h b/private/ole32/dcomss/objex/shrmem/or.h new file mode 100644 index 000000000..b647a8992 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/or.h @@ -0,0 +1,139 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + or.h + +Abstract: + + General include file for C things the OR. This file is pre-compiled. + +Author: + + Mario Goertzel [mariogo] Feb-10-95 + Satish Thatte [SatishT] Feb-22-96 modified for DCOM95 + +Revision History: + +--*/ + +#ifndef __OR_H +#define __OR_H + +#include <ole2int.h> // ComDebOut, etc + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _CHICAGO_ +#include <dcomss.h> // BUGBUG: reduce and copy here +#endif + +#include <stddef.h> +#include <debnot.h> // debugging stuff + +#include <objex.h> // Remote OR if from private\dcomidl +#include <orcb.h> // Callback if from private\dcomidl +#include <odeth.h> // ORPC OID rundown interface +#include <rawodeth.h> // Raw RPC -> ORPC OID rundown interface +#include <olerem.h> // MOXID, REFMOXID, etc +#include <tls.h> // OLE thread local storage + +#define IN +#define OUT +#define CONST const + +#define WSTR(s) L##s + +#define OrStringCompare(str1, str2, len) wcscmp((str1), (str2), (len)) +#define OrStringLen(str) wcslen(str) +#define OrStringCat(str1, str2) wcscat((str1), (str2)) +#define OrStringCopy(str1, str2) wcscpy((str1), (str2)) +#define OrMemorySet(p, value, len) memset((p), (value), (len)) +#define OrMemoryCompare(p1, p2, len) memcmp((p1), (p2), (len)) +#define OrMemoryCopy(dest, src, len) memcpy((dest), (src), (len)) +// OrStringSearch in or.hxx + +// +// The OR uses Win32 (RPC) error codes. +// + +typedef LONG ORSTATUS; + +// When the OR code asigns and error it uses +// one of the following mappings: +// There are no internal error codes. + +#define OR_OK RPC_S_OK +#define OR_NOMEM RPC_S_OUT_OF_MEMORY +#define OR_NORESOURCE RPC_S_OUT_OF_RESOURCES +#define OR_NOACCESS ERROR_ACCESS_DENIED +#define OR_BADOXID OR_INVALID_OXID +#define OR_BADOID OR_INVALID_OID +#define OR_BADSET OR_INVALID_SET +#define OR_BAD_SEQNUM OR_INVALID_SET // BUGBUG: need to change +#define OR_NOSERVER RPC_S_SERVER_UNAVAILABLE +#define OR_BADPARAM ERROR_INVALID_PARAMETER + +// Should NEVER be seen outside the OR. +#define OR_BUGBUG RPC_S_INTERNAL_ERROR +#define OR_INTERNAL_ERROR RPC_S_INTERNAL_ERROR +#define OR_BAD_LOAD_ADDR RPC_S_INTERNAL_ERROR +#define OR_REPEAT_START RPC_S_INTERNAL_ERROR + +// Internal codes used to indicate a special event. +#define OR_I_RETRY 0xC0210051UL +#define OR_I_NOPROTSEQ 0xC0210052UL + +#define UNUSED(_x_) ((void *)(_x_)) + +#if DBG + +extern int __cdecl ValidateError( + IN ORSTATUS Status, + IN ...); + + +#define VALIDATE(X) if (!ValidateError X) ASSERT(0); + +#ifndef _CHICAGO_ + +#define OrDbgPrint(X) DbgPrint X +#define OrDbgDetailPrint(X) DbgPrint X + +#else + +#define OrDbgPrint(X) +#define OrDbgDetailPrint(X) + +#endif + +#undef ASSERT +#ifndef _CHICAGO_ +#define ASSERT( exp ) \ + if (! (exp) ) \ + { \ + DbgPrint("OR: Assertion failed: %s(%d) %s\n", __FILE__, __LINE__, #exp); \ + DebugBreak(); \ + } +#else // _CHICAGO_ +#define ASSERT( exp ) if (! (exp) ) DebugBreak(); +#endif // _CHICAGO_ + + +#else // DBG +#define VALIDATE(X) +#define OrDbgPrint(X) +#define OrDbgDetailPrint(X) +#endif // DBG + + +#ifdef __cplusplus +} +#endif + +#endif // __OR_H + diff --git a/private/ole32/dcomss/objex/shrmem/or.hxx b/private/ole32/dcomss/objex/shrmem/or.hxx new file mode 100644 index 000000000..e9c97b7af --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/or.hxx @@ -0,0 +1,160 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + or.hxx + +Abstract: + + C++ include for C++ OR modules. + +Author: + + Mario Goertzel [mariogo] Feb-10-95 + +Revision History: + +--*/ + +#ifndef __OR_HXX +#define __OR_HXX + +#include <or.h> + +// Protcol defined timeouts + +const unsigned short BasePingInterval = 10; +const unsigned short BaseNumberOfPings = 3; +const unsigned short BaseTimeoutInterval = (BasePingInterval * BaseNumberOfPings); +const unsigned short InitialProtseqBufferLength = 118; + +// Well known tower IDs + +const unsigned short ID_LPC = 0x10; // ncalrpc, IsLocal() == TRUE +const unsigned short ID_WMSG = 0x01; // mswmsg, IsLoclal() == TRUE +const unsigned short ID_NP = 0x0F; // ncacn_np, IsLocal() == FALSE + +// Timer ID + +#define IDT_DCOM_RUNDOWN 1234 + +// Shared memory constants + +const ULONG DCOMSharedHeapName = 1111; +#define DCOMSharedGlobalBlockName L"DCOMSharedGlobals12321" + +// Name of global mutex used to protect shred memory structures +#define GLOBAL_MUTEX_NAME TEXT("ObjectResolverGlobalMutex") + +// Building blocks +#include <base.hxx> + +#include <ipidtbl.hxx> // OXIDEntry, RUNDOWN_TIMER_INTERVAL +#include <remoteu.hxx> // gpMTARemoteUnknown, CRemoteUnknown + +#include <memapi.hxx> // CPrivAlloc + +#include <smemor.hxx> // shared memory OR client interface +#include <intor.hxx> // internal version of OR client interface +#include <time.hxx> +#include <mutex.hxx> +#include <misc.hxx> +#include <callid.hxx> +#include <refobj.hxx> +#include <string.hxx> +#include <linklist.hxx> +#include <gentable.hxx> +#include <dsa.hxx> + +// +// Class forward declarations +// + +class CMid; +class COxid; +class COid; +class CProcess; + +// +// Global variables and constants +// + +#define OXID_TABLE_SIZE 16 +#define OID_TABLE_SIZE OXID_TABLE_SIZE*11 +#define MID_TABLE_SIZE 16 +#define PROCESS_TABLE_SIZE 16 +#define MAX_PROTSEQ_IDS 100 + +extern DWORD MyProcessId; +extern DWORD *gpdwLastCrashedProcessCheckTime; +extern CSmAllocator gSharedAllocator; // global shared memory allocator + +extern DUALSTRINGARRAY *gpLocalDSA; // phony bindings for this machine +extern MID gLocalMID; // MID of this machine +extern CMid *gpLocalMid; // Mid object for this machine + +extern PWSTR gpwstrProtseqs; + +extern CGlobalMutex *gpMutex; // global mutex to protect shared memory + +extern LONG *gpIdSequence; // shared sequence for generating IDs +extern DWORD *gpNextThreadID; // shared apartment ID generator +extern BOOL DCOM_Started; + +extern CProcess *gpProcess; // self pointer +extern CProcess *gpPingProcess; // pointer to surrogate for ping thread + +extern USHORT *gpcRemoteProtseqs; // count of remote protseqs +extern USHORT *gpRemoteProtseqIds; // array of remote protseq ids +extern PWSTR gpwstrProtseqs; // remote protseqs strings catenated +extern PROTSEQ_INFO gaProtseqInfo[]; + +// +// Security data passed to processes on connect. +// BUGBUG: this should be in shared memory to speed startup +// + +extern BOOL s_fEnableDCOM; +extern DWORD s_lAuthnLevel; +extern DWORD s_lImpLevel; +extern BOOL s_fMutualAuth; +extern BOOL s_fSecureRefs; +extern DWORD s_cServerSvc; +extern USHORT *s_aServerSvc; +extern DWORD s_cClientSvc; +extern USHORT *s_aClientSvc; + + +// +// Global tables +// + +// +// cannot use short forms for table types due to declaration order +// + +extern TCSafeResolverHashTable<COxid> * gpOxidTable; +extern TCSafeResolverHashTable<COid> * gpOidTable; +extern TCSafeResolverHashTable<CMid> * gpMidTable; +extern TCSafeResolverHashTable<CProcess> * gpProcessTable; + +// Headers which may use globals + +#include <oxid.hxx> +#include <process.hxx> +#include <mid.hxx> +#include <set.hxx> +#include <globals.hxx> + +// +// Startup routine. +// + +ORSTATUS StartDCOM(void); + +#pragma hdrstop + +#endif // __OR_HXX + diff --git a/private/ole32/dcomss/objex/shrmem/server/makefile b/private/ole32/dcomss/objex/shrmem/server/makefile new file mode 100644 index 000000000..14f79b701 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/server/makefile @@ -0,0 +1 @@ +!include $(NTMAKEENV)\makefile.def diff --git a/private/ole32/dcomss/objex/shrmem/server/serv.cxx b/private/ole32/dcomss/objex/shrmem/server/serv.cxx new file mode 100644 index 000000000..b97f72274 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/server/serv.cxx @@ -0,0 +1,303 @@ +#include <or.hxx> +#include <simpleLL.hxx> + +DECLARE_INFOLEVEL(Cairole) + +DUALSTRINGARRAY *pdsaMyBindings; + +OXID Oxid; +OID aOids[2]; +HPROCESS hProcess; + + +DUALSTRINGARRAY * +MakeDSA( + RPC_BINDING_VECTOR * pbv + ) +{ + PWSTR pwstrT; + DUALSTRINGARRAY *pdsaT; + PWSTR *aStringBindings; + USHORT psaLen; + DWORD i; + RPC_STATUS status; + + aStringBindings = new PWSTR[pbv->Count]; + + // Build array of string bindings for protseqs we're listening to. + + for(psaLen = 0, i = 0; i < pbv->Count; i++) + { + status = RpcBindingToStringBinding(pbv->BindingH[i], &aStringBindings[i]); + + if (status != RPC_S_OK) + { + break; + } + + ASSERT(aStringBindings[i]); + + psaLen += wcslen(aStringBindings[i]) + 1; + } + + + // string bindings, final null, and two final nulls + + psaLen += 1 + 2; + + pdsaT = new(psaLen * sizeof(WCHAR)) DUALSTRINGARRAY; + + pdsaT->wNumEntries = psaLen; + pdsaT->wSecurityOffset = psaLen - 2; + pwstrT = pdsaT->aStringArray; + memset(pwstrT,0,psaLen * sizeof(WCHAR)); + + for (i = 0; i < pbv->Count; i++) + + { + OrStringCopy(pwstrT, aStringBindings[i]); + pwstrT = OrStringSearch(pwstrT, 0) + 1; // next + + status = RpcStringFree(&aStringBindings[i]); + ASSERT(status == RPC_S_OK); + } + + ASSERT(dsaValid(pdsaT)); + + return pdsaT; +} + + +void +ServerSetup() +{ + RPC_STATUS status; + unsigned int cMinCalls = 1; + unsigned int cMaxCalls = 20; + unsigned int fDontWait = TRUE; + TCHAR * pszStringBinding = NULL; + TCHAR * pszProtocolSequence = TEXT("ncalrpc"); + + ULONG i, j; + + /* + + WCHAR self[10]; + + printf("Self = "); + scanf("%S",self); + printf("Self = %S\n",self); + + */ + + RPC_BINDING_VECTOR * BindingVector; + + status = RpcServerUseProtseq( + pszProtocolSequence, + cMaxCalls, + NULL); // Security descriptor + + /* + status = RpcServerUseAllProtseqs( + cMaxCalls, + NULL); // Security descriptor + + printf("RpcServerUseAllProtseqs returned 0x%x\n", status); + if (status) + exit(status); + + */ + + status = RpcServerRegisterIf( + _SharedMemoryTest_ServerIfHandle, + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + printf("RpcServerRegisterIf returned 0x%x\n", status); + if (status) + exit(status); + + status = RpcServerInqBindings(&BindingVector); + + printf("RpcServerInqBindings returned 0x%x\n", status); + if (status) + exit(status); + + /* + + WCHAR* entryName = catenate(TEXT("/.:/ShareTest"),self); + + status = RpcNsBindingExport( + 0, // no name syntax specified + entryName, + _SharedMemoryTest_ServerIfHandle, + BindingVector, + NULL + ); + + printf("RpcNsBindingExport returned 0x%x\n", status); + if (status) + exit(status); + + printf("Exported the following string bindings to entry %S:\n",entryName); + + for (j = 0; j < BindingVector->Count; j++) + { + RpcBindingToStringBinding( + BindingVector->BindingH[j], + &pszStringBinding + ); + printf("%d) %S\n",j,pszStringBinding); + RpcStringFree(&pszStringBinding); + } + + */ + + status = RpcEpRegister( + _SharedMemoryTest_ServerIfHandle, + BindingVector, + NULL, + NULL); + + printf("RpcEpRegister returned 0x%x\n", status); + if (status) + exit(status); + + pdsaMyBindings = MakeDSA(BindingVector); + + status = RpcServerListen( + cMinCalls, + cMaxCalls, + TRUE); + printf("RpcServerListen returned: 0x%x\n", status); + if (status) + exit(status); + + HANDLE pThreadHandle; + unsigned long ThreadID; + + printf("Creating RpcMgmtWaitServerListen Thread\n"); + pThreadHandle = CreateThread(0, 0, + (LPTHREAD_START_ROUTINE) RpcMgmtWaitServerListen, NULL, 0, &ThreadID); +} + +/* server prototype */ +void _RemoteRead( + /* [in] */ unsigned long offset, + /* [out] */ long __RPC_FAR *value) +{ + *value = *OR_FULL_POINTER(long,(int)offset); +} + +CSimpleLinkList OR_BASED *pList; +CSimpleLinkListIterator *pIter; + +/* server prototype */ +void _SendList( + /* [in] */ unsigned long list_offset) +{ + pIter = new CSimpleLinkListIterator( + *OR_FULL_POINTER(CSimpleLinkList,list_offset) + ); +} + +/* server prototype */ +void _ReadNext( + /* [out] */ unsigned long __RPC_FAR *value) +{ + *value = (unsigned long) pIter->next(); +} + +/* server prototype */ +void _GetIds( + /* [out] */ OXID __RPC_FAR *pOxid, + /* [out] */ OID __RPC_FAR *pOid) +{ + *pOxid = Oxid; + *pOid = aOids[0]; +} + +/* server prototype */ +void _ShutDown( void) +{ + ServerFreeOXID( + hProcess, + Oxid, + 2, + aOids + ); +} + +void +TestLocalResolverAPI() +{ + DWORD dwTimeoutInSeconds; + MID LocalMid; + BOOL DisableDCOM; + DWORD AuthnLevel; + DWORD ImpLevel; + BOOL MutualAuth; + DWORD cServerSvc; + USHORT *aServerSvc; + DWORD cClientSvc; + USHORT *aClientSvc; + + long Status; + + OXID_INFO oxidInfo; + + Status = ConnectDCOM( + &hProcess, + &dwTimeoutInSeconds, + &LocalMid, + &DisableDCOM, + &AuthnLevel, + &ImpLevel, + &MutualAuth, + &cServerSvc, + &aServerSvc, + &cClientSvc, + &aClientSvc + ); + + Status = ServerAllocateOXID( + hProcess, + FALSE, + oxidInfo, + pdsaMyBindings, + Oxid + ); + + Status = ServerAllocateOID( + hProcess, + Oxid, + aOids[0] + ); + + Status = ServerAllocateOID( + hProcess, + Oxid, + aOids[1] + ); +} + +void __cdecl +main() +{ + ServerSetup(); + TestLocalResolverAPI(); + + Sleep(INFINITE); +} + + +/* MIDL allocate and free */ + +void __RPC_FAR * __RPC_API midl_user_allocate(size_t len) +{ + return(malloc(len)); +} + +void __RPC_API midl_user_free(void __RPC_FAR * ptr) +{ + free(ptr); +} diff --git a/private/ole32/dcomss/objex/shrmem/server/sources b/private/ole32/dcomss/objex/shrmem/server/sources new file mode 100644 index 000000000..07efa68e9 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/server/sources @@ -0,0 +1,109 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David Plummer (davepl) 19-Mar-94 + + Modifed by via awk to include global project include file + and to wrap precompiled header line within a conditional + that can be set in this include file. + + Drew Bliss (DrewB) 21-Dec-1993 + +!ENDIF + +!IF "$(NTDEBUG)" != "ntsd" +CXXCPP_OPTIONS=-DDBG=0 +!else +CXXCPP_OPTIONS=-DDBG=1 +DEBUG_DEFINES=-DLDEBUG +MSC_OPTIMIZATION=/Od +!endif + +MAJORCOMP= cairole +MINORCOMP= stg + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= serv + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= ..\bin + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= PROGRAM + +#PRECOMPILED_INCLUDE= ..\or.hxx + +# +# The following includes a global include file defined at the +# base of the project for all components +# + +LIBDIR=$(_NTDRIVE)\nt\public\sdk\lib + +OLEDIR=$(_NTDRIVE)\nt\private\ole32 + +!include $(OLEDIR)\daytona.inc + +INCLUDES=..;..\dcom95;..\stg;$(OLEDIR)\dcomss;$(OLEDIR)\ih;$(OLEDIR)\com\inc;$(OLEDIR)\common\daytona;$(OLEDIR)\stg\docfile;$(OLEDIR)\stg\h;\nt\private\types\new_ole;C:\nt\private\dcomidl\obj;$(OLEDIR)\stg\exp + + +C_DEFINES= \ + $(C_DEFINES) \ + -DMULTIHEAP + +SOURCES= \ + serv.cxx \ + test_s.c + +LINKLIBS=$(LIBDIR)\*\Rpcrt4.lib \ + $(LIBDIR)\*\RpcNdr.lib \ + $(LIBDIR)\*\ntdll.lib \ + $(LIBDIR)\*\uuid.lib \ + $(LIBDIR)\*\user32.lib \ + $(LIBDIR)\*\security.lib \ + $(LIBDIR)\*\ole32.lib \ + $(OLEDIR)\common\daytona\obj\*\common.lib \ + $(OLEDIR)\com\inc\daytona\obj\*\inc.lib \ + ..\lib\*\stg.lib \ + ..\lib\*\dcom95.lib \ + +USE_LIBCMT=1 + + +UMTYPE= console +UMAPPL= +UMTEST= +UMLIBS= + +PRECOMPILED_OPTION= +#PRECOMPILED_TARGET=..\obj\*\$(PRECOMPILED_PCH) +PRECOMPILED_CXX= + diff --git a/private/ole32/dcomss/objex/shrmem/smemor.hxx b/private/ole32/dcomss/objex/shrmem/smemor.hxx new file mode 100644 index 000000000..e28e3e8a8 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/smemor.hxx @@ -0,0 +1,127 @@ +#ifndef __SMEMOR_HXX__ +#define __SMEMOR_HXX__ + +#define CONNECT_DISABLEDCOM ( 0x1 ) +#define CONNECT_MUTUALAUTH ( 0x2 ) +#define CONNECT_SECUREREF ( 0x4 ) + +class CProcess; + +typedef CProcess *HPROCESS; + +error_status_t __declspec(dllexport) +AllocateReservedIds( + IN long cIdsToReserve, + OUT ID *pidReservedBase); + + error_status_t __declspec(dllexport) + Connect( + OUT HPROCESS *phProcess, + OUT ULONG *pdwTimeoutInSeconds, + OUT DUALSTRINGARRAY **ppdsaOrBindings, + OUT MID *pLocalMid, + IN long cIdsToReserve, + OUT ID *pidReservedBase, + OUT ULONG *pfConnectFlags, + OUT DWORD *pAuthnLevel, + OUT DWORD *pImpLevel, + OUT DWORD *pcServerSvc, + OUT USHORT **aServerSvc, + OUT DWORD *pcClientSvc, + OUT USHORT **aClientSvc, + OUT DWORD *pThreadID); + +error_status_t __declspec(dllexport) +Disconnect( + IN OUT HPROCESS *phProcess); + +error_status_t __declspec(dllexport) +ClientResolveOXID( + IN HPROCESS hProcess, + IN OXID *poxidServer, + IN DUALSTRINGARRAY *pssaServerObjectResolverBindings, + IN long fApartment, + OUT OXID_INFO *poxidInfo, + OUT MID *pLocalMidOfRemote); + +error_status_t __declspec(dllexport) +ServerAllocateOXIDAndOIDs( + IN HPROCESS hProcess, + OUT OXID *poxidServer, + IN long fApartment, + IN unsigned long cOids, + OUT OID aOid[ ], + OUT unsigned long *pcOidsAllocated, + IN OXID_INFO *pOxidInfo, + IN DUALSTRINGARRAY *pdsaStringBindings, + IN DUALSTRINGARRAY *pdsaSecurityBindings); + +error_status_t __declspec(dllexport) +ServerAllocateOIDs( + IN HPROCESS hProcess, + IN OXID *poxidServer, + IN unsigned long cOids, + OUT OID aOid[ ], + OUT unsigned long *pcOidsAllocated); + +error_status_t __declspec(dllexport) +ServerFreeOXIDAndOIDs( + IN HPROCESS hProcess, + IN OXID oxidServer, + IN unsigned long cOids, + IN OID aOids[ ]); + +#define OR_PARTIAL_UPDATE ( 1003L ) + +error_status_t __declspec(dllexport) +ClientAddOID( + IN HPROCESS hProcess, + IN OID OidToBeAdded, + IN OXID OxidForOid, + IN MID MidForOxid + ); + +error_status_t __declspec(dllexport) +ClientDropOID( + IN HPROCESS hProcess, + IN OID OidToBeRemoved, + IN MID Mid + ); + +error_status_t __declspec(dllexport) +GetOXID( + IN HPROCESS hProcess, + IN OXID Oxid, + IN DUALSTRINGARRAY *pdsaServerObjectResolverBindings, + IN long fApartment, + IN USHORT wProtseqId, + OUT OXID_INFO &OxidInfo, + OUT MID &LocalMidOfRemote + ); + +error_status_t __declspec(dllexport) +ServerAllocateOXID( + IN HPROCESS hProcess, + IN long fApartment, + IN OXID_INFO *pOxidInfo, + IN DUALSTRINGARRAY *pdsaStringBindings, + OUT OXID &Oxid + ); + +error_status_t __declspec(dllexport) +ServerAllocateOID( + IN HPROCESS hProcess, + IN OXID Oxid, + OUT OID &Oid + ); + + +error_status_t __declspec(dllexport) +ServerFreeOXID( + IN HPROCESS hProcess, + IN OXID oxidServer, + IN unsigned long cOids, + IN OID aOids[ ] + ); + +#endif // __SMEMOR_HXX__ diff --git a/private/ole32/dcomss/objex/shrmem/stg/daytona/makefile b/private/ole32/dcomss/objex/shrmem/stg/daytona/makefile new file mode 100644 index 000000000..14f79b701 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/daytona/makefile @@ -0,0 +1 @@ +!include $(NTMAKEENV)\makefile.def diff --git a/private/ole32/dcomss/objex/shrmem/stg/daytona/sources b/private/ole32/dcomss/objex/shrmem/stg/daytona/sources new file mode 100644 index 000000000..efdc35fe6 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/daytona/sources @@ -0,0 +1,64 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + David Plummer (davepl) 19-Mar-94 + + Modifed by via awk to include global project include file + and to wrap precompiled header line within a conditional + that can be set in this include file. + + Drew Bliss (DrewB) 21-Dec-1993 + +!ENDIF + + +# +# This is the name of the target built from the source files specified +# below. The name should include neither the path nor the file extension. +# + +TARGETNAME= stg + +# +# This specifies where the target is to be built. A private target of +# type LIBRARY or DYNLINK should go to obj, whereas a public target of +# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib. +# + +TARGETPATH= ..\..\lib + +# +# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY, +# etc. +# + +TARGETTYPE= LIBRARY + +!include ..\..\daytona.inc + +SOURCES= \ + ..\simplell.cxx \ + ..\dfdbg.cxx \ + ..\fastlock.cxx \ + ..\smalloc.cxx + + +UMTYPE= console +UMAPPL= +UMTEST= +UMLIBS= diff --git a/private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx b/private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx new file mode 100644 index 000000000..3e05ed8ae --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx @@ -0,0 +1,744 @@ +//+-------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1992 +// +// File: debug.cxx +// +// Contents: Debugging routines +// +// History: 07-Mar-92 DrewB Created +// +//--------------------------------------------------------------- + +#include <or.hxx> + +#include <debug.hxx> + +#if DBG == 1 + +#include <stdarg.h> +#include <dfdeb.hxx> +#include <logfile.hxx> +#include <df32.hxx> + +//+------------------------------------------------------------- +// +// Function: DfDebug, public +// +// Synopsis: Sets debugging level +// +//--------------------------------------------------------------- + +DECLARE_INFOLEVEL(ol); + +/* + +#define LOGFILENAME L"logfile.txt" + +static CGlobalFileStream *_pgfstLogFiles = NULL; +WCHAR gwcsLogFile[] = LOGFILENAME; + +STDAPI_(void) DfDebug(ULONG ulLevel, ULONG ulMSFLevel) +{ +#if DBG == 1 + olInfoLevel = ulLevel; +// SetInfoLevel(ulMSFLevel); + _SetWin4InfoLevel(ulLevel | ulMSFLevel); + + olDebugOut((DEB_ITRACE, "\n-- DfDebug(0x%lX, 0x%lX)\n", + ulLevel, ulMSFLevel)); +#endif +} + +*/ + +// NT and Cairo +#ifdef WIN32 +#if 0 +// Throw Win32 error information +#define THROW_LAST_ERROR() THROW_SC(LAST_SCODE) + +//+--------------------------------------------------------------------------- +// +// Class: CDfGlobalMemory (dgm) +// +// Purpose: Create a fixed size chunk of globally shared memory +// +// Interface: See below +// +// History: 06-May-93 DrewB Created +// +// Notes: The init function is only called once when the shared +// memory is first created. +// +// The end function is only called once when the last +// reference to the global memory is released +// +// The reference count is added onto the global allocation +// and kept at offset zero so the address returned to +// client code is offset by sizeof(LONG) +// +//---------------------------------------------------------------------------- + +typedef void (*DfGlobalMemoryFn)(void *); + +class CDfGlobalMemory +{ +public: + CDfGlobalMemory(TCHAR const *ptcsName, + DWORD cbSize, + DfGlobalMemoryFn pfnInit, + DfGlobalMemoryFn pfnEnd); + ~CDfGlobalMemory(void); + + inline void *GetAddress(void) const; + +private: + inline LONG *RefCount(void); + + HANDLE _hMapping; + void *_pvMemory; + DfGlobalMemoryFn _pfnEnd; +}; + +//+--------------------------------------------------------------------------- +// +// Member: CDfGlobalMemory::GetAddress, public +// +// Synopsis: Returns the address of the shared memory +// +// History: 06-May-93 DrewB Created +// +//---------------------------------------------------------------------------- + +inline void *CDfGlobalMemory::GetAddress(void) const +{ + return (void *)((LONG *)_pvMemory+1); +} + +//+--------------------------------------------------------------------------- +// +// Member: CDfGlobalMemory::RefCount, private +// +// Synopsis: Returns a pointer to the reference count +// +// History: 07-May-93 DrewB Created +// +//---------------------------------------------------------------------------- + +inline LONG *CDfGlobalMemory::RefCount(void) +{ + return (LONG *)_pvMemory; +} + +//+--------------------------------------------------------------------------- +// +// Member: CDfGlobalMemory::CDfGlobalMemory, public +// +// Synopsis: Creates a chunk of global memory +// +// Arguments: [ptcsName] - Name for sharing +// [cbSize] - Size of chunk +// [pfnInit] - Initialization function or NULL +// [pfnEnd] - Shutdown function or NULL +// +// History: 06-May-93 DrewB Created +// +// Notes: Allowed to throw on failure; this is debug only code +// +//---------------------------------------------------------------------------- + +CDfGlobalMemory::CDfGlobalMemory(TCHAR const *ptcsName, + DWORD cbSize, + DfGlobalMemoryFn pfnInit, + DfGlobalMemoryFn pfnEnd) +{ + BOOL fOpened; +#if WIN32 == 100 || WIN32 > 200 + CGlobalSecurity gs; + SCODE sc; + + if (FAILED(sc = gs.Init())) + THROW_SC(sc); + _hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, gs, PAGE_READWRITE, + 0, cbSize+sizeof(LONG), (TCHAR *)ptcsName); +#else + _hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, + 0, cbSize+sizeof(LONG), (TCHAR *)ptcsName); +#endif + if (_hMapping == NULL) + THROW_LAST_ERROR(); + + fOpened = GetLastError() == ERROR_ALREADY_EXISTS; + + _pvMemory = MapViewOfFile(_hMapping, FILE_MAP_ALL_ACCESS, + 0, 0, 0); + if (_pvMemory == NULL) + { + CloseHandle(_hMapping); + THROW_LAST_ERROR(); + } + + if (pfnInit && !fOpened) + { + *(RefCount()) = 0; + pfnInit(GetAddress()); + } + + _pfnEnd = pfnEnd; + InterlockedIncrement(RefCount()); +} + +//+--------------------------------------------------------------------------- +// +// Member: CDfGlobalMemory::~CDfGlobalMemory, public +// +// Synopsis: Releases resources for shared memory +// +// History: 06-May-93 DrewB Created +// +//---------------------------------------------------------------------------- + +CDfGlobalMemory::~CDfGlobalMemory(void) +{ + if (InterlockedDecrement(RefCount()) == 0 && _pfnEnd) + _pfnEnd(GetAddress()); + + UnmapViewOfFile(_pvMemory); + CloseHandle(_hMapping); +} +#endif //0 +#endif // WIN32 + +// Resource limits + +static LONG lResourceLimits[CDBRESOURCES] = +{ + 0x7fffffff, // DBR_MEMORY + 0x7fffffff, // DBR_XSCOMMITS + 0x0, // DBR_FAILCOUNT + 0x0, // DBR_FAILLIMIT + 0x0, // DBRQ_MEMORY_ALLOCATED + 0x0, // DBRI_ALLOC_LIST + 0x0, // DBRI_LOGFILE_LIST + 0x0 // DBRF_LOGGING +}; + +#define CBRESOURCES sizeof(lResourceLimits) + +#if 0 + +static CStaticDfMutex _sdmtxResources(TSTR("DfResourceMutex")); + +static void ResInit(void *pvMemory) +{ + // Initialize limits + memcpy(pvMemory, lResourceLimits, CBRESOURCES); +} + +static CDfGlobalMemory _dgmResourceLimits(TSTR("DfResourceMemory"), + CBRESOURCES, + ResInit, + NULL); + +#define RESLIMIT(n) \ + (*((LONG *)_dgmResourceLimits.GetAddress()+(n))) + +#define TAKEMTX \ + olVerSucc(_sdmtxResources.Take(INFINITE)) +#define RELEASEMTX \ + _sdmtxResources.Release(); + +#else + +#define RESLIMIT(n) lResourceLimits[n] +#define TAKEMTX +#define RELEASEMTX + +#endif + +//+--------------------------------------------------------------------------- +// +// Function: DfSetResLimit, public +// +// Synopsis: Sets a resource limit +// +// History: 24-Nov-92 DrewB Created +// +//---------------------------------------------------------------------------- + +STDAPI_(void) DfSetResLimit(UINT iRes, LONG lLimit) +{ + TAKEMTX; + + RESLIMIT(iRes) = lLimit; + + RELEASEMTX; +} + +//+--------------------------------------------------------------------------- +// +// Function: DfGetResLimit, public +// +// Synopsis: Gets a resource limit +// +// History: 24-Nov-92 DrewB Created +// +//---------------------------------------------------------------------------- + +STDAPI_(LONG) DfGetResLimit(UINT iRes) +{ + // Doesn't need serialization + return RESLIMIT(iRes); +} + +//+--------------------------------------------------------------------------- +// +// Function: HaveResource, private +// +// Synopsis: Checks to see if a resource limit is exceeded +// and consumes resource if not +// +// History: 24-Nov-92 DrewB Created +// +//---------------------------------------------------------------------------- + +BOOL HaveResource(UINT iRes, LONG lRequest) +{ + if (RESLIMIT(iRes) >= lRequest) + { + TAKEMTX; + + RESLIMIT(iRes) -= lRequest; + + RELEASEMTX; + + return TRUE; + } + return FALSE; +} + +//+--------------------------------------------------------------------------- +// +// Function: ModifyResLimit, private +// +// Synopsis: Adds to a resource limit +// +// History: 24-Nov-92 DrewB Created +// +//---------------------------------------------------------------------------- + +LONG ModifyResLimit(UINT iRes, LONG lChange) +{ + LONG l; + + TAKEMTX; + + RESLIMIT(iRes) += lChange; + l = RESLIMIT(iRes); + + RELEASEMTX; + + return l; +} + +//+------------------------------------------------------------------------- +// +// Function: SimulateFailure +// +// Synopsis: Check for simulated failure +// +// Effects: Tracks failure count +// +// Arguments: [failure] -- failure type +// +// Returns: TRUE if call should fail, FALSE if call should succeed +// +// Modifies: RESLIMIT(DBR_FAILCOUNT) +// +// Algorithm: Increment failure count, fail if count has succeeded +// limit +// +// History: 21-Jan-93 AlexT Created +// +//-------------------------------------------------------------------------- + +BOOL SimulateFailure(DBFAILURE failure) +{ + LONG l; + BOOL fFail; + + // We don't special case failure types, yet. + + TAKEMTX; + + RESLIMIT(DBR_FAILCOUNT)++; + l = RESLIMIT(DBR_FAILLIMIT); + fFail = RESLIMIT(DBR_FAILCOUNT) >= l; + + RELEASEMTX; + + if (l == 0) + { + // We're not simulating any failures; just tracking them + return(FALSE); + } + + return fFail; +} + +//+-------------------------------------------------------------- +// +// Class: CChecksumBlock (cb) +// +// Purpose: Holds a memory block that is being checksummed +// +// Interface: See below +// +// History: 08-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +class CChecksumBlock +{ +public: + CChecksumBlock(char *pszName, + void *pvAddr, + ULONG cBytes, + DWORD dwFlags, + CChecksumBlock *pcbNext, + CChecksumBlock *pcbPrev); + ~CChecksumBlock(void); + + char *_pszName; + void *_pvAddr; + ULONG _cBytes; + DWORD _dwFlags; + CChecksumBlock *_pcbNext, *_pcbPrev; + ULONG _ulChecksum; +}; + +// Global list of checksummed blocks +static CChecksumBlock *pcbChkBlocks = NULL; + +//+-------------------------------------------------------------- +// +// Member: CChecksumBlock::CChecksumBlock, private +// +// Synopsis: Ctor +// +// Arguments: [pszName] - Block name +// [pvAddr] - Starting addr +// [cBytes] - Length +// [dwFlags] - Type flags +// [pcbNext] - Next checksum block +// +// History: 08-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +CChecksumBlock::CChecksumBlock(char *pszName, + void *pvAddr, + ULONG cBytes, + DWORD dwFlags, + CChecksumBlock *pcbNext, + CChecksumBlock *pcbPrev) +{ + ULONG i; + char *pc; + + olVerify(_pszName = new char[strlen(pszName)+1]); + strcpy(_pszName, pszName); + _pvAddr = pvAddr; + _cBytes = cBytes; + _dwFlags = dwFlags; + _pcbNext = pcbNext; + if (pcbNext) + pcbNext->_pcbPrev = this; + _pcbPrev = pcbPrev; + if (pcbPrev) + pcbPrev->_pcbNext = this; + _ulChecksum = 0; + pc = (char *)pvAddr; + for (i = 0; i<cBytes; i++) + _ulChecksum += *pc++; +} + +//+-------------------------------------------------------------- +// +// Member: CChecksumBlock::~CChecksumBlock, private +// +// Synopsis: Dtor +// +// History: 08-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +CChecksumBlock::~CChecksumBlock(void) +{ + delete _pszName; +} + +//+-------------------------------------------------------------- +// +// Function: DbgChkBlocks, private +// +// Synopsis: Verify checksums on all current blocks +// +// Arguments: [dwFlags] - Types of blocks to check +// [pszFile] - File check was called from +// [iLine] - Line in file +// +// History: 08-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +void DbgChkBlocks(DWORD dwFlags, char *pszFile, int iLine) +{ + CChecksumBlock *pcb; + + for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext) + if (pcb->_dwFlags & dwFlags) + { + ULONG i, ulSum = 0; + char *pc; + + for (pc = (char *)pcb->_pvAddr, i = 0; i<pcb->_cBytes; i++) + ulSum += *pc++; + if (ulSum != pcb->_ulChecksum) + olDebugOut((DEB_ERROR, "* Bad checksum %s:%d '%s' %p:%lu *\n", + pszFile, iLine, pcb->_pszName, + pcb->_pvAddr, pcb->_cBytes)); + else if (dwFlags & DBG_VERBOSE) + olDebugOut((DEB_ERROR, "* Checksum passed %s:%d" + " '%s' %p:%lu *\n", + pszFile, iLine, pcb->_pszName, + pcb->_pvAddr, pcb->_cBytes)); + } +} + +//+-------------------------------------------------------------- +// +// Function: DbgAddChkBlock, private +// +// Synopsis: Adds a checksum block +// +// Arguments: [pszName] - Name of block +// [pvAddr] - Starting addr +// [cBytes] - Length +// [dwFlags] - Type flags +// +// History: 08-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +void DbgAddChkBlock(char *pszName, + void *pvAddr, + ULONG cBytes, + DWORD dwFlags) +{ + CChecksumBlock *pcb; + + olVerify(pcb = new CChecksumBlock(pszName, pvAddr, cBytes, + dwFlags, pcbChkBlocks, NULL)); + pcbChkBlocks = pcb; +} + +//+-------------------------------------------------------------- +// +// Function: DbgFreeChkBlock, private +// +// Synopsis: Removes a block from the list +// +// Arguments: [pvAddr] - Block's check address +// +// History: 10-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +void DbgFreeChkBlock(void *pvAddr) +{ + CChecksumBlock *pcb; + + for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext) + if (pcb->_pvAddr == pvAddr) + { + if (pcb->_pcbPrev) + pcb->_pcbPrev->_pcbNext = pcb->_pcbNext; + else + pcbChkBlocks = pcb->_pcbNext; + if (pcb->_pcbNext) + pcb->_pcbNext->_pcbPrev = pcb->_pcbPrev; + delete pcb; + return; + } +} + +//+-------------------------------------------------------------- +// +// Function: DbgFreeChkBlocks, private +// +// Synopsis: Frees all checksum blocks +// +// History: 08-Apr-92 DrewB Created +// +//--------------------------------------------------------------- + +void DbgFreeChkBlocks(void) +{ + CChecksumBlock *pcb; + + while (pcbChkBlocks) + { + pcb = pcbChkBlocks->_pcbNext; + delete pcbChkBlocks; + pcbChkBlocks = pcb; + } +} + +/* + +inline CGlobalFileStream *GetGlobalFileStream() +{ + return((CGlobalFileStream *)DfGetResLimit(DBRI_LOGFILE_LIST)); +} + +inline void SetGlobalFileStream(CGlobalFileStream *pgfst) +{ + DfSetResLimit(DBRI_LOGFILE_LIST, (LONG) pgfst); +} + +SCODE GetLogFile(CFileStream **pfs) +{ + SCODE sc = S_OK; + CFileStream *pfsLoop = NULL; + + *pfs = NULL; + + if (GetGlobalFileStream() == NULL) + { + IMalloc *pMalloc; + +#ifdef WIN32 + olHChk(DfCreateSharedAllocator(&pMalloc)); +#else + olHChk(CoGetMalloc(MEMCTX_SHARED, &pMalloc)); +#endif + SetGlobalFileStream(new (pMalloc) CGlobalFileStream(pMalloc, + 0, LOGFILEDFFLAGS, + LOGFILESTARTFLAGS)); + pMalloc->Release(); + } + + if (GetGlobalFileStream() != NULL) + { + pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId()); + + if (pfsLoop == NULL) + { + IMalloc *pMalloc; +#ifdef WIN32 + olHChk(DfCreateSharedAllocator(&pMalloc)); +#else + olHChk(CoGetMalloc(MEMCTX_SHARED, &pMalloc)); +#endif + + pfsLoop = new (pMalloc) CFileStream(pMalloc); + pMalloc->Release(); + + if (pfsLoop != NULL) + pfsLoop->InitFromGlobal(GetGlobalFileStream()); + } + } + +EH_Err: + *pfs = pfsLoop; + return sc; +} + +SCODE _FreeLogFile(void) +{ + CFileStream *pfsLoop = NULL; + + if (GetGlobalFileStream()) + pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId()); + + if (pfsLoop != NULL) + { + pfsLoop->vRelease(); + GetGlobalFileStream()->Release(); + SetGlobalFileStream(NULL); + return S_OK; + } + + return STG_E_UNKNOWN; +} + +long cLogNestings = 0; + +void OutputLogfileMessage(char const *format, ...) +{ + int length; + char achPreFormat[] = "PID[%lx] TID[%lx] "; + char achBuffer[256]; + ULONG cbWritten; + CFileStream *pfs = NULL; + va_list arglist; + STATSTG stat; + + if (cLogNestings > 0) + return; + + TAKEMTX; + cLogNestings++; + + va_start(arglist, format); + + GetLogFile(&pfs); + + if (NULL != pfs) + { + pfs->Init(gwcsLogFile); + pfs->Stat(&stat, STATFLAG_NONAME); + + if (DfGetResLimit(DBRF_LOGGING) & DFLOG_PIDTID) + { + // Prepare prefix string + length = wsprintfA(achBuffer, "PID[%8lx] TID[%8lx] ", + GetCurrentProcessId(), GetCurrentThreadId()); + + // length does not include NULL terminator + + pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten); + stat.cbSize.LowPart += cbWritten; + } + + // Write caller data to logfile +#if WIN32 == 300 + wsprintfA(achBuffer, format, arglist); +#else + w4vsprintf(achBuffer, format, arglist); +#endif + + length = strlen(achBuffer); + for (int i = 0; i < length; i++) + { + if (((achBuffer[i] < 32) || (achBuffer[i] > 127)) && + (achBuffer[i] != '\n') && (achBuffer[i] != '\t')) + { + achBuffer[i] = '.'; + } + } + + pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten); + } + + cLogNestings--; + RELEASEMTX; +} + + +*/ + +#endif // DBG == 1 diff --git a/private/ole32/dcomss/objex/shrmem/stg/dirs b/private/ole32/dcomss/objex/shrmem/stg/dirs new file mode 100644 index 000000000..869a606d0 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/dirs @@ -0,0 +1,27 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Steve Wood (stevewo) 17-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS= + +OPTIONAL_DIRS= \ + daytona + diff --git a/private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx b/private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx new file mode 100644 index 000000000..b810a7705 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx @@ -0,0 +1,433 @@ +//+-------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1991 - 1992 +// +// File: fastlock.cxx +// +// Contents: Implementation of CDfMutex methods for DocFiles +// +// History: 26-Jul-94 DonnaLi Created +// +//--------------------------------------------------------------- + +#include <or.hxx> + +#ifdef UNICODE +#define GLOBAL_CS L"GlobalCsMutex" +#else +#define GLOBAL_CS "GlobalCsMutex" +#endif + +// +// This is the number of characters to skip over in the name +// pased to CDfMutex::Init. The name consists of the string +// OleDfRoot followed by the hex representation of a unique +// number for each Docfile. We skip CHARS_TO_SKIP number of +// characters in the name to produce a related and yet unique +// name for the file mapping containing global state for the +// critical section. +// +#define CHARS_TO_SKIP 3 + + +//+-------------------------------------------------------------- +// +// Member: CDfMutex::Init, public +// +// Synopsis: This routine creates and initializes the global +// critical section if it does not already exist. +// It then attaches to the global critical section. +// +// Arguments: [lpName] - Supplies the critical section name +// +// Returns: Appropriate status code +// +// History: 26-Jul-94 DonnaLi Created +// +// Algorithm: Uses a mutex to serialize global critical section +// creation and initialization +// The name passed in is used to create or open the +// semaphore embedded in the global critical section. +// The name with the first CHARS_TO_SKIP characters +// skipped is used to create or open the file mapping +// containing global state of the critical section. +// If a file mapping with that name already exists, +// it is not reinitialized. The caller instead just +// attaches to it. +// +//--------------------------------------------------------------- + +SCODE +CDfMutex::Init( + TCHAR * lpName + ) +{ + HANDLE hGlobalMutex; + SCODE scResult = S_OK; + DWORD dwResult; + LPSECURITY_ATTRIBUTES lpsa = NULL; + +#if WIN32 == 100 || WIN32 > 200 + CGlobalSecurity gs; + if (FAILED(scResult = gs.Init())) return scResult; +#else + LPSECURITY_ATTRIBUTES gs = NULL; +#endif + + // + // Serialize all global critical section initialization + // + + hGlobalMutex = CreateMutex( + gs, // LPSECURITY_ATTRIBUTES lpsa + TRUE, // BOOL fInitialOwner + GLOBAL_CS // LPCTSTR lpszMutexName + ); + + // + // If the mutex create/open failed, then bail + // + + if ( !hGlobalMutex ) + { + return LAST_SCODE; + } + + if ( GetLastError() == ERROR_ALREADY_EXISTS ) + { + + // + // Since the mutex already existed, the request for ownership has + // no effect. + // + // wait for the mutex + // + + if ( WaitForSingleObject (hGlobalMutex, INFINITE) == WAIT_FAILED ) + { + scResult = LAST_SCODE; + CloseHandle (hGlobalMutex); + return scResult; + } + } + + // + // We now own the global critical section creation mutex. Create/Open the + // named semaphore. + // + + _hLockSemaphore = CreateSemaphore ( + gs, // LPSECURITY_ATTRIBUTES lpsa + 0, // LONG cSemInitial + MAXLONG-1, // LONG cSemMax + lpName // LPCTSTR lpszSemName + ); + + // + // If the semaphore create/open failed, then bail + // + + if ( !_hLockSemaphore ) + { + scResult = LAST_SCODE; + } + else + { + // + // Create/open a shared file mapping object + // If we created it, we need to initialize the global structure. + // Otherwise just point to it. + // The global critical section creation mutex allows us to do + // this safely. + // + + _hSharedMapping = CreateFileMapping ( + (HANDLE)0xffffffff, // HANDLE hFile + gs, // LPSECURITY_ATTRIBUTES lpsa + PAGE_READWRITE, // DWORD fdwProtect + 0, // DWORD dwMaximumSizeHigh + 1024, // DWORD dwMaximumSizeLow + lpName+CHARS_TO_SKIP// LPCTSTR lpszMapName + ); + + if ( !_hSharedMapping ) + { + scResult = LAST_SCODE; + CloseHandle (_hLockSemaphore); + _hLockSemaphore = (HANDLE)NULL; + } + else + { + dwResult = GetLastError(); + + _pGlobalPortion = (PGLOBAL_SHARED_CRITICAL_SECTION) + MapViewOfFile ( + _hSharedMapping, // HANDLE hMapObject + FILE_MAP_WRITE, // DWORD fdwAccess + 0, // DWORD dwOffsetHigh + 0, // DWORD dwOffsetLow + 0 // DWORD cbMap + ); + + if (!_pGlobalPortion) + { + scResult = LAST_SCODE; + CloseHandle (_hLockSemaphore); + _hLockSemaphore = (HANDLE)NULL; + CloseHandle (_hSharedMapping); + _hSharedMapping = (HANDLE)NULL; + } + else if (dwResult != ERROR_ALREADY_EXISTS ) + { + // + // We created the file mapping, so initialize the + // global portion. + // + + _pGlobalPortion->LockCount = -1; +#ifdef SUPPORT_RECURSIVE_LOCK + _pGlobalPortion->RecursionCount = 0; + _pGlobalPortion->OwningThread = 0; +#else +#if DBG == 1 + _pGlobalPortion->OwningThread = 0; +#endif +#endif + _pGlobalPortion->Reserved = 0; + } + } + } + + + ReleaseMutex (hGlobalMutex); + CloseHandle (hGlobalMutex); + + return scResult; +} + + +//+-------------------------------------------------------------- +// +// Member: CDfMutex::~CDfMutex, public +// +// Synopsis: This routine detaches from an existing global +// critical section. +// +// History: 26-Jul-94 DonnaLi Created +// +// Algorithm: Create or get the entry from the multistream +// +//--------------------------------------------------------------- + +CDfMutex::~CDfMutex( + void + ) +{ + //If we're holding the mutex, we need to get rid of it here. + +#ifdef SUPPORT_RECURSIVE_LOCK + if ((_pGlobalPortion) && + (_pGlobalPortion->OwningThread == GetCurrentThreadId())) + { +#else + if (_pGlobalPortion) + { +#if DBG == 1 + olAssert (_pGlobalPortion->OwningThread == 0 || _pGlobalPortion->OwningThread == GetCurrentThreadId()); +#endif +#endif + Release(); + } + + if ( _pGlobalPortion ) + { + UnmapViewOfFile (_pGlobalPortion); + } + + if ( _hLockSemaphore ) + { + CloseHandle (_hLockSemaphore); + } + if ( _hSharedMapping ) + { + CloseHandle (_hSharedMapping); + } +} + +//+-------------------------------------------------------------- +// +// Member: CDfMutex::Take, public +// +// Synopsis: This routine enters the global critical section. +// +// Arguments: [dwTimeout] - Supplies the timeout +// +// Returns: Appropriate status code +// +// History: 26-Jul-94 DonnaLi Created +// +// Algorithm: Enters the critical section if nobody owns it or +// if the current thread already owns it. +// Waits for the critical section otherwise. +// +//--------------------------------------------------------------- + +SCODE +CDfMutex::Take ( + DWORD dwTimeout + ) +{ + olAssert (_pGlobalPortion->LockCount >= -1); + +#ifdef SUPPORT_RECURSIVE_LOCK + + olAssert (_pGlobalPortion->RecursionCount >= 0); + + DWORD ThreadId; + + ThreadId = GetCurrentThreadId(); + +#endif + + // + // Increment the lock variable. On the transition to 0, the caller + // becomes the absolute owner of the lock. Otherwise, the caller is + // either recursing, or is going to have to wait + // + + if ( !InterlockedIncrement (&_pGlobalPortion->LockCount) ) + { + // + // lock count went from -1 to 0, so the caller + // is the owner of the lock + // + +#ifdef SUPPORT_RECURSIVE_LOCK + _pGlobalPortion->RecursionCount = 1; + _pGlobalPortion->OwningThread = ThreadId; +#else +#if DBG == 1 + _pGlobalPortion->OwningThread = GetCurrentThreadId(); +#endif +#endif + return S_OK; + } + else + { +#ifdef SUPPORT_RECURSIVE_LOCK + // + // If the caller is recursing, then increment the recursion count + // + + if ( _pGlobalPortion->OwningThread == ThreadId ) + { + _pGlobalPortion->RecursionCount++; + return S_OK; + } + else + { +#else +#if DBG == 1 + olAssert (_pGlobalPortion->OwningThread != GetCurrentThreadId()); +#endif +#endif + switch (WaitForSingleObject( + _hLockSemaphore, + dwTimeout + )) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: +#ifdef SUPPORT_RECURSIVE_LOCK + _pGlobalPortion->RecursionCount = 1; + _pGlobalPortion->OwningThread = ThreadId; +#else +#if DBG == 1 + _pGlobalPortion->OwningThread = GetCurrentThreadId(); +#endif +#endif + return S_OK; + case WAIT_TIMEOUT: + return STG_E_INUSE; + default: + return LAST_SCODE; + } +#ifdef SUPPORT_RECURSIVE_LOCK + } +#endif + } +} + + +//+-------------------------------------------------------------- +// +// Member: CDfMutex::Release, public +// +// Synopsis: This routine leaves the global critical section +// +// History: 26-Jul-94 DonnaLi Created +// +// Algorithm: Leaves the critical section if this is the owning +// thread. +// +//--------------------------------------------------------------- + +VOID +CDfMutex::Release( + void + ) +{ +#ifdef SUPPORT_RECURSIVE_LOCK + if ( _pGlobalPortion->OwningThread != GetCurrentThreadId() ) return; +#else +#if DBG == 1 + olAssert (_pGlobalPortion->OwningThread == 0 || _pGlobalPortion->OwningThread == GetCurrentThreadId()); +#endif +#endif + + olAssert (_pGlobalPortion->LockCount >= -1); + +#ifdef SUPPORT_RECURSIVE_LOCK + olAssert (_pGlobalPortion->RecursionCount >= 0); + + // + // decrement the recursion count. If it is still non-zero, then + // we are still the owner so don't do anything other than dec the lock + // count + // + + if ( --_pGlobalPortion->RecursionCount ) + { + InterlockedDecrement(&_pGlobalPortion->LockCount); + } + else + { + // + // We are really leaving, so give up ownership and decrement the + // lock count + // + + _pGlobalPortion->OwningThread = 0; +#else +#if DBG == 1 + _pGlobalPortion->OwningThread = 0; +#endif +#endif + + // + // Check to see if there are other waiters. If so, then wake up a waiter + // + + if ( InterlockedDecrement(&_pGlobalPortion->LockCount) >= 0 ) + { + ReleaseSemaphore( + _hLockSemaphore, // HANDLE hSemaphore + 1, // LONG cReleaseCount + NULL // LPLONG lplPreviousCount + ); + } +#ifdef SUPPORT_RECURSIVE_LOCK + } +#endif +} diff --git a/private/ole32/dcomss/objex/shrmem/stg/simplell.cxx b/private/ole32/dcomss/objex/shrmem/stg/simplell.cxx new file mode 100644 index 000000000..74051a040 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/simplell.cxx @@ -0,0 +1,128 @@ + +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + simpleLL.cxx + +Abstract: + + This module contains definitions of non inline member functions for the + CSimpleLinkList class, which is a linked list without reference counting. + +Author: + + Satish Thatte (SatishT) 11/20/95 Created all the code below except where + otherwise indicated. + +--*/ + +#include <or.hxx> +#include <simpleLL.hxx> + + + +void* +CSimpleLinkList::pop() + +/*++ +Routine Description: + + Delete first item in the CSimpleLinkList and return it + +--*/ + +{ + if (!pLnkFirst) return NULL; + + void* result = pLnkFirst->data; + Link OR_BASED *oldFirst = pLnkFirst; + pLnkFirst = pLnkFirst->next; + if (!pLnkFirst) pLnkLast = NULL; // nothing left + DELETE_OR_BASED(Link,oldFirst); + + lCount--; + return result; +} + + +void* +CSimpleLinkList::nth(long lOrdinal) + +/*++ +Routine Description: + + Simply return the Nth data item -- starting the count at 0. + +--*/ + +{ + if (!pLnkFirst) return NULL; // empty list + + Link OR_BASED * pLnkCurr = pLnkFirst; + long lCount = 0; + + while (pLnkCurr && (lCount++ < lOrdinal)) + pLnkCurr = pLnkCurr->next; + + if (!pLnkCurr) return NULL; // not found + else return pLnkCurr->data; +} + +void +CSimpleLinkList::rotate(long lDegree) + +/*++ +Routine Description: + + This routine imagines that the list is in fact circular and + rotates it by lDegree -- using pop and enque for modularity. + We could actually move links around, but this operation is + not frequent enough (once for every NS lookup). Here we pay the + price of not having a true circular list (we moved away from + the true circular list for ref counting). + +--*/ + +{ + if (!pLnkFirst) return; // nothing to rotate; + + void *pCurr; + + for (long i = 0; i < (lDegree % lCount); i++) { + pCurr = pop(); + enque(pCurr); + } +} + + + +void CSimpleLinkList::clear() { // deletes all links but not the data + + Link OR_BASED * pLnkCurr = pLnkFirst; + + while (pLnkCurr) + { + Link OR_BASED * pLnkDel = pLnkCurr; + pLnkCurr = pLnkCurr->next; + DELETE_OR_BASED(Link,pLnkDel); + } + + pLnkFirst = pLnkLast = NULL; +} + + + +void* +CSimpleLinkListIterator::next() { // advance the iterator and return next void + + if (!ptr) return NULL; + + void* result = ptr->data; + ptr = ptr->next; + return result; +} + diff --git a/private/ole32/dcomss/objex/shrmem/stg/simplell.hxx b/private/ole32/dcomss/objex/shrmem/stg/simplell.hxx new file mode 100644 index 000000000..f65cdced6 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/simplell.hxx @@ -0,0 +1,180 @@ + +/*++ + +Microsoft Windows NT RPC Name Service +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + simpleLL.hxx + +Abstract: + + This module contains the definition a simple linklist class + which avoids reference counting, and stored pointers of any kind. + +Author: + + Satish Thatte (SatishT) 11/20/95 Created all the code below except where + otherwise indicated. + +--*/ + + + +#ifndef _SimpleListType_ +#define _SimpleListType_ + +#include <base.hxx> + +#define NULL 0 + +/*++ + +Class Definition: + + CSimpleLinkList + +Abstract: + + This is a minimal linked list class, used when a link list is required + for short term use and the data could be pointers of any kind, not + necessarily pointers to types derived from IDataItem, as required + for the CLinkList class. + +--*/ + +class CSimpleLinkList +{ + + friend class CSimpleLinkListIterator; + + protected: + + struct Link + { + Link OR_BASED *next; + void* data; + Link(void* a, Link OR_BASED * n) + { + data = a; + next = n; + } + + ~Link() {} + + void * operator new(size_t s) + { + return OrMemAlloc(s); + } + + void operator delete(void * p) // do not inherit this! + { + OrMemFree(p); + } + }; + + Link OR_BASED * pLnkFirst; + Link OR_BASED * pLnkLast; + + long lCount; + + public: + + CSimpleLinkList() { + pLnkFirst = pLnkLast = NULL; + lCount = 0; + } + + void clear(); + + ~CSimpleLinkList() { + clear(); + } + + void enque(void* x) + { + if (pLnkLast) + { + NEW_OR_BASED(pLnkLast->next,Link,(x, NULL)); + pLnkLast = pLnkLast->next; + } + else + { + NEW_OR_BASED(pLnkLast,Link,(x,NULL)); + pLnkFirst = pLnkLast; + } + + lCount++; + } + + void push(void* x) + { + NEW_OR_BASED(pLnkFirst,Link,(x, pLnkFirst)); + if (!pLnkLast) pLnkLast = pLnkFirst; + + lCount++; + } + + void insert(void* x) // at the end in this class + { enque(x); } + + void* pop(); // remove first item and return it + + void* nth(long lOrdinal); + + long size() { return lCount; } + + void rotate(long lDegree); + + inline void *operator new(size_t); + + inline void operator delete(void*); // do not inherit this! +}; + + +inline void * +CSimpleLinkList::operator new(size_t s) +{ + return OrMemAlloc(s); +} + +inline void +CSimpleLinkList::operator delete(void* p) // do not inherit this! +{ + OrMemFree(p); +} + + +/*++ + +Class Definition: + + CSimpleLinkListIterator + +Abstract: + + An iterator class for traversing a CSimpleLinkList. + +--*/ + + +class CSimpleLinkListIterator { + + CSimpleLinkList::Link OR_BASED *ptr; // the current link + + public: + + CSimpleLinkListIterator(CSimpleLinkList& source) { + ptr = source.pLnkFirst; + } + + void* next(); // advance the iterator and return next void + + int finished() { return ptr == NULL; } + +}; + + + +#endif // _SimpleListType_ diff --git a/private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx b/private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx new file mode 100644 index 000000000..9f5c13f84 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx @@ -0,0 +1,1185 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1994. +// +// File: smalloc.cxx +// +// Contents: Shared memory heap implementation +// +// Classes: +// +// Functions: +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// 10-May-95 KentCe Defer Heap Destruction to the last +// process detach. +// +//---------------------------------------------------------------------------- + +#include <or.hxx> + +#ifdef NEWPROPS +#define FULLIMPL +#endif + +// +// Take advantage of unique Win95 support of a shared heap. +// +#if defined(_CHICAGO_) + +#define HEAP_SHARED 0x04000000 // Secret feature of Win95 only. + +// +// Locate the following in a shared data segment. +// +#pragma data_seg(".sdata") + +HANDLE gs_hSharedHeap = NULL; // hSharedHeap Handle for Win95. +DFLUID gs_dfluid = LUID_BASE; // shared docfile global LUID + +#pragma data_seg() + +#define PRINTSTATS + +#else // defined(_CHICAGO_) + +#define DLL + +#define DEB_STATS 0x00010000 +#define DEB_PRINT 0x00020000 + +#ifdef DLL + +#define PERCENT(a,b,c) (int)((((double)a + (double)b) / (double)c) * 100.0) + +#define PRINTSTATS \ + memDebugOut((DEB_STATS, \ + "Total size: %lu, Space: Free: %lu, Alloced: %lu"\ + " Blocks: Free: %lu, Alloced: %lu"\ + " Efficiency: %.2f%%\n",\ + _cbSize,\ + GetHeader()->_ulFreeBytes,\ + GetHeader()->_ulAllocedBytes,\ + GetHeader()->_ulFreeBlocks,\ + GetHeader()->GetAllocedBlocks(),\ + PERCENT(GetHeader()->_ulFreeBytes,\ + GetHeader()->_ulAllocedBytes, _cbSize))); + +#else +#define PRINTSTATS \ + printf( \ + "Total size: %lu, Free space: %lu, Alloced space: %lu"\ + " Efficiency: %.2f%%\n",\ + _cbSize,\ + GetHeader()->_ulFreeBytes,\ + GetHeader()->_ulAllocedBytes,\ + ((double)(GetHeader()->_ulFreeBytes +\ + GetHeader()->_ulAllocedBytes) / \ + (double)_cbSize) * (double)100); +#endif + + +#if DBG == 1 +inline BOOL IsAligned(void *pv) +{ + return !((ULONG)pv & 7); +} +#else +#define IsAligned(x) TRUE +#endif + + +#define SHAREDMEMBASE NULL + +#endif // !defined(_CHICAGO_) + +ULONG g_ulHeapName; +CSmAllocator g_SmAllocator; +CSharedMemoryBlock g_smb; + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Init, public +// +// Synopsis: Initialize heap for use +// +// Arguments: [pszName] -- Name of shared memory heap to use +// +// Returns: Appropriate status code +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// +// Remarks: Review the class destructor if you change this code. +// +//---------------------------------------------------------------------------- + +#if !defined(MULTIHEAP) +SCODE CSmAllocator::Init(LPWSTR pszName) +#else +SCODE CSmAllocator::Init(ULONG ulHeapName, BOOL fUnmarshal) +#endif +{ + SCODE sc = S_OK; + +#if !defined(MULTIHEAP) + // Initialize the mutex + sc = _dmtx.Init(TEXT("DocfileAllocatorMutex")); + if (FAILED(sc)) + { + return sc; + } + + sc = _dmtx.Take(DFM_TIMEOUT); + if (FAILED(sc)) + { + return sc; + } +#endif + +#if defined(_CHICAGO_) + // + // Create a new shared heap if this is the first time thru. + // + if (gs_hSharedHeap == NULL) + { + gs_hSharedHeap = HeapCreate(HEAP_SHARED, 0, 0); + } + + // + // We keep a copy of the shared heap as a flag so the destructor logic + // does the right thing. + // + // + m_hSharedHeap = gs_hSharedHeap; + +#else + CSharedMemoryBlock *psmb = NULL; +#ifdef MULTIHEAP + _cbSize = 0; + if (!fUnmarshal && this == &g_SmAllocator) // only for main thread + { + if (g_ulHeapName != 0) // the global shared memory block is active + { + _psmb = &g_smb; // needed for GetHeader + _pbBase = (BYTE *)(_psmb->GetBase()); // needed for GetHeader + if (_pbBase != NULL && GetHeader()->GetAllocedBlocks() == 0) + { // its' empty reuse it + psmb = _psmb; + _ulHeapName = g_ulHeapName; + memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init " + " reuse %x\n", g_ulHeapName)); + return sc; + } + } + else + { + psmb = _psmb = &g_smb; // initialize g_smb + } + } + + if (psmb == NULL) + { + psmb = _psmb = new CSharedMemoryBlock (); + if (psmb == NULL) + return STG_E_INSUFFICIENTMEMORY; + } + + WCHAR pszName[DOCFILE_SM_NAMELEN]; + wsprintf(pszName, L"DfSharedHeap%X", ulHeapName); +#else + psmb = &_smb; +#endif + // the SMB needs a few bytes for its own header. If we request + // a page sized allocation, those few header bytes will cause an + // extra page to be allocated, so to prevent that we subtract off + // the header space from our requests. + + sc = psmb->Init(pszName, + DOCFILE_SM_SIZE - psmb->GetHdrSize(), // reserve size + INITIALHEAPSIZE - psmb->GetHdrSize(), // commit size + SHAREDMEMBASE, // base address + NULL, // security descriptor + TRUE); // create if doesn't exist + + if (SUCCEEDED(sc)) + { + _cbSize = psmb->GetSize(); + _pbBase = (BYTE *)(psmb->GetBase()); +#ifdef MULTIHEAP + _ulHeapName = ulHeapName; +#endif + + if (psmb->Created()) + { + CBlockHeader *pbh = (CBlockHeader *) + (_pbBase + sizeof(CHeapHeader)); + + memAssert(IsAligned(pbh)); + pbh->SetFree(); + pbh->SetSize(_cbSize - sizeof(CHeapHeader)); + pbh->SetNext(0); + + memAssert((BYTE *)pbh + pbh->GetSize() == _pbBase + _cbSize); + GetHeader()->SetFirstFree(GetOffset(pbh)); + GetHeader()->SetCompacted(); + GetHeader()->ResetAllocedBlocks(); + GetHeader()->ResetLuid(); + +#if DBG == 1 + GetHeader()->_ulAllocedBytes = 0; + GetHeader()->_ulFreeBytes = + pbh->GetSize() - sizeof(CBlockPreHeader); + GetHeader()->_ulFreeBlocks = 1; +#endif + } + +#ifdef MULTIHEAP + if (psmb == &g_smb) + g_ulHeapName = ulHeapName; // store global heap name +#endif + PRINTSTATS; + } +#endif + +#if defined(MULTIHEAP) + memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init sc=%x %x\n", + sc, ulHeapName)); +#else + _dmtx.Release(); + memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init sc=%x\n", + sc)); +#endif + + return sc; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::QueryInterface, public +// +// Synopsis: Standard QI +// +// Arguments: [iid] - Interface ID +// [ppvObj] - Object return +// +// Returns: Appropriate status code +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP CSmAllocator::QueryInterface(REFIID iid, void **ppvObj) +{ + SCODE sc; + + memDebugOut((DEB_ITRACE, "In CSmAllocator::QueryInterface:%p()\n", this)); + + if (IsEqualIID(iid, IID_IMalloc) || IsEqualIID(iid, IID_IUnknown)) + { + *ppvObj = (IMalloc *) this; + CSmAllocator::AddRef(); + } + else + sc = E_NOINTERFACE; + + memDebugOut((DEB_ITRACE, "Out CSmAllocator::QueryInterface\n")); + + return ResultFromScode(sc); +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::AddRef, public +// +// Synopsis: Add reference +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(ULONG) CSmAllocator::AddRef(void) +{ +#ifdef MULTIHEAP + return ++_cRefs; +#else + return 1; +#endif +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Release, public +// +// Synopsis: Release +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(ULONG) CSmAllocator::Release(void) +{ +#ifdef MULTIHEAP + ULONG cRefs = --_cRefs; + if (cRefs <= 0) + delete this; + return cRefs; +#else + return 0; +#endif +} + +#if !defined(_CHICAGO_) + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::FindBlock, private +// +// Synopsis: Find an appropriately sized block in the heap. +// +// Arguments: [cb] -- Size of block required +// +// Returns: Pointer to block, NULL on failure +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +CBlockHeader * CSmAllocator::FindBlock(ULONG cb, CBlockHeader **ppbhPrev) +{ + CBlockHeader *pbhCurrent = GetAddress(GetHeader()->GetFirstFree()); + *ppbhPrev = NULL; + + while (pbhCurrent != NULL) + { + memAssert(IsAligned(pbhCurrent)); + + if ((pbhCurrent->GetSize() >= cb) && (pbhCurrent->IsFree())) + { + memAssert(pbhCurrent->GetSize() < _cbSize); //MULTIHEAP + memAssert((BYTE *)pbhCurrent >= _pbBase && + (BYTE *)pbhCurrent < _pbBase + _cbSize); // MULTIHEAP + break; + } + else + { + memAssert (pbhCurrent->GetNext() <= _cbSize); // MULITHEAP + *ppbhPrev = pbhCurrent; + pbhCurrent = GetAddress(pbhCurrent->GetNext()); + } + } + return pbhCurrent; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Reset, private +// +// Synopsis: Reset the heap to its original empty state. +// +// Returns: Appropriate status code +// +// History: 04-Apr-94 PhilipLa Created +// +// Notes: There is only one caller of this function. Hence it is +// declared inline. +// +//---------------------------------------------------------------------------- + +inline SCODE CSmAllocator::Reset(void) +{ + memDebugOut((DEB_ITRACE, "In CSmAllocator::Reset:%p()\n", this)); +#ifdef RESETOK +#ifdef MULTIHEAP + CSharedMemoryBlock *psmb = _psmb; +#else + CSharedMemoryBlock *psmb = &_smb; +#endif + psmb->Reset(); + _cbSize = psmb->GetSize(); + _pbBase = (BYTE *)(psmb->GetBase()); + + CBlockHeader *pbh = (CBlockHeader *) + (_pbBase + sizeof(CHeapHeader)); + + pbh->SetFree(); + pbh->SetSize(_cbSize - sizeof(CHeapHeader)); + pbh->SetNext(0); + + memAssert((BYTE *)pbh + pbh->GetSize() == _pbBase + _cbSize); + GetHeader()->SetFirstFree(GetOffset(pbh)); + GetHeader()->SetCompacted(); + GetHeader()->ResetAllocedBlocks(); + +#if DBG == 1 + GetHeader()->_ulAllocedBytes = 0; + GetHeader()->_ulFreeBytes = + pbh->GetSize() - sizeof(CBlockPreHeader); + GetHeader()->_ulFreeBlocks = 1; +#endif + + memDebugOut((DEB_ITRACE, "Out CSmAllocator::Reset\n")); +#else + HeapMinimize(); +#endif + return S_OK; +} + +#endif + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Alloc, public +// +// Synopsis: Allocate memory +// +// Arguments: [cb] -- Number of bytes to allocate +// +// Returns: Pointer to block, NULL if failure +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(void *) CSmAllocator::Alloc ( + ULONG cb ) +{ + void *pv = NULL; + +#if !defined(_CHICAGO_) + CBlockHeader *pbh = NULL; + CBlockHeader *pbhPrev = NULL; + SCODE sc; +#endif + + memDebugOut((DEB_ITRACE, "In CSmAllocator::Alloc:%p(%lu)\n", this, cb)); + +#if defined(_CHICAGO_) + + pv = HeapAlloc(m_hSharedHeap, 0, cb); + +#else // !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + CLockDfMutex lckdmtx(_dmtx); +#endif + + Sync(); + + //The block must be at least large enough to hold the standard + // header (size and free bit) and a pointer to the next block. + if (cb < sizeof(CBlockHeader) - sizeof(CBlockPreHeader)) + { + cb = sizeof(CBlockHeader) - sizeof(CBlockPreHeader); + } + + cb = cb + sizeof(CBlockPreHeader); + + //Make cb 8 byte aligned. + if (cb & 7) + { + cb += (8 - (cb & 7)); + } + + memAssert((cb >= CBLOCKMIN) && "Undersized block requested."); + pbh = FindBlock(cb, &pbhPrev); + + if (pbh == NULL) + { + if (!(GetHeader()->IsCompacted())) + { + //Do a heap merge and try to allocate again. + CSmAllocator::HeapMinimize(); + pbh = FindBlock(cb, &pbhPrev); + } + + if (pbh == NULL) + { +#ifdef MULTIHEAP + CSharedMemoryBlock *psmb = _psmb; +#else + CSharedMemoryBlock *psmb = &_smb; +#endif +#if DBG == 1 + ULONG ulOldSize = psmb->GetSize(); +#endif + sc = psmb->Commit(_cbSize + max(cb, MINHEAPGROWTH)); + if (SUCCEEDED(sc)) + { + //Attach newly committed space to free list. + CBlockHeader *pbhNew = (CBlockHeader *) + (_pbBase + _cbSize); + + _cbSize = psmb->GetSize(); + + memAssert((pbhPrev == NULL) || (pbhPrev->GetNext() == 0)); + memAssert(_cbSize > ulOldSize); + + if (pbhPrev != NULL) + { + pbhPrev->SetNext(GetOffset(pbhNew)); + } + else + { + GetHeader()->SetFirstFree(GetOffset(pbhNew)); + } + + pbhNew->SetNext(0); + pbhNew->SetSize(max(cb, MINHEAPGROWTH)); + pbhNew->SetFree(); + + + memAssert((BYTE *)pbhNew + pbhNew->GetSize() == + _pbBase + _cbSize); + +#if DBG == 1 + GetHeader()->_ulFreeBytes += + pbhNew->GetSize() - sizeof(CBlockPreHeader); + GetHeader()->_ulFreeBlocks += 1; +#endif + + pbh = pbhNew; + } + } + } + + if (pbh != NULL) + { + //Allocate the found block. + if ((pbh->GetSize() > cb) && + (pbh->GetSize() - cb > CBLOCKMIN)) + { + //Split an existing block. No free list update required. + + CBlockHeader *pbhNew = + (CBlockHeader *)((BYTE *)pbh + (pbh->GetSize() - cb)); + + pbhNew->SetSize(cb); + pbhNew->ResetFree(); + pbhNew->SetNext(0); + + pbh->SetSize(pbh->GetSize() - cb); +#if DBG == 1 + GetHeader()->_ulAllocedBytes += (cb - sizeof(CBlockPreHeader)); + //The number of available free bytes decreases by the number + // of bytes allocated + GetHeader()->_ulFreeBytes -= cb; +#endif + memAssert(IsAligned(pbhNew)); + memAssert(IsAligned(pbh)); + + pbh = pbhNew; + } + else + { + //Use an entire block. Update free list appropriately. + memAssert(IsAligned(pbh)); + pbh->ResetFree(); + if (pbhPrev != NULL) + { + pbhPrev->SetNext(pbh->GetNext());; + } + else + { + GetHeader()->SetFirstFree(pbh->GetNext()); + } +#if DBG == 1 + GetHeader()->_ulAllocedBytes += (cb - sizeof(CBlockPreHeader)); + GetHeader()->_ulFreeBytes -= (cb - sizeof(CBlockPreHeader)); + GetHeader()->_ulFreeBlocks--; +#endif + pbh->SetNext(0); + } + } + + if (pbh != NULL) + { + pv = (BYTE *)pbh + sizeof(CBlockPreHeader); + GetHeader()->IncrementAllocedBlocks(); + } +#endif // !defined(_CHICAGO_) + + memDebugOut((DEB_ITRACE, "Out CSmAllocator::Alloc=> %p\n", pv)); + +#if !defined(_CHICAGO_) + memAssert(IsAligned(pv)); +#endif // !defined(_CHICAGO_) + + PRINTSTATS; + +#if DBG == 1 + if (pv == NULL) + { +#if defined(_CHICAGO_) + memDebugOut((DEB_ERROR, + "Failed allocation of %lu bytes.\n", + cb)); +#else // !defined(_CHICAGO_) + memDebugOut((DEB_ERROR, + "Failed allocation of %lu bytes. Heap size is %lu\n", + cb, + _cbSize)); +#endif // !defined(_CHICAGO_) + } +#endif + + return pv; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Realloc, public +// +// Synopsis: Resize the block given +// +// Arguments: [pv] -- Pointer to block to realloc +// [cb] -- New size for block +// +// Returns: Pointer to new block, NULL if failure +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(void *) CSmAllocator::Realloc( + void *pv, + ULONG cb ) +{ + void *pvNew = NULL; +#ifdef FULLIMPL + memDebugOut((DEB_ITRACE, "In CSmAllocator::Realloc:%p()\n", this)); + +#if defined(_CHICAGO_) + + pvNew = HeapReAlloc(m_hSharedHeap, 0, pv, cb); + +#else +#if !defined(MULTIHEAP) + CLockDfMutex lckdmtx(_dmtx); +#endif + + if ((pv != NULL) && (cb == 0)) + { + CSmAllocator::Free(pv); + return NULL; + } + + pvNew = CSmAllocator::Alloc(cb); + if (pvNew != NULL && pv != NULL) + { + //Copy contents + memcpy(pvNew, pv, min(cb, CSmAllocator::GetSize(pv))); + CSmAllocator::Free(pv); + } +#endif + + memDebugOut((DEB_ITRACE, "Out CSmAllocator::Realloc\n")); +#endif + PRINTSTATS; + + return pvNew; +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::DoFree, private +// +// Synopsis: Free a memory block +// +// Arguments: [pv] -- Pointer to block to free +// +// Returns: void +// +// History: 26-Jul-95 SusiA Created +// +//---------------------------------------------------------------------------- +inline void CSmAllocator::DoFree(void *pv) +{ + memDebugOut((DEB_ITRACE, "In CSmAllocator::DoFree:%p(%p)\n", this, pv)); + +#if defined(_CHICAGO_) + + if (pv != NULL) + { + HeapFree(m_hSharedHeap, 0, pv); + } + +#else + + Sync(); + + if (pv != NULL) + { + CBlockHeader *pbh = (CBlockHeader *) + ((BYTE *)pv - sizeof(CBlockPreHeader)); +#ifdef MULTIHEAP + ULONG ulSize = pbh->GetSize(); // temporary to hold size for debug +#endif + + memAssert(IsAligned(pbh)); + memAssert((BYTE*)pbh >= _pbBase && + (BYTE*)pbh < _pbBase + _cbSize); // MULTIHEAP + pbh->SetFree(); + pbh->SetNext(GetHeader()->GetFirstFree()); + + GetHeader()->SetFirstFree(GetOffset(pbh)); + GetHeader()->ResetCompacted(); + if (GetHeader()->DecrementAllocedBlocks() == 0) + { +#ifdef MULTIHEAP + Uninit(); +#else + + Reset(); +#endif + } + +#if DBG == 1 + else + { + GetHeader()->_ulAllocedBytes -= + (pbh->GetSize() - sizeof(CBlockPreHeader)); + GetHeader()->_ulFreeBytes += + (pbh->GetSize() - sizeof(CBlockPreHeader)); + GetHeader()->_ulFreeBlocks++; + } +#endif +#ifdef MULTIHEAP + memDebugOut((DEB_ITRACE, "Out CSmAllocator::DoFree. Freed %lu\n", + ulSize)); // don't access shared memory +#else + memDebugOut((DEB_ITRACE, "Out CSmAllocator::DoFree. Freed %lu\n", + pbh->GetSize())); +#endif + } +#endif +#if !defined(MULTIHEAP) + // the shared heap may have been unmapped, mustn't read it now + PRINTSTATS; +#endif +} +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Free, public +// +// Synopsis: Free a memory block +// +// Arguments: [pv] -- Pointer to block to free +// +// Returns: void +// +// History: 29-Mar-94 PhilipLa Created +// 26-Jul-95 SusiA Moved bulk of work to DoFree to +// share code between Free and +// FreeNoMutex +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(void) CSmAllocator::Free(void *pv) +{ + memDebugOut((DEB_ITRACE, "In CSmAllocator::Free:%p(%p)\n", this, pv)); + +#if !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + CLockDfMutex lckdmtx(_dmtx); +#endif +#endif + DoFree(pv); + +} +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::FreeNoMutex, public +// +// Synopsis: Free a memory block without first aquiring the mutex. +// This function is equivalent to Free above, except that is does +// not attempt to first aquire the mutex. It should be used OLNY +// when the calling function guarantees to already have the mutex. +// +// +// Arguments: [pv] -- Pointer to block to free +// +// Returns: void +// +// History: 19-Jul-95 SusiA Created +// +//---------------------------------------------------------------------------- + +void CSmAllocator::FreeNoMutex(void *pv) +{ + memDebugOut((DEB_ITRACE, "In CSmAllocator::FreeNoMutex:%p(%p)\n", this, pv)); + +#if !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + //ensure we already have the mutex + memAssert(_dmtx.HaveMutex()); +#endif +#endif + DoFree(pv); + +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetSize, public +// +// Synopsis: Return the size of the given block +// +// Arguments: [pv] -- Block to get size of +// +// Returns: Size of block pointer to by pv +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(ULONG) CSmAllocator::GetSize(void * pv) +{ +#if !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + CLockDfMutex lckdmtx(_dmtx); +#endif +#endif + + Sync(); + + ULONG ulSize = (ULONG)-1; +#ifdef FULLIMPL + memDebugOut((DEB_ITRACE, "In CSmAllocator::GetSize:%p()\n", this)); + if (pv != NULL) + { +#if defined(_CHICAGO_) + ulSize = HeapSize(m_hSharedHeap, 0, pv); +#else + CBlockHeader *pbh; + pbh = (CBlockHeader *)((BYTE *)pv - sizeof(CBlockPreHeader)); + + ulSize = pbh->GetSize() - sizeof(CBlockPreHeader); +#endif + } + + memDebugOut((DEB_ITRACE, "Out CSmAllocator::GetSize\n")); +#endif + return ulSize; +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::DidAlloc, public +// +// Synopsis: Return '1' if this heap allocated pointer at pv +// +// Arguments: [pv] -- Pointer to block +// +// Returns: '1' == This heap allocated block. +// '0' == This heap did not allocate block. +// '-1' == Could not determine if this heap allocated block. +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(int) CSmAllocator::DidAlloc(void FAR * pv) +{ + int i = -1; +#ifdef FULLIMPL + memDebugOut((DEB_ITRACE, "In CSmAllocator::DidAlloc:%p()\n", this)); +#if defined(_CHICAGO_) + if (HeapValidate(m_hSharedHeap, 0, pv)) + { + i = 1; + } + else + { + i = 0; + } +#else // !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + CLockDfMutex lckdmtx(_dmtx); +#endif + + i = ((BYTE *)pv >= _pbBase) && ((BYTE *)pv <= (_pbBase + _cbSize)); +#endif // !defined(_CHICAGO_) + memDebugOut((DEB_ITRACE, "Out CSmAllocator::DidAlloc\n")); +#endif + return i; +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::HeapMinimize, public +// +// Synopsis: Minimize the heap +// +// Arguments: None. +// +// Returns: void. +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +STDMETHODIMP_(void) CSmAllocator::HeapMinimize(void) +{ +#if !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + CLockDfMutex lckdmtx(_dmtx); +#endif +#endif + + memDebugOut((DEB_ITRACE, "In CSmAllocator::HeapMinimize:%p()\n", this)); + + PRINTSTATS; + +#if defined(_CHICAGO_) + + HeapCompact(m_hSharedHeap, 0); + +#else // !defined(_CHICAGO_) + + CBlockHeader *pbhCurrent; + CBlockHeader *pbhLast = NULL; + BYTE *pbEnd = _pbBase + _cbSize; + +#if DBG == 1 + PrintFreeBlocks(); + GetHeader()->_ulAllocedBytes = 0; + GetHeader()->_ulFreeBytes = 0; + GetHeader()->_ulFreeBlocks = 0; +#endif + + pbhCurrent = (CBlockHeader *)(_pbBase + sizeof(CHeapHeader)); + + while ((BYTE *)pbhCurrent < pbEnd) + { + memAssert(IsAligned(pbhCurrent)); + memAssert((pbhCurrent->GetSize != 0) && + "Zero size block found."); + if (pbhCurrent->IsFree()) + { + //Check last block. If adjacent, merge them. If not, + // update pbhNext. + + if (pbhLast == NULL) + { + GetHeader()->SetFirstFree(GetOffset(pbhCurrent)); +#if DBG == 1 + GetHeader()->_ulFreeBlocks = 1; +#endif + } + else + { + if (pbhLast->GetSize() + GetOffset(pbhLast) == + GetOffset(pbhCurrent)) + { + //Merge the blocks. + pbhLast->SetSize(pbhLast->GetSize() + + pbhCurrent->GetSize()); + pbhCurrent = pbhLast; + } + else + { +#if DBG == 1 + GetHeader()->_ulFreeBytes += + (pbhLast->GetSize() - sizeof(CBlockPreHeader)); + GetHeader()->_ulFreeBlocks++; +#endif + pbhLast->SetNext(GetOffset(pbhCurrent)); + } + } + pbhLast = pbhCurrent; + } +#if DBG == 1 + else + { + GetHeader()->_ulAllocedBytes += + (pbhCurrent->GetSize() - sizeof(CBlockPreHeader)); + } +#endif + //Move to next block. + pbhCurrent = + (CBlockHeader *)((BYTE *)pbhCurrent + pbhCurrent->GetSize()); + } + + if (pbhLast != NULL) + { + +#if DBG == 1 + GetHeader()->_ulFreeBytes += + (pbhLast->GetSize() - sizeof(CBlockPreHeader)); +#endif + pbhLast->SetNext(0); + } + else + { + GetHeader()->SetFirstFree(0); + } + + GetHeader()->SetCompacted(); +#if DBG == 1 + PrintFreeBlocks(); +#endif + +#endif // !defined(_CHICAGO_) + + memDebugOut((DEB_ITRACE, "Out CSmAllocator::HeapMinimize\n")); + + PRINTSTATS; +} + +#if !defined(_CHICAGO_) +#if DBG == 1 +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::PrintFreeBlocks, private +// +// Synopsis: Debug code to print sizes of free blocks +// +// History: 25-Apr-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +void CSmAllocator::PrintFreeBlocks(void) +{ + CBlockHeader *pbhCurrent = GetAddress(GetHeader()->GetFirstFree()); + + memDebugOut((DEB_PRINT, "There are %lu total free blocks\n", + GetHeader()->_ulFreeBlocks)); + + while (pbhCurrent != NULL) + { + memDebugOut((DEB_PRINT, "Free block %p has size %lu\n", pbhCurrent, + pbhCurrent->GetSize())); + pbhCurrent = GetAddress(pbhCurrent->GetNext()); + } +} +#endif + +#ifdef MULTIHEAP +#if DBG == 1 +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::PrintAllocatedBlocks, private +// +// Synopsis: Debug code to find allocated block(s) that leaked +// +// History: 25-Nov-95 HenryLee Created +// +//---------------------------------------------------------------------------- +void CSmAllocator::PrintAllocatedBlocks(void) +{ + CBlockHeader *pbhCurrent; + CBlockHeader *pbhLast = NULL; + BYTE *pbEnd = _pbBase + _cbSize; + ULONG *pul; + + pbhCurrent = (CBlockHeader *)(_pbBase + sizeof(CHeapHeader)); + + while ((BYTE *)pbhCurrent < pbEnd) + { + memAssert(IsAligned(pbhCurrent)); + memAssert((pbhCurrent->GetSize != 0) && "Zero size block found."); + if (!pbhCurrent->IsFree()) + { + pul = (ULONG *)((BYTE *)pbhCurrent + sizeof(CBlockHeader)); + memDebugOut((DEB_PRINT, "PrintAllocatedBlocks %p %8x %8x\n", + pul, *pul, *(pul+1))); + + } + pbhCurrent = + (CBlockHeader *)((BYTE *)pbhCurrent + pbhCurrent->GetSize()); + } +} +#endif // DBG == 1 + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::SetState +// +// Synopsis: replace thread local state by PerContext state +// +// History: 20-Nov-95 Henrylee Created +// +//---------------------------------------------------------------------------- +void CSmAllocator::SetState (CSharedMemoryBlock *psmb, BYTE * pbBase, + ULONG ulHeapName, CPerContext ** ppcPrev, + CPerContext *ppcOwner) +{ + olDebugOut((DEB_ITRACE, "In CSmAllocator::SetState(%p, %p, %lx, %p, %p) (this == %p)\n", psmb, pbBase, ulHeapName, ppcPrev, ppcOwner, this)); + olDebugOut((DEB_ITRACE, "Current allocator owner == %p\n", _ppcOwner)); + + _psmb = psmb; + _pbBase = pbBase; + _cbSize = (_psmb) ? _psmb->GetSize() : 0; + _ulHeapName = ulHeapName; + // DFBASEPTR = _pbBase; + + if (ppcPrev != NULL) + *ppcPrev = _ppcOwner; + _ppcOwner = ppcOwner; + + //memAssert (g_smAllocator.GetBase() == DFBASEPTR); + olDebugOut((DEB_ITRACE, "Out CSmAllocator::SetState()\n")); +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetState +// +// Synopsis: retrive thread local allocator state into percontext +// +// History: 20-Nov-95 Henrylee Created +// +//---------------------------------------------------------------------------- +void CSmAllocator::GetState (CSharedMemoryBlock **ppsmb, + BYTE ** ppbBase, ULONG *pulHeapName) +{ + *ppsmb = _psmb; + *ppbBase = _pbBase; + *pulHeapName = _ulHeapName; +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Uninit +// +// Synopsis: unmap the shared memory region +// +// History: 20-Nov-95 Henrylee Created +// +//---------------------------------------------------------------------------- +SCODE CSmAllocator::Uninit () +{ + memDebugOut((DEB_ITRACE, "In CSmAllocator::Uninit\n")); + if (_psmb != NULL) + { + if (_psmb != &g_smb) + { + // This is last block in the heap, so we can close the heap + // now. There must be no shared heap accesses after this. + BOOL b = VirtualFree(_pbBase - sizeof(CSharedMemHeader), + 0, MEM_RELEASE); + delete _psmb; + } + else + { + Reset(); // for g_smb + } + _psmb = NULL; + } + _pbBase = NULL; + memDebugOut((DEB_ITRACE, "Out CSmAllocator::Uninit %x\n", _ulHeapName)); + + return S_OK; +} +#endif // MULTIHEAP + +#endif // !defined(_CHICAGO_) diff --git a/private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx b/private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx new file mode 100644 index 000000000..150ddf3b9 --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx @@ -0,0 +1,850 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1994. +// +// File: heap.hxx +// +// Contents: Heap code headers +// +// Classes: CHeap +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// 10-Apr095 HenryLee Added global LUID +// 10-May-95 KentCe Defer Heap Destruction to the last +// process detach. +// +//---------------------------------------------------------------------------- + +#ifndef __HEAP_HXX__ +#define __HEAP_HXX__ + +DECLARE_DEBUG(ol) + +#define olAssert(e) Win4Assert(e) +#define olVerify(e) Win4Assert(e) +#define olDebugOut(x) olInlineDebugOut x + + +#include <smblock.hxx> +#include <memdebug.hxx> +#include <smmutex.hxx> +#include <msf.hxx> +#include <df32.hxx> + +#ifdef COORD +#include <dfrlist.hxx> +#endif + +//Space to reserve for heap. +const ULONG MINHEAPGROWTH = 4096; +const ULONG INITIALHEAPSIZE = 16384; + +#ifdef MULTIHEAP +#include <ntpsapi.h> +class CPerContext; + +#endif + +//+------------------------------------------------------------------------- +// +// Class: CLockDfMutex +// +// Purpose: Simple class to guarantee that a DfMutex is unlocked +// +// History: 29-Apr-95 DonnaLi Created +// +//-------------------------------------------------------------------------- +class CLockDfMutex +{ +public: + + CLockDfMutex(CDfMutex& dmtx); + + ~CLockDfMutex(void); + +private: + + CDfMutex& _dmtx; +}; + + + +//+------------------------------------------------------------------------- +// +// Member: CLockDfMutex::CLockDfMutex +// +// Synopsis: Get mutex +// +// Arguments: [dmtx] -- mutex to get +// +// History: 29-Apr-95 DonnaLi Created +// +//-------------------------------------------------------------------------- +inline CLockDfMutex::CLockDfMutex(CDfMutex& dmtx) : _dmtx(dmtx) +{ + _dmtx.Take(DFM_TIMEOUT); +} + + +//+------------------------------------------------------------------------- +// +// Member: CLockDfMutex::~CLockDfMutex +// +// Synopsis: Release the mutex +// +// History: 29-Apr-95 DonnaLi Created +// +//-------------------------------------------------------------------------- +inline CLockDfMutex::~CLockDfMutex(void) +{ + _dmtx.Release(); +} + +// +// Take advantage of Windows 95 Shared Heap. +// +#if !defined(_CHICAGO_) + +//+--------------------------------------------------------------------------- +// +// Class: CBlockPreHeader +// +// Purpose: Required header fields for a block +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +class CBlockPreHeader +{ +protected: + ULONG _ulSize; //Size of block + BOOL _fFree; //TRUE if block is free +}; + + +//+--------------------------------------------------------------------------- +// +// Class: CBlockHeader +// +// Purpose: Fields required for free blocks but overwritten for +// allocated blocks. +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- +class CBlockHeader: public CBlockPreHeader +{ +public: + inline ULONG GetSize(void) const; + inline BOOL IsFree(void) const; + inline ULONG GetNext(void) const; + + inline void SetSize(ULONG ulSize); + inline void SetFree(void); + inline void ResetFree(void); + inline void SetNext(ULONG ulNext); +private: + ULONG _ulNext; //Pointer to next block +}; + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::GetSize, public +// +// Synopsis: Returns the size of the block +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CBlockHeader::GetSize(void) const +{ + return _ulSize; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::IsFree, public +// +// Synopsis: Returns free state of block +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline BOOL CBlockHeader::IsFree(void) const +{ + return _fFree; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::GetNext, public +// +// Synopsis: Return next offset +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CBlockHeader::GetNext(void) const +{ + return _ulNext; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::SetSize, public +// +// Synopsis: Set size of block +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CBlockHeader::SetSize(ULONG ulSize) +{ + _ulSize = ulSize; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::SetFree, public +// +// Synopsis: Set this block to free +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CBlockHeader::SetFree(void) +{ + _fFree = TRUE; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::ResetFree, public +// +// Synopsis: Set this block to !free +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CBlockHeader::ResetFree(void) +{ + _fFree = FALSE; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CBlockHeader::SetNext, public +// +// Synopsis: Set next offset +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CBlockHeader::SetNext(ULONG ulNext) +{ + _ulNext = ulNext; +} + +const ULONG CBLOCKMIN = ((sizeof(CBlockHeader) & 7) + ? sizeof(CBlockHeader) + + (8 - (sizeof(CBlockHeader) & 7)) + : sizeof(CBlockHeader)); + +//+--------------------------------------------------------------------------- +// +// Class: CHeapHeader +// +// Purpose: Header information for shared memory heap +// +// Interface: +// +// History: 30-Mar-94 PhilipLa Created +// +// Notes: The size of this structure must be a multiple of 8 bytes. +// +//---------------------------------------------------------------------------- + +class CHeapHeader +{ +public: + inline ULONG GetFirstFree(void) const; + inline void SetFirstFree(ULONG ulNew); + + inline BOOL IsCompacted(void) const; + inline void SetCompacted(void); + inline void ResetCompacted(void); + + inline void ResetAllocedBlocks(void); + inline ULONG IncrementAllocedBlocks(void); + inline ULONG DecrementAllocedBlocks(void); + + inline ULONG GetAllocedBlocks(void); + inline DFLUID IncrementLuid(void); + inline void ResetLuid(void); + +#if DBG == 1 + ULONG _ulAllocedBytes; + ULONG _ulFreeBytes; + ULONG _ulFreeBlocks; +#endif + +private: + ULONG _ulFirstFree; + ULONG _ulAllocedBlocks; + BOOL _fIsCompacted; + DFLUID _dfLuid; +#if DBG == 1 + ULONG ulPad; +#endif +}; + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::GetFirstFree, public +// +// Synopsis: Return first free information +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CHeapHeader::GetFirstFree(void) const +{ + return _ulFirstFree; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::SetFirstFree, public +// +// Synopsis: Set first free information +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CHeapHeader::SetFirstFree(ULONG ulNew) +{ + _ulFirstFree = ulNew; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::IsCompacted, public +// +// Synopsis: Return TRUE if heap is compacted +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline BOOL CHeapHeader::IsCompacted(void) const +{ + return _fIsCompacted; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::SetCompacted, public +// +// Synopsis: Set compacted bit +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CHeapHeader::SetCompacted(void) +{ + _fIsCompacted = TRUE; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::ResetCompacted, public +// +// Synopsis: Reset compacted bit +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CHeapHeader::ResetCompacted(void) +{ + _fIsCompacted = FALSE; +} + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::IncrementLuid, public +// +// Synopsis: Increment the global LUID +// +// History: 06-Apr-95 HenryLee Created +// +//---------------------------------------------------------------------------- +inline ULONG CHeapHeader::IncrementLuid() +{ + return ++_dfLuid; +} + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::ResetLuid, public +// +// Synopsis: Increment the global LUID +// +// History: 06-Apr-95 HenryLee Created +// +//---------------------------------------------------------------------------- +inline void CHeapHeader::ResetLuid() +{ + _dfLuid = LUID_BASE; // some LUIDs are reserved +} + +#else // define(_CHICAGO_) + +extern HANDLE gs_hSharedHeap; // hSharedHeap Handle for Win95. +extern DFLUID gs_dfluid; // shared docfile LUID + +#endif // !define(_CHICAGO_) + +//+--------------------------------------------------------------------------- +// +// Class: CSmAllocator +// +// Purpose: Shared memory heap implementation +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// +//---------------------------------------------------------------------------- + +class CSmAllocator: public IMalloc +{ +public: + inline CSmAllocator(); + inline ~CSmAllocator(); + + STDMETHOD_(ULONG,AddRef) ( void ); + STDMETHOD_(ULONG,Release) ( void ); + STDMETHOD(QueryInterface) ( REFIID riid, void ** ppv ); + + STDMETHOD_(void*,Alloc) ( ULONG cb ); + STDMETHOD_(void *,Realloc) ( void *pvCurrent, ULONG cbNeeded ); + STDMETHOD_(void,Free) ( void *pvMemToFree ); + STDMETHOD_(ULONG,GetSize) ( void * pv ); + STDMETHOD_(void,HeapMinimize) ( void ); + STDMETHOD_(int,DidAlloc) ( void * pv ); + + inline SCODE Sync(void); + inline DFLUID IncrementLuid(void); + +#if !defined(MULTIHEAP) + SCODE Init ( LPWSTR pszName ); +#else + SCODE Init ( ULONG ulHeapName, BOOL fUnmarshal ); +#endif + + inline void * GetBase(void); + + // This function is equivalent to Free above, except that is does + // not attempt to first acquire the mutex. It should be used ONLY + // when the calling function guarantees to already have the mutex. + void FreeNoMutex (void * pv); +#if !defined(MULTIHEAP) + inline CDfMutex * GetMutex (void); +#endif +#ifdef MULTIHEAP + void SetState (CSharedMemoryBlock *psmb, BYTE * pbBase, + ULONG ulHeapName, CPerContext ** ppcPrev, + CPerContext *ppcOwner); + void GetState (CSharedMemoryBlock **ppsmb, BYTE ** ppbBase, + ULONG *pulHeapName); + inline const ULONG GetHeapName (); + SCODE Uninit (); + inline const ULONG GetHeapSize () { return _cbSize; }; +#endif + +private: + inline void DoFree (void *pv); +#if !defined(MULTIHEAP) + CDfMutex _dmtx; +#endif +// +// Take advantage of Windows 95 Shared Heap. +// +#if !defined(_CHICAGO_) + + CBlockHeader * FindBlock(ULONG cb, CBlockHeader **ppbhPrev); + + inline CHeapHeader *GetHeader(void); + + inline CBlockHeader * GetAddress(ULONG ulOffset) const; + inline ULONG GetOffset(CBlockHeader *pbh) const; + + inline SCODE Reset(void); +#if DBG == 1 + void PrintFreeBlocks(void); +#ifdef MULTIHEAP + void PrintAllocatedBlocks(void); +#endif +#endif + +#ifdef MULTIHEAP + CSharedMemoryBlock *_psmb; + BYTE *_pbBase; + ULONG _cbSize; + CPerContext * _ppcOwner; + ULONG _ulHeapName; + ULONG _cRefs; // yes, this object has a lifetime now +#else + CSharedMemoryBlock _smb; + + BYTE *_pbBase; + + ULONG _cbSize; +#endif // MULTIHEAP + +#else // defined(_CHICAGO_) + + HANDLE m_hSharedHeap; + +#endif // !defined(_CHICAGO_) +}; + +#ifdef MULTIHEAP +extern CSmAllocator g_SmAllocator; // single-threaded allocator +extern CSharedMemoryBlock g_smb; //performance optimization +extern ULONG g_ulHeapName; +extern CSmAllocator& GetTlsSmAllocator(); // all other threads +#define g_smAllocator (GetTlsSmAllocator()) + +#else +extern CSmAllocator g_smAllocator; +#endif +extern CRITICAL_SECTION g_csScratchBuffer; + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::CSmAllocator, public +// +// Synopsis: Constructor +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// +//---------------------------------------------------------------------------- + +inline CSmAllocator::CSmAllocator(void) +#if !defined(_CHICAGO_) +#ifdef MULTIHEAP + : _cbSize(0), _pbBase(NULL), _cRefs(1), _ulHeapName(0), + _psmb(NULL), _ppcOwner(NULL) +#else + : _cbSize(0) +#endif // MULTIHEAP +#else + : m_hSharedHeap(NULL) +#endif +{ +#if !defined(MULTIHEAP) + InitializeCriticalSection(&g_csScratchBuffer); +#ifdef COORD + InitializeCriticalSection(&g_csResourceList); +#endif +#endif // MULTIHEAP +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::~CSmAllocator, public +// +// Synopsis: Destructor +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// 10-May-95 KentCe Defer Heap Destruction to the last +// process detach. +// +//---------------------------------------------------------------------------- + +inline CSmAllocator::~CSmAllocator(void) +{ +#if !defined(MULTIHEAP) + DeleteCriticalSection(&g_csScratchBuffer); +#ifdef COORD + DeleteCriticalSection(&g_csResourceList); +#endif +#endif // MULTIHEAP +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::Sync, public +// +// Synopsis: Sync memory to global state. +// +// Arguments: None. +// +// Returns: Appropriate status code +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// +//---------------------------------------------------------------------------- + +inline SCODE CSmAllocator::Sync(void) +{ + SCODE sc = S_OK; +#if !defined(_CHICAGO_) +#if !defined(MULTIHEAP) + if (!_smb.IsSynced()) + { + CLockDfMutex lckdmtx(_dmtx); + + sc = _smb.Sync(); + _cbSize = _smb.GetSize(); + } +#else + if (!_psmb->IsSynced()) + { + sc = _psmb->Sync(); + } + _cbSize = _psmb->GetSize(); +#endif + +#endif + return sc; +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::IncrementLuid, public +// +// Synopsis: Increments the global LUID +// +// Arguments: None. +// +// Returns: Appropriate status code +// +// History: 06-Apr-95 HenryLee Created +//---------------------------------------------------------------------------- + +inline DFLUID CSmAllocator::IncrementLuid(void) +{ +#if !defined(MULTIHEAP) + CLockDfMutex lckdmx(_dmtx); +#endif + +#ifdef _CHICAGO_ + // + // On Chicago, we merely increment the globally available + // LUID to the next value. + // + return ++gs_dfluid; +#else + return GetHeader()->IncrementLuid(); +#endif + +} + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetBase, public +// +// Synopsis: Return pointer to base of heap +// +// History: 29-Mar-94 PhilipLa Created +// 05-Feb-95 KentCe Use Win95 Shared Heap. +// +//---------------------------------------------------------------------------- + +inline void * CSmAllocator::GetBase(void) +{ +#if defined(_CHICAGO_) + return NULL; +#else + return _pbBase; +#endif +} + +#if !defined(MULTIHEAP) +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetMutex, public +// +// Synopsis: Return a pointer to the Mutex +// +// History: 19-Jul-95 SusiA Created +// +//---------------------------------------------------------------------------- + +inline CDfMutex * CSmAllocator::GetMutex(void) +{ + return &_dmtx; +} +#endif + +// +// Take advantage of Windows 95 Shared Heap. +// +#if !defined(_CHICAGO_) + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetAddress, private +// +// Synopsis: Returns an address given an offset from the base +// +// Arguments: [ulOffset] -- Offset to convert to address +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline CBlockHeader * CSmAllocator::GetAddress(ULONG ulOffset) const +{ + return (ulOffset == 0) ? NULL : (CBlockHeader *)(_pbBase + ulOffset); +} + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetOffset +// +// Synopsis: Returns a byte offset from the base given a pointer +// +// Arguments: [pbh] -- Pointer to convert to offset +// +// History: 29-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CSmAllocator::GetOffset(CBlockHeader *pbh) const +{ + memAssert((BYTE *)pbh >= _pbBase && (BYTE*)pbh < _pbBase + _cbSize); + return (ULONG)pbh - (ULONG)_pbBase; +} + + + +//+--------------------------------------------------------------------------- +// +// Member: CSmAllocator::GetHeader, private +// +// Synopsis: Return pointer to CHeapHeader for this heap +// +// History: 30-Mar-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline CHeapHeader * CSmAllocator::GetHeader(void) +{ + return (CHeapHeader *)_pbBase; +} + +#ifdef MULTIHEAP +//+------------------------------------------------------------------------- +// +// Member: CSmAllocator::HeapName, public +// +// Synopsis: Return the luid part of the shared heap name +// +// History: 30-Nov-95 HenryLee Created +// +//-------------------------------------------------------------------------- +inline const ULONG CSmAllocator::GetHeapName() +{ + return _ulHeapName; +} +#endif + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::ResetAllocedBlocks, public +// +// Synopsis: Reset the allocated block counter +// +// History: 04-Apr-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline void CHeapHeader::ResetAllocedBlocks(void) +{ + _ulAllocedBlocks = 0; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::IncrementAllocedBlocks, public +// +// Synopsis: Increment the allocated block count +// +// History: 04-Apr-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CHeapHeader::IncrementAllocedBlocks(void) +{ + return ++_ulAllocedBlocks; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::DecrementAllocedBlocks, public +// +// Synopsis: Decrement the allocated block count +// +// History: 04-Apr-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CHeapHeader::DecrementAllocedBlocks(void) +{ + return --_ulAllocedBlocks; +} + + +//+--------------------------------------------------------------------------- +// +// Member: CHeapHeader::GetAllocedBlocks, public +// +// Synopsis: Return the allocated block count +// +// History: 04-Apr-94 PhilipLa Created +// +//---------------------------------------------------------------------------- + +inline ULONG CHeapHeader::GetAllocedBlocks(void) +{ + return _ulAllocedBlocks; +} + +#endif // !defined(_CHICAGO_) + +#endif // #ifndef __HEAP_HXX__ + diff --git a/private/ole32/dcomss/objex/shrmem/test.acf b/private/ole32/dcomss/objex/shrmem/test.acf new file mode 100644 index 000000000..347a4fe9a --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/test.acf @@ -0,0 +1,3 @@ +[ implicit_handle (handle_t SMTBinding)] interface SharedMemoryTest +{ +} diff --git a/private/ole32/dcomss/objex/shrmem/test.idl b/private/ole32/dcomss/objex/shrmem/test.idl new file mode 100644 index 000000000..b6814be0c --- /dev/null +++ b/private/ole32/dcomss/objex/shrmem/test.idl @@ -0,0 +1,40 @@ +[ + uuid (7e1de6b0-5cbd-11cf-af39-00aa00b50686), + version (1.0), + pointer_default (unique) +] + +interface SharedMemoryTest +{ + +import "obase.idl"; + +/* + * Send the offset of a shared block to another process which returns the contents. + */ + +void RemoteRead + ( + [in] unsigned long offset, + [out] long * value + ); + +void SendList + ( + [in] unsigned long list_offset + ); + +void ReadNext + ( + [out] unsigned long * value + ); + +void GetIds + ( + [out] OXID * pOxid, + [out] OID * pOid + ); + +void ShutDown(); + +} |