reactos/subsystems/win32/csrsrv/server.c
Hermès Bélusca-Maïto b75ee7fd14 [CSRSRV]
- Zero-out some allocated memory.
- During my investigations preceding the implementation of AttachConsole (r58166), I wanted (in a first attempt; finally I've found a better way to achieve what I wanted to do) to retrieve the CSR_PROCESS structure of the parent of a given process. I've found the 'Parent' member in the CSR_PROCESS structure, however this member was always initialized to NULL when new processes were created via CsrCreateProcess (and via the call to CsrInsertProcess). After looking at some informating here (http://svn.reactos.org/svn/reactos/trunk/reactos/include/subsys/csr/server.h?r1=17363&r2=17362&pathrev=17363) and there (http://forum.sysinternals.com/csrwalker-processes-detection-from-user-mode_topic15457.html), I became convinced that the 'Parent' member was unexistent starting from Windows Server 2003. Also, after much more investigation, I've found that the CsrInsertProcess function was called with only two parameters starting from Windows Server 2003 (and still continues in Windows 7), the always-NULL paramater being removed.
Therefore, I remove that unneeded parameter from CsrInsertProcess and the corresponding 'Parent' member from CSR_PROCESS.

svn path=/branches/ros-csrss/; revision=58232
2013-01-26 21:23:10 +00:00

673 lines
19 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Client/Server Runtime SubSystem
* FILE: subsystems/win32/csrsrv/server.c
* PURPOSE: CSR Server DLL Server Functions
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES *******************************************************************/
#include "srv.h"
#define NDEBUG
#include <debug.h>
/* DATA ***********************************************************************/
PCSR_API_ROUTINE CsrServerApiDispatchTable[CsrpMaxApiNumber] =
{
CsrSrvClientConnect,
CsrSrvUnusedFunction,
CsrSrvUnusedFunction,
CsrSrvIdentifyAlertableThread,
CsrSrvSetPriorityClass
};
BOOLEAN CsrServerApiServerValidTable[CsrpMaxApiNumber] =
{
TRUE,
FALSE,
TRUE,
TRUE,
TRUE
};
PCHAR CsrServerApiNameTable[CsrpMaxApiNumber] =
{
"ClientConnect",
"ThreadConnect",
"ProfileControl",
"IdentifyAlertableThread",
"SetPriorityClass"
};
PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
PVOID CsrSrvSharedSectionHeap = NULL;
PVOID CsrSrvSharedSectionBase = NULL;
PVOID *CsrSrvSharedStaticServerData = NULL;
ULONG CsrSrvSharedSectionSize = 0;
HANDLE CsrSrvSharedSection = NULL;
/* PRIVATE FUNCTIONS **********************************************************/
/*++
* @name CsrServerDllInitialization
* @implemented NT4
*
* The CsrServerDllInitialization is the initialization routine for
* the this Server DLL.
*
* @param LoadedServerDll
* Pointer to the CSR Server DLL structure representing this Server DLL.
*
* @return STATUS_SUCCESS.
*
* @remarks None.
*
*--*/
CSR_SERVER_DLL_INIT(CsrServerDllInitialization)
{
/* Setup the DLL Object */
LoadedServerDll->ApiBase = 0;
LoadedServerDll->HighestApiSupported = CsrpMaxApiNumber;
LoadedServerDll->DispatchTable = CsrServerApiDispatchTable;
LoadedServerDll->ValidTable = CsrServerApiServerValidTable;
LoadedServerDll->NameTable = CsrServerApiNameTable;
LoadedServerDll->SizeOfProcessData = 0;
LoadedServerDll->ConnectCallback = NULL;
LoadedServerDll->DisconnectCallback = NULL;
/* All done */
return STATUS_SUCCESS;
}
/*++
* @name CsrLoadServerDll
* @implemented NT4
*
* The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
*
* @param DllString
* Pointer to the CSR Server DLL to load and call.
*
* @param EntryPoint
* Pointer to the name of the server's initialization function. If
* this parameter is NULL, the default ServerDllInitialize will be
* assumed.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* otherwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrLoadServerDll(IN PCHAR DllString,
IN PCHAR EntryPoint OPTIONAL,
IN ULONG ServerId)
{
NTSTATUS Status;
ANSI_STRING DllName;
UNICODE_STRING TempString, ErrorString;
ULONG_PTR Parameters[2];
HANDLE hServerDll = NULL;
ULONG Size;
PCSR_SERVER_DLL ServerDll;
STRING EntryPointString;
PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure;
ULONG Response;
DPRINT1("CsrLoadServerDll(%s, 0x%p, %lu)\n", DllString, EntryPoint, ServerId);
/* Check if it's beyond the maximum we support */
if (ServerId >= CSR_SERVER_DLL_MAX) return STATUS_TOO_MANY_NAMES;
/* Check if it's already been loaded */
if (CsrLoadedServerDll[ServerId]) return STATUS_INVALID_PARAMETER;
/* Convert the name to Unicode */
ASSERT(DllString != NULL);
RtlInitAnsiString(&DllName, DllString);
Status = RtlAnsiStringToUnicodeString(&TempString, &DllName, TRUE);
if (!NT_SUCCESS(Status)) return Status;
/* If we are loading ourselves, don't actually load us */
if (ServerId != CSRSRV_SERVERDLL_INDEX)
{
/* Load the DLL */
Status = LdrLoadDll(NULL, 0, &TempString, &hServerDll);
if (!NT_SUCCESS(Status))
{
/* Setup error parameters */
Parameters[0] = (ULONG_PTR)&TempString;
Parameters[1] = (ULONG_PTR)&ErrorString;
RtlInitUnicodeString(&ErrorString, L"Default Load Path");
/* Send a hard error */
NtRaiseHardError(Status,
2,
3,
Parameters,
OptionOk,
&Response);
}
/* Get rid of the string */
RtlFreeUnicodeString(&TempString);
if (!NT_SUCCESS(Status)) return Status;
}
/* Allocate a CSR DLL Object */
Size = sizeof(CSR_SERVER_DLL) + DllName.MaximumLength;
ServerDll = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Size);
if (!ServerDll)
{
if (hServerDll) LdrUnloadDll(hServerDll);
return STATUS_NO_MEMORY;
}
/* Set up the Object */
ServerDll->Length = Size;
ServerDll->SharedSection = CsrSrvSharedSectionHeap; // Send to the server dll our shared heap pointer.
ServerDll->Event = CsrInitializationEvent;
ServerDll->Name.Length = DllName.Length;
ServerDll->Name.MaximumLength = DllName.MaximumLength;
ServerDll->Name.Buffer = (PCHAR)(ServerDll + 1);
if (DllName.Length)
{
strncpy(ServerDll->Name.Buffer, DllName.Buffer, DllName.Length);
}
ServerDll->ServerId = ServerId;
ServerDll->ServerHandle = hServerDll;
/* Now get the entrypoint */
if (hServerDll)
{
/* Initialize a string for the entrypoint, or use the default */
RtlInitAnsiString(&EntryPointString,
EntryPoint ? EntryPoint : "ServerDllInitialization");
/* Get a pointer to it */
Status = LdrGetProcedureAddress(hServerDll,
&EntryPointString,
0,
(PVOID)&ServerDllInitProcedure);
}
else
{
/* No handle, so we are loading ourselves */
ServerDllInitProcedure = CsrServerDllInitialization;
Status = STATUS_SUCCESS;
}
/* Check if we got the pointer, and call it */
if (NT_SUCCESS(Status))
{
/* Get the result from the Server DLL */
Status = ServerDllInitProcedure(ServerDll);
if (NT_SUCCESS(Status))
{
/*
* Add this Server's Per-Process Data Size to the total that each
* process will need.
*/
CsrTotalPerProcessDataLength += ServerDll->SizeOfProcessData;
/* Save the pointer in our list */
CsrLoadedServerDll[ServerDll->ServerId] = ServerDll;
/* Does it use our generic heap? */
if (ServerDll->SharedSection != CsrSrvSharedSectionHeap)
{
/* No, save the pointer to its shared section in our list */
CsrSrvSharedStaticServerData[ServerDll->ServerId] = ServerDll->SharedSection;
}
}
else
{
/* Use shared failure code */
goto LoadFailed;
}
}
else
{
LoadFailed:
/* Server Init failed, unload it */
if (hServerDll) LdrUnloadDll(hServerDll);
/* Delete the Object */
RtlFreeHeap(CsrHeap, 0, ServerDll);
}
/* Return to caller */
return Status;
}
/*++
* @name CsrSrvClientConnect
*
* The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
*
* @param ApiMessage
* Pointer to the CSR API Message for this request.
*
* @param ReplyCode
* Optional reply to this request.
*
* @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
* or STATUS_TOO_MANY_NAMES in case of failure.
*
* @remarks None.
*
*--*/
CSR_API(CsrSrvClientConnect)
{
NTSTATUS Status;
PCSR_CLIENT_CONNECT ClientConnect = &ApiMessage->Data.CsrClientConnect;
PCSR_SERVER_DLL ServerDll;
PCSR_PROCESS CurrentProcess = CsrGetClientThread()->Process;
/* Set default reply */
*ReplyCode = CsrReplyImmediately;
/* Validate the ServerID */
if (ClientConnect->ServerId >= CSR_SERVER_DLL_MAX)
{
return STATUS_TOO_MANY_NAMES;
}
else if (!CsrLoadedServerDll[ClientConnect->ServerId])
{
return STATUS_INVALID_PARAMETER;
}
/* Validate the Message Buffer */
if (!(CsrValidateMessageBuffer(ApiMessage,
&ClientConnect->ConnectionInfo,
ClientConnect->ConnectionInfoSize,
sizeof(BYTE))))
{
/* Fail due to buffer overflow or other invalid buffer */
return STATUS_INVALID_PARAMETER;
}
/* Load the Server DLL */
ServerDll = CsrLoadedServerDll[ClientConnect->ServerId];
/* Check if it has a Connect Callback */
if (ServerDll->ConnectCallback)
{
/* Call the callback */
Status = ServerDll->ConnectCallback(CurrentProcess,
ClientConnect->ConnectionInfo,
&ClientConnect->ConnectionInfoSize);
}
else
{
/* Assume success */
Status = STATUS_SUCCESS;
}
/* Return status */
return Status;
}
/*++
* @name CsrSrvCreateSharedSection
*
* The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server
* DLLs and Clients can use to share data.
*
* @param ParameterValue
* Specially formatted string from our registry command-line which
* specifies various arguments for the shared section.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* otherwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrSrvCreateSharedSection(IN PCHAR ParameterValue)
{
PCHAR SizeValue = ParameterValue;
ULONG Size;
NTSTATUS Status;
LARGE_INTEGER SectionSize;
ULONG ViewSize = 0;
PPEB Peb = NtCurrentPeb();
/* If there's no parameter, fail */
if (!ParameterValue) return STATUS_INVALID_PARAMETER;
/* Find the first comma, and null terminate */
while (*SizeValue)
{
if (*SizeValue == ',')
{
*SizeValue++ = ANSI_NULL;
break;
}
else
{
SizeValue++;
}
}
/* Make sure it's valid */
if (!*SizeValue) return STATUS_INVALID_PARAMETER;
/* Convert it to an integer */
Status = RtlCharToInteger(SizeValue, 0, &Size);
if (!NT_SUCCESS(Status)) return Status;
/* Multiply by 1024 entries and round to page size */
CsrSrvSharedSectionSize = ROUND_UP(Size * 1024, CsrNtSysInfo.PageSize);
/* Create the Secion */
SectionSize.LowPart = CsrSrvSharedSectionSize;
SectionSize.HighPart = 0;
Status = NtCreateSection(&CsrSrvSharedSection,
SECTION_ALL_ACCESS,
NULL,
&SectionSize,
PAGE_EXECUTE_READWRITE,
SEC_BASED | SEC_RESERVE,
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Map the section */
Status = NtMapViewOfSection(CsrSrvSharedSection,
NtCurrentProcess(),
&CsrSrvSharedSectionBase,
0,
0,
NULL,
&ViewSize,
ViewUnmap,
MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(CsrSrvSharedSection);
return Status;
}
/* FIXME: Write the value to registry */
/* The Heap is the same place as the Base */
CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase;
/* Create the heap */
if (!(RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_CLASS_7,
CsrSrvSharedSectionHeap,
CsrSrvSharedSectionSize,
PAGE_SIZE,
0,
0)))
{
/* Failure, unmap section and return */
NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase);
NtClose(CsrSrvSharedSection);
return STATUS_NO_MEMORY;
}
/* Now allocate space from the heap for the Shared Data */
CsrSrvSharedStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
HEAP_ZERO_MEMORY,
CSR_SERVER_DLL_MAX * sizeof(PVOID));
if (!CsrSrvSharedStaticServerData) return STATUS_NO_MEMORY;
/* Write the values to the PEB */
Peb->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
Peb->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
Peb->ReadOnlyStaticServerData = CsrSrvSharedStaticServerData;
/* Return */
return STATUS_SUCCESS;
}
/*++
* @name CsrSrvAttachSharedSection
*
* The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
* CSR Process' address space, and returns the pointers to the section
* through the Connection Info structure.
*
* @param CsrProcess
* Pointer to the CSR Process that is attempting a connection.
*
* @param ConnectInfo
* Pointer to the CSR Connection Info structure for the incoming
* connection.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* otherwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,
OUT PCSR_CONNECTION_INFO ConnectInfo)
{
NTSTATUS Status;
ULONG ViewSize = 0;
/* Check if we have a process */
if (CsrProcess)
{
/* Map the section into this process */
DPRINT("CSR Process Handle: %p. CSR Process: %p\n", CsrProcess->ProcessHandle, CsrProcess);
Status = NtMapViewOfSection(CsrSrvSharedSection,
CsrProcess->ProcessHandle,
&CsrSrvSharedSectionBase,
0,
0,
NULL,
&ViewSize,
ViewUnmap,
SEC_NO_CHANGE,
PAGE_EXECUTE_READ);
if (!NT_SUCCESS(Status)) return Status;
}
/* Write the values in the Connection Info structure */
ConnectInfo->SharedSectionBase = CsrSrvSharedSectionBase;
ConnectInfo->SharedSectionHeap = CsrSrvSharedSectionHeap;
ConnectInfo->SharedSectionData = CsrSrvSharedStaticServerData;
/* Return success */
return STATUS_SUCCESS;
}
/*++
* @name CsrSrvIdentifyAlertableThread
* @implemented NT4
*
* The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
*
* @param ApiMessage
* Pointer to the CSR API Message for this request.
*
* @param ReplyCode
* Pointer to an optional reply to this request.
*
* @return STATUS_SUCCESS.
*
* @remarks None.
*
*--*/
CSR_API(CsrSrvIdentifyAlertableThread)
{
PCSR_THREAD CsrThread = CsrGetClientThread();
/* Set the alertable flag */
CsrThread->Flags |= CsrThreadAlertable;
/* Return success */
return STATUS_SUCCESS;
}
/*++
* @name CsrSrvSetPriorityClass
* @implemented NT4
*
* The CsrSrvSetPriorityClass CSR API is deprecated.
*
* @param ApiMessage
* Pointer to the CSR API Message for this request.
*
* @param ReplyCode
* Pointer to an optional reply to this request.
*
* @return STATUS_SUCCESS.
*
* @remarks None.
*
*--*/
CSR_API(CsrSrvSetPriorityClass)
{
/* Deprecated */
return STATUS_SUCCESS;
}
/*++
* @name CsrSrvUnusedFunction
* @implemented NT4
*
* The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
*
* The CsrSrvSetPriorityClass CSR API is deprecated.
*
* @param ApiMessage
* Pointer to the CSR API Message for this request.
*
* @param ReplyCode
* Pointer to an optional reply to this request.
*
* @return STATUS_INVALID_PARAMETER.
*
* @remarks CsrSrvSetPriorityClass does not use this stub because it must
* return success.
*
*--*/
CSR_API(CsrSrvUnusedFunction)
{
/* Deprecated */
return STATUS_INVALID_PARAMETER;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*++
* @name CsrSetCallingSpooler
* @implemented NT4
*
* the CsrSetCallingSpooler routine is deprecated.
*
* @param Reserved
* Deprecated
*
* @return None.
*
* @remarks This routine was used in archaic versions of NT for Printer Drivers.
*
*--*/
VOID
NTAPI
CsrSetCallingSpooler(ULONG Reserved)
{
/* Deprecated */
return;
}
/*++
* @name CsrUnhandledExceptionFilter
* @implemented NT5
*
* The CsrUnhandledExceptionFilter routine handles all exceptions
* within SEH-protected blocks.
*
* @param ExceptionPointers
* System-defined Argument.
*
* @return EXCEPTION_EXECUTE_HANDLER.
*
* @remarks None.
*
*--*/
EXCEPTION_DISPOSITION
NTAPI
CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
{
SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo;
EXCEPTION_DISPOSITION Result = EXCEPTION_EXECUTE_HANDLER;
BOOLEAN OldValue;
NTSTATUS Status;
UNICODE_STRING ErrorSource;
ULONG_PTR ErrorParameters[4];
ULONG Response;
/* Check if a debugger is installed */
Status = NtQuerySystemInformation(SystemKernelDebuggerInformation,
&DebuggerInfo,
sizeof(DebuggerInfo),
NULL);
/* Check if this is Session 0, and the Debugger is Enabled */
if ((NtCurrentPeb()->SessionId) && (NT_SUCCESS(Status)) &&
(DebuggerInfo.KernelDebuggerEnabled))
{
/* Call the Unhandled Exception Filter */
if ((Result = RtlUnhandledExceptionFilter(ExceptionInfo)) !=
EXCEPTION_CONTINUE_EXECUTION)
{
/* We're going to raise an error. Get Shutdown Privilege first */
Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
TRUE,
TRUE,
&OldValue);
/* Use the Process token if that failed */
if (Status == STATUS_NO_TOKEN)
{
Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
TRUE,
FALSE,
&OldValue);
}
/* Initialize our Name String */
RtlInitUnicodeString(&ErrorSource, L"Windows SubSystem");
/* Set the parameters */
ErrorParameters[0] = (ULONG_PTR)&ErrorSource;
ErrorParameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
ErrorParameters[2] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
ErrorParameters[3] = (ULONG_PTR)ExceptionInfo->ContextRecord;
/* Bugcheck */
Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
4,
1,
ErrorParameters,
OptionShutdownSystem,
&Response);
}
/* Just terminate us */
NtTerminateProcess(NtCurrentProcess(),
ExceptionInfo->ExceptionRecord->ExceptionCode);
}
return Result;
}
/* EOF */