summaryrefslogtreecommitdiffstats
path: root/private/ntos/dll/csrinit.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dll/csrinit.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/dll/csrinit.c')
-rw-r--r--private/ntos/dll/csrinit.c604
1 files changed, 604 insertions, 0 deletions
diff --git a/private/ntos/dll/csrinit.c b/private/ntos/dll/csrinit.c
new file mode 100644
index 000000000..cf9054452
--- /dev/null
+++ b/private/ntos/dll/csrinit.c
@@ -0,0 +1,604 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dllinit.c
+
+Abstract:
+
+ This module contains the initialization code for the Client-Server (CS)
+ Client DLL.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Environment:
+
+ User Mode only
+
+Revision History:
+
+--*/
+
+#include "csrdll.h"
+#include "ldrp.h"
+
+BOOLEAN
+CsrDllInitialize(
+ IN PVOID DllHandle,
+ IN ULONG Reason,
+ IN PCONTEXT Context OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function is the DLL initialization routine for the Client DLL
+ This function gets control when the application links to this DLL
+ are snapped.
+
+Arguments:
+
+ Context - Supplies an optional context buffer that will be restore
+ after all DLL initialization has been completed. If this
+ parameter is NULL then this is a dynamic snap of this module.
+ Otherwise this is a static snap prior to the user process
+ gaining control.
+
+Return Value:
+
+ Status value.
+
+--*/
+
+{
+ Context;
+
+ if (Reason != DLL_PROCESS_ATTACH) {
+ return( TRUE );
+ }
+
+ //
+ // Remember our DLL handle in a global variable.
+ //
+
+ CsrDllHandle = DllHandle;
+
+ return( TRUE );
+}
+
+
+NTSTATUS
+CsrOneTimeInitialize( VOID )
+{
+ NTSTATUS Status;
+
+ //
+ // Save away system information in a global variable
+ //
+
+ Status = NtQuerySystemInformation( SystemBasicInformation,
+ &CsrNtSysInfo,
+ sizeof( CsrNtSysInfo ),
+ NULL
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+ //
+ // Use the process heap for memory allocation.
+ //
+
+ CsrHeap = RtlProcessHeap();
+
+ CsrInitOnceDone = TRUE;
+
+ return( STATUS_SUCCESS );
+}
+
+
+NTSTATUS
+CsrClientConnectToServer(
+ IN PWSTR ObjectDirectory,
+ IN ULONG ServerDllIndex,
+ IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL,
+ IN PVOID ConnectionInformation,
+ IN OUT PULONG ConnectionInformationLength OPTIONAL,
+ OUT PBOOLEAN CalledFromServer OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by the client side DLL to connect with its
+ server side DLL.
+
+Arguments:
+
+ ObjectDirectory - Points to a null terminate string that is the same
+ as the value of the ObjectDirectory= argument passed to the CSRSS
+ program.
+
+ ServerDllIndex - Index of the server DLL that is being connected to.
+ It should match one of the ServerDll= arguments passed to the CSRSS
+ program.
+
+ CallbackInformation - An optional pointer to a structure that contains
+ a pointer to the client callback function dispatch table.
+
+ ConnectionInformation - An optional pointer to uninterpreted data.
+ This data is intended for clients to pass package, version and
+ protocol identification information to the server to allow the
+ server to determine if it can satisify the client before
+ accepting the connection. Upon return to the client, the
+ ConnectionInformation data block contains any information passed
+ back from the server DLL by its call to the
+ CsrCompleteConnection call. The output data overwrites the
+ input data.
+
+ ConnectionInformationLength - Pointer to the length of the
+ ConnectionInformation data block. The output value is the
+ length of the data stored in the ConnectionInformation data
+ block by the server's call to the NtCompleteConnectPort
+ service. This parameter is OPTIONAL only if the
+ ConnectionInformation parameter is NULL, otherwise it is
+ required.
+
+ CalledFromServer - On output, TRUE if the dll has been called from
+ a server process.
+
+Return Value:
+
+ Status value.
+
+--*/
+
+{
+ NTSTATUS Status;
+ CSR_API_MSG m;
+ PCSR_CLIENTCONNECT_MSG a = &m.u.ClientConnect;
+ PCSR_CAPTURE_HEADER CaptureBuffer;
+ HANDLE CsrServerModuleHandle;
+ STRING ProcedureName;
+ ANSI_STRING DllName;
+ UNICODE_STRING DllName_U;
+ PIMAGE_NT_HEADERS NtHeaders;
+
+ if (ARGUMENT_PRESENT( ConnectionInformation ) &&
+ (!ARGUMENT_PRESENT( ConnectionInformationLength ) ||
+ *ConnectionInformationLength == 0
+ )
+ ) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ if (!CsrInitOnceDone) {
+ Status = CsrOneTimeInitialize();
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+ }
+
+ if (ARGUMENT_PRESENT( CallbackInformation )) {
+ CsrLoadedClientDll[ ServerDllIndex ] = RtlAllocateHeap( CsrHeap, MAKE_TAG( CSR_TAG ), sizeof(CSR_CALLBACK_INFO) );
+ CsrLoadedClientDll[ ServerDllIndex ]->ApiNumberBase =
+ CallbackInformation->ApiNumberBase;
+ CsrLoadedClientDll[ ServerDllIndex ]->MaxApiNumber =
+ CallbackInformation->MaxApiNumber;
+ CsrLoadedClientDll[ ServerDllIndex ]->CallbackDispatchTable =
+ CallbackInformation->CallbackDispatchTable;
+ }
+
+ //
+ // if we are being called by a server process, skip lpc port initialization
+ // and call to server connect routine and just initialize heap. the
+ // dll initialization routine will do any necessary initialization. this
+ // stuff only needs to be done for the first connect.
+ //
+
+ if ( CsrServerProcess == TRUE ) {
+ *CalledFromServer = CsrServerProcess;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // If the image is an NT Native image, we are running in the
+ // context of the server.
+ //
+
+ NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
+ CsrServerProcess =
+ (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) ? TRUE : FALSE;
+
+ if ( CsrServerProcess ) {
+ extern PVOID NtDllBase;
+ RtlInitAnsiString( &DllName, "csrsrv" );
+ Status = RtlAnsiStringToUnicodeString(&DllName_U, &DllName, TRUE);
+ ASSERT(NT_SUCCESS(Status));
+
+ LdrDisableThreadCalloutsForDll(NtDllBase);
+
+ Status = LdrGetDllHandle(
+ UNICODE_NULL,
+ NULL,
+ &DllName_U,
+ (PVOID *)&CsrServerModuleHandle
+ );
+
+ RtlFreeUnicodeString(&DllName_U);
+
+ CsrServerProcess = TRUE;
+
+ RtlInitString(&ProcedureName,"CsrCallServerFromServer");
+ Status = LdrGetProcedureAddress(
+ CsrServerModuleHandle,
+ &ProcedureName,
+ 0L,
+ (PVOID *)&CsrServerApiRoutine
+ );
+ ASSERT(NT_SUCCESS(Status));
+
+ RtlInitString(&ProcedureName, "CsrLocateThreadInProcess");
+ Status = LdrGetProcedureAddress(
+ CsrServerModuleHandle,
+ &ProcedureName,
+ 0L,
+ (PVOID *)&CsrpLocateThreadInProcess
+ );
+ ASSERT(NT_SUCCESS(Status));
+
+ ASSERT (CsrPortHeap==NULL);
+ CsrPortHeap = RtlProcessHeap();
+
+ CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap,
+ 0,
+ L"CSRPORT!",
+ L"CAPTURE\0"
+ );
+
+ if (ARGUMENT_PRESENT(CalledFromServer)) {
+ *CalledFromServer = CsrServerProcess;
+ }
+ return STATUS_SUCCESS;
+ }
+
+ if ( ARGUMENT_PRESENT(ConnectionInformation) ) {
+ CsrServerProcess = FALSE;
+ if (CsrPortHandle == NULL) {
+ Status = CsrpConnectToServer( ObjectDirectory );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+ }
+
+ a->ServerDllIndex = ServerDllIndex;
+ a->ConnectionInformationLength = *ConnectionInformationLength;
+ if (ARGUMENT_PRESENT( ConnectionInformation )) {
+ CaptureBuffer = CsrAllocateCaptureBuffer( 1,
+ 0,
+ a->ConnectionInformationLength
+ );
+ if (CaptureBuffer == NULL) {
+ return( STATUS_NO_MEMORY );
+ }
+
+ CsrAllocateMessagePointer( CaptureBuffer,
+ a->ConnectionInformationLength,
+ (PVOID *)&a->ConnectionInformation
+ );
+ RtlMoveMemory( a->ConnectionInformation,
+ ConnectionInformation,
+ a->ConnectionInformationLength
+ );
+
+ *ConnectionInformationLength = a->ConnectionInformationLength;
+ }
+ else {
+ CaptureBuffer = NULL;
+ }
+
+ Status = CsrClientCallServer( &m,
+ CaptureBuffer,
+ CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX,
+ CsrpClientConnect
+ ),
+ sizeof( *a )
+ );
+
+ if (CaptureBuffer != NULL) {
+ if (ARGUMENT_PRESENT( ConnectionInformation )) {
+ RtlMoveMemory( ConnectionInformation,
+ a->ConnectionInformation,
+ *ConnectionInformationLength
+ );
+ }
+
+ CsrFreeCaptureBuffer( CaptureBuffer );
+ }
+ }
+ else {
+ Status = STATUS_SUCCESS;
+ }
+
+ if (ARGUMENT_PRESENT(CalledFromServer)) {
+ *CalledFromServer = CsrServerProcess;
+ }
+ return( Status );
+}
+
+BOOLEAN
+xProtectHandle(
+ HANDLE hObject
+ )
+{
+ NTSTATUS Status;
+ OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
+
+ Status = NtQueryObject( hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof( HandleInfo ),
+ NULL
+ );
+ if (NT_SUCCESS( Status )) {
+ HandleInfo.ProtectFromClose = TRUE;
+
+ Status = NtSetInformationObject( hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof( HandleInfo )
+ );
+ if (NT_SUCCESS( Status )) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+NTSTATUS
+CsrpConnectToServer(
+ IN PWSTR ObjectDirectory
+ )
+{
+ NTSTATUS Status;
+ REMOTE_PORT_VIEW ServerView;
+ ULONG MaxMessageLength;
+ ULONG ConnectionInformationLength;
+ CSR_API_CONNECTINFO ConnectionInformation;
+ SECURITY_QUALITY_OF_SERVICE DynamicQos;
+ HANDLE PortSection;
+ PORT_VIEW ClientView;
+ ULONG n;
+ LARGE_INTEGER SectionSize;
+
+ //
+ // Create the port name string by combining the passed in object directory
+ // name with the port name.
+ //
+
+ n = ((wcslen( ObjectDirectory ) + 1) * sizeof( WCHAR )) +
+ sizeof( CSR_API_PORT_NAME );
+ CsrPortName.Length = 0;
+ CsrPortName.MaximumLength = (USHORT)n;
+ CsrPortName.Buffer = RtlAllocateHeap( CsrHeap, MAKE_TAG( CSR_TAG ), n );
+ if (CsrPortName.Buffer == NULL) {
+ return( STATUS_NO_MEMORY );
+ }
+ RtlAppendUnicodeToString( &CsrPortName, ObjectDirectory );
+ RtlAppendUnicodeToString( &CsrPortName, L"\\" );
+ RtlAppendUnicodeToString( &CsrPortName, CSR_API_PORT_NAME );
+
+ //
+ // Set up the security quality of service parameters to use over the
+ // port. Use the most efficient (least overhead) - which is dynamic
+ // rather than static tracking.
+ //
+
+ DynamicQos.ImpersonationLevel = SecurityImpersonation;
+ DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+ DynamicQos.EffectiveOnly = TRUE;
+
+
+ //
+ // Create a section to contain the Port Memory. Port Memory is private
+ // memory that is shared between the client and server processes.
+ // This allows data that is too large to fit into an API request message
+ // to be passed to the server.
+ //
+
+ SectionSize.LowPart = CSR_PORT_MEMORY_SIZE;
+ SectionSize.HighPart = 0;
+
+ Status = NtCreateSection( &PortSection,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &SectionSize,
+ PAGE_READWRITE,
+ SEC_RESERVE,
+ NULL
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+ //
+ // Connect to the server. This includes a description of the Port Memory
+ // section so that the LPC connection logic can make the section visible
+ // to both the client and server processes. Also pass information the
+ // server needs in the connection information structure.
+ //
+
+ ClientView.Length = sizeof( ClientView );
+ ClientView.SectionHandle = PortSection;
+ ClientView.SectionOffset = 0;
+ ClientView.ViewSize = SectionSize.LowPart;
+ ClientView.ViewBase = 0;
+ ClientView.ViewRemoteBase = 0;
+
+ ServerView.Length = sizeof( ServerView );
+ ServerView.ViewSize = 0;
+ ServerView.ViewBase = 0;
+
+ ConnectionInformationLength = sizeof( ConnectionInformation );
+ ConnectionInformation.ExpectedVersion = CSR_VERSION;
+
+ Status = NtConnectPort( &CsrPortHandle,
+ &CsrPortName,
+ &DynamicQos,
+ &ClientView,
+ &ServerView,
+ (PULONG)&MaxMessageLength,
+ (PVOID)&ConnectionInformation,
+ (PULONG)&ConnectionInformationLength
+ );
+ NtClose( PortSection );
+ if (!NT_SUCCESS( Status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRDLL: Unable to connect to %wZ Server - Status == %X\n",
+ &CsrPortName,
+ Status
+ );
+ }
+
+ return( Status );
+ }
+ xProtectHandle(CsrPortHandle);
+
+ NtCurrentPeb()->ReadOnlySharedMemoryBase = ConnectionInformation.SharedSectionBase;
+ NtCurrentPeb()->ReadOnlySharedMemoryHeap = ConnectionInformation.SharedSectionHeap;
+ NtCurrentPeb()->ReadOnlyStaticServerData = (PVOID *)ConnectionInformation.SharedStaticServerData;
+
+#if DBG
+ CsrDebug = ConnectionInformation.DebugFlags;
+#endif
+ CsrObjectDirectory = ConnectionInformation.ObjectDirectory;
+
+ CsrPortMemoryRemoteDelta = (ULONG)ClientView.ViewRemoteBase -
+ (ULONG)ClientView.ViewBase;
+
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRDLL: ClientView: Base=%lX RemoteBase=%lX Delta: %lX Size=%lX\n",
+ (ULONG)ClientView.ViewBase,
+ (ULONG)ClientView.ViewRemoteBase,
+ CsrPortMemoryRemoteDelta,
+ (ULONG)ClientView.ViewSize
+ );
+ }
+
+ //
+ // Create a sparse heap in the share memory section. Initially
+ // commit just one page.
+ //
+
+ CsrPortHeap = RtlCreateHeap( HEAP_CLASS_8, // Flags
+ ClientView.ViewBase, // HeapBase
+ ClientView.ViewSize, // ReserveSize
+ CsrNtSysInfo.PageSize, // CommitSize
+ 0, // Reserved
+ 0 // GrowthThreshold
+ );
+ if (CsrPortHeap == NULL) {
+ NtClose( CsrPortHandle );
+ CsrPortHandle = NULL;
+
+ return( STATUS_NO_MEMORY );
+ }
+
+ CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap,
+ 0,
+ L"CSRPORT!",
+ L"!CSRPORT\0"
+ L"CAPTURE\0"
+ );
+
+ return( STATUS_SUCCESS );
+}
+
+
+ULONG
+CsrNullApiCall(
+ IN LONG CountArguments,
+ IN PCHAR *Arguments OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function is present to test the overhead associated with
+ communicating with the OS/2 Subsystem.
+
+Arguments:
+
+ CountArguments - Number of string arguments to pass to the server
+ via Port Memory.
+
+ Arguments - Optional pointer to an array of ASCIZ string pointers.
+
+
+Return Value:
+
+ Random 32-bit number
+
+--*/
+
+{
+ CSR_API_MSG m;
+ PCSR_NULLAPICALL_MSG a = &m.u.NullApiCall;
+ PCSR_CAPTURE_HEADER CaptureBuffer;
+ ULONG Size;
+ LONG i;
+
+ a->CountArguments = CountArguments;
+ if (CountArguments > 0) {
+ Size = CountArguments * sizeof( PCHAR );
+ for (i=0; i<CountArguments; i++) {
+ Size += (strlen( Arguments[ i ] ) + 1) & ~3;
+ }
+ CaptureBuffer = CsrAllocateCaptureBuffer( 1,
+ CountArguments,
+ Size
+ );
+ CsrAllocateMessagePointer( CaptureBuffer,
+ CountArguments * sizeof( PCHAR ),
+ (PVOID *)&a->Arguments
+ );
+ for (i=0; i<CountArguments; i++) {
+ Size = strlen( Arguments[ i ] ) + 1;
+ CsrAllocateCapturePointer( CaptureBuffer,
+ Size,
+ (PVOID *)&a->Arguments[ i ]
+ );
+ RtlMoveMemory( a->Arguments[ i ], Arguments[ i ], Size );
+ }
+ }
+ else {
+ CaptureBuffer = NULL;
+ CountArguments = -CountArguments;
+ ASSERT(sizeof(ULONG) == sizeof(PVOID));
+ for (i=0; i<CountArguments; i++) {
+ a->FastArguments[ i ] = (ULONG)Arguments[ i ];
+ }
+ }
+
+ CsrClientCallServer( &m,
+ CaptureBuffer,
+ CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX,
+ CsrpNullApiCall
+ ),
+ sizeof( *a )
+ );
+
+ if (CaptureBuffer != NULL) {
+ CsrFreeCaptureBuffer( CaptureBuffer );
+ }
+
+ return( (NTSTATUS) m.ReturnValue );
+}