summaryrefslogtreecommitdiffstats
path: root/private/ole32/dcomss/objex/shrmem
diff options
context:
space:
mode:
Diffstat (limited to 'private/ole32/dcomss/objex/shrmem')
-rw-r--r--private/ole32/dcomss/objex/shrmem/client/clt.cxx227
-rw-r--r--private/ole32/dcomss/objex/shrmem/client/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/client/sources109
-rw-r--r--private/ole32/dcomss/objex/shrmem/daytona.inc39
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/base.hxx240
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx113
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx35
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def37
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources99
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx54
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx110
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx4
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dirs28
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx126
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx312
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/epts.c461
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx269
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx297
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx378
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx90
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx346
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx173
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx389
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx766
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx398
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx331
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx189
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx120
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx104
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx239
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx402
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx521
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx437
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/process.cxx453
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/process.hxx283
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx82
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx202
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx38
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/set.hxx104
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/string.cxx685
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/string.hxx159
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/time.hxx113
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcomss.h81
-rw-r--r--private/ole32/dcomss/objex/shrmem/dirs32
-rw-r--r--private/ole32/dcomss/objex/shrmem/intor.hxx26
-rw-r--r--private/ole32/dcomss/objex/shrmem/makefil043
-rw-r--r--private/ole32/dcomss/objex/shrmem/or.h139
-rw-r--r--private/ole32/dcomss/objex/shrmem/or.hxx160
-rw-r--r--private/ole32/dcomss/objex/shrmem/server/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/server/serv.cxx303
-rw-r--r--private/ole32/dcomss/objex/shrmem/server/sources109
-rw-r--r--private/ole32/dcomss/objex/shrmem/smemor.hxx127
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/daytona/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/daytona/sources64
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx744
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/dirs27
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx433
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/simplell.cxx128
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/simplell.hxx180
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx1185
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx850
-rw-r--r--private/ole32/dcomss/objex/shrmem/test.acf3
-rw-r--r--private/ole32/dcomss/objex/shrmem/test.idl40
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();
+
+}