mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 12:23:30 +00:00
[REACTOS]
Here is all the deprecated code: the old CSR as well as the new one which wasn't included; the ReactOS-specific win32csr and the csr module of win32k. svn path=/trunk/; revision=58771
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Interface to csrss
|
||||
* FILE: subsys/win32k/ntuser/csr.c
|
||||
* PROGRAMER: Ge van Geldorp ([email protected])
|
||||
*/
|
||||
|
||||
#include <win32k.h>
|
||||
|
||||
static HANDLE WindowsApiPort = NULL;
|
||||
PEPROCESS CsrProcess = NULL;
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
CsrInit(void)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING PortName;
|
||||
ULONG ConnectInfoLength;
|
||||
SECURITY_QUALITY_OF_SERVICE Qos;
|
||||
|
||||
RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort");
|
||||
ConnectInfoLength = 0;
|
||||
Qos.Length = sizeof(Qos);
|
||||
Qos.ImpersonationLevel = SecurityDelegation;
|
||||
Qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
|
||||
Qos.EffectiveOnly = FALSE;
|
||||
|
||||
Status = ZwConnectPort(&WindowsApiPort,
|
||||
&PortName,
|
||||
&Qos,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&ConnectInfoLength);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
CsrProcess = PsGetCurrentProcess();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
co_CsrNotify(PCSR_API_MESSAGE Request)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PEPROCESS OldProcess;
|
||||
|
||||
if (NULL == CsrProcess)
|
||||
{
|
||||
return STATUS_INVALID_PORT_HANDLE;
|
||||
}
|
||||
|
||||
Request->Header.u2.ZeroInit = 0;
|
||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
|
||||
/* Switch to the process in which the WindowsApiPort handle is valid */
|
||||
OldProcess = PsGetCurrentProcess();
|
||||
if (CsrProcess != OldProcess)
|
||||
{
|
||||
KeAttachProcess(&CsrProcess->Pcb);
|
||||
}
|
||||
|
||||
UserLeaveCo();
|
||||
|
||||
Status = ZwRequestWaitReplyPort(WindowsApiPort,
|
||||
&Request->Header,
|
||||
&Request->Header);
|
||||
|
||||
UserEnterCo();
|
||||
|
||||
if (CsrProcess != OldProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = Request->Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Interface to csrss
|
||||
* FILE: subsys/win32k/include/csr.h
|
||||
* PROGRAMER: Ge van Geldorp ([email protected])
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern PEPROCESS CsrProcess;
|
||||
|
||||
NTSTATUS FASTCALL CsrInit(void);
|
||||
NTSTATUS FASTCALL co_CsrNotify(PCSR_API_MESSAGE Request);
|
||||
NTSTATUS FASTCALL CsrCloseHandle(HANDLE Handle);
|
||||
NTSTATUS WINAPI CsrInsertObject(HANDLE ObjectHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
PHANDLE Handle);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
include_directories(
|
||||
include
|
||||
${REACTOS_SOURCE_DIR}/include/reactos/subsys
|
||||
${REACTOS_SOURCE_DIR}/include/reactos/drivers)
|
||||
|
||||
add_executable(csrss2 main.c csr.rc)
|
||||
|
||||
set_module_type(csrss2 nativecui)
|
||||
target_link_libraries(csrss2 nt)
|
||||
add_importlibs(csrss2 ntdll csrsrv2)
|
||||
add_dependencies(csrss2 psdk bugcodes)
|
||||
add_cd_file(TARGET csrss2 DESTINATION reactos/system32 FOR all)
|
||||
|
||||
add_subdirectory(csrsrv)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Client/Server Runtime Process\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "csrss\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "csrss.exe\0"
|
||||
#include <reactos/version.rc>
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/subsystems/win32/csrss/include)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
|
||||
|
||||
spec2def(csrsrv2.dll csrsrv2.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
api.c
|
||||
init.c
|
||||
process.c
|
||||
server.c
|
||||
session.c
|
||||
thread.c
|
||||
wait.c
|
||||
csrsrv.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/csrsrv2.def)
|
||||
|
||||
add_library(csrsrv2 SHARED ${SOURCE})
|
||||
|
||||
target_link_libraries(csrsrv2 ${PSEH_LIB} smlib)
|
||||
|
||||
set_module_type(csrsrv2 nativedll)
|
||||
|
||||
add_importlibs(csrsrv2 ntdll)
|
||||
|
||||
add_pch(csrsrv2 srv.h)
|
||||
|
||||
add_dependencies(csrsrv2 psdk bugcodes)
|
||||
add_cd_file(TARGET csrsrv2 DESTINATION reactos/system32 FOR all)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS CSR Core Server\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "csrsrv\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "csrsrv.dll\0"
|
||||
#include <reactos/version.rc>
|
||||
@@ -0,0 +1,35 @@
|
||||
@ stdcall CsrAddStaticServerThread(ptr ptr long)
|
||||
@ stdcall CsrCallServerFromServer(ptr ptr)
|
||||
@ stdcall CsrConnectToUser()
|
||||
@ stdcall CsrCreateProcess(ptr ptr ptr ptr long ptr)
|
||||
@ stdcall CsrCreateRemoteThread(ptr ptr)
|
||||
@ stdcall CsrCreateThread(ptr ptr ptr long)
|
||||
@ stdcall CsrCreateWait(ptr ptr ptr ptr ptr ptr)
|
||||
@ stdcall CsrDebugProcess(ptr)
|
||||
@ stdcall CsrDebugProcessStop(ptr)
|
||||
@ stdcall CsrDereferenceProcess(ptr)
|
||||
@ stdcall CsrDereferenceThread(ptr)
|
||||
@ stdcall CsrDereferenceWait(ptr)
|
||||
@ stdcall CsrDestroyProcess(ptr long)
|
||||
@ stdcall CsrDestroyThread(ptr)
|
||||
@ stdcall CsrExecServerThread(ptr long)
|
||||
@ stdcall CsrGetProcessLuid(ptr ptr)
|
||||
@ stdcall CsrImpersonateClient(ptr)
|
||||
@ stdcall CsrLockProcessByClientId(ptr ptr)
|
||||
@ stdcall CsrLockThreadByClientId(ptr ptr)
|
||||
@ stdcall CsrMoveSatisfiedWait(ptr ptr)
|
||||
@ stdcall CsrNotifyWait(ptr long ptr ptr)
|
||||
@ stdcall CsrPopulateDosDevices()
|
||||
@ stdcall CsrQueryApiPort()
|
||||
@ stdcall CsrReferenceThread(ptr)
|
||||
@ stdcall CsrRevertToSelf()
|
||||
@ stdcall CsrServerInitialization(long ptr)
|
||||
@ stdcall CsrSetBackgroundPriority(ptr)
|
||||
@ stdcall CsrSetCallingSpooler(long)
|
||||
@ stdcall CsrSetForegroundPriority(ptr)
|
||||
@ stdcall CsrShutdownProcesses(ptr long)
|
||||
@ stdcall CsrUnhandledExceptionFilter(ptr)
|
||||
@ stdcall CsrUnlockProcess(ptr)
|
||||
@ stdcall CsrUnlockThread(ptr)
|
||||
@ stdcall CsrValidateMessageBuffer(ptr ptr long long)
|
||||
@ stdcall CsrValidateMessageString(ptr ptr)
|
||||
@@ -0,0 +1,988 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsys/csr/csrsrv/init.c
|
||||
* PURPOSE: CSR Server DLL Initialization
|
||||
* PROGRAMMERS: Alex Ionescu ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "srv.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
HANDLE CsrObjectDirectory;
|
||||
ULONG SessionId;
|
||||
BOOLEAN CsrProfileControl;
|
||||
UNICODE_STRING CsrDirectoryName;
|
||||
HANDLE CsrHeap;
|
||||
HANDLE BNOLinksDirectory;
|
||||
HANDLE SessionObjectDirectory;
|
||||
HANDLE DosDevicesDirectory;
|
||||
HANDLE CsrInitializationEvent;
|
||||
SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
|
||||
ULONG CsrDebug;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrParseServerCommandLine
|
||||
*
|
||||
* The CsrParseServerCommandLine routine parses the CSRSS command-line in the
|
||||
* registry and performs operations for each entry found.
|
||||
*
|
||||
* @param ArgumentCount
|
||||
* Number of arguments on the command line.
|
||||
*
|
||||
* @param Arguments
|
||||
* Array of arguments.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
CsrParseServerCommandLine(IN ULONG ArgumentCount,
|
||||
IN PCHAR Arguments[])
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCHAR ParameterName = NULL, ParameterValue = NULL, EntryPoint, ServerString;
|
||||
ULONG i, DllIndex;
|
||||
ANSI_STRING AnsiString;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
||||
/* Set the Defaults */
|
||||
CsrTotalPerProcessDataLength = 0;
|
||||
CsrObjectDirectory = 0;
|
||||
CsrMaxApiRequestThreads = 16;
|
||||
|
||||
/* Save our Session ID, and create a Directory for it */
|
||||
SessionId = NtCurrentPeb()->SessionId;
|
||||
Status = CsrCreateSessionObjectDirectory(SessionId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
|
||||
Status);
|
||||
|
||||
/* It's not fatal if the session ID isn't zero */
|
||||
if (SessionId) return Status;
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
}
|
||||
|
||||
/* Loop through every argument */
|
||||
for (i = 1; i < ArgumentCount; i++)
|
||||
{
|
||||
/* Split Name and Value */
|
||||
ParameterName = Arguments[i];
|
||||
ParameterValue = NULL;
|
||||
ParameterValue = strchr(ParameterName, '=');
|
||||
if (ParameterValue) *ParameterValue++ = ANSI_NULL;
|
||||
DPRINT1("Name=%s, Value=%s\n", ParameterName, ParameterValue);
|
||||
|
||||
/* Check for Object Directory */
|
||||
if (!_stricmp(ParameterName, "ObjectDirectory"))
|
||||
{
|
||||
/* Check if a session ID is specified */
|
||||
if (SessionId)
|
||||
{
|
||||
DPRINT1("Sessions not yet implemented\n");
|
||||
ASSERT(SessionId);
|
||||
}
|
||||
|
||||
/* Initialize the directory name */
|
||||
RtlInitAnsiString(&AnsiString, ParameterValue);
|
||||
Status = RtlAnsiStringToUnicodeString(&CsrDirectoryName,
|
||||
&AnsiString,
|
||||
TRUE);
|
||||
ASSERT(NT_SUCCESS(Status) || SessionId != 0);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Create it */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&CsrDirectoryName,
|
||||
OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtCreateDirectoryObject(&CsrObjectDirectory,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Secure it */
|
||||
Status = CsrSetDirectorySecurity(CsrObjectDirectory);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "SubSystemType"))
|
||||
{
|
||||
/* Ignored */
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "MaxRequestThreads"))
|
||||
{
|
||||
Status = RtlCharToInteger(ParameterValue,
|
||||
0,
|
||||
&CsrMaxApiRequestThreads);
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "RequestThreads"))
|
||||
{
|
||||
/* Ignored */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "ProfileControl"))
|
||||
{
|
||||
/* Ignored */
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "SharedSection"))
|
||||
{
|
||||
/* Craete the Section */
|
||||
Status = CsrSrvCreateSharedSection(ParameterValue);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
|
||||
ParameterName, ParameterValue, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Load us */
|
||||
Status = CsrLoadServerDll("CSRSS", NULL, CSR_SRV_SERVER);
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "ServerDLL"))
|
||||
{
|
||||
/* Loop the command line */
|
||||
EntryPoint = NULL;
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
ServerString = ParameterValue;
|
||||
while (*ServerString)
|
||||
{
|
||||
/* Check for the Entry Point */
|
||||
if ((*ServerString == ':') && (!EntryPoint))
|
||||
{
|
||||
/* Found it. Add a nullchar and save it */
|
||||
*ServerString++ = ANSI_NULL;
|
||||
EntryPoint = ServerString;
|
||||
}
|
||||
|
||||
/* Check for the Dll Index */
|
||||
if (*ServerString++ == ',') break;
|
||||
}
|
||||
|
||||
/* Did we find something to load? */
|
||||
if (!*ServerString)
|
||||
{
|
||||
DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
|
||||
ParameterValue, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Convert it to a ULONG */
|
||||
Status = RtlCharToInteger(ServerString, 10, &DllIndex);
|
||||
|
||||
/* Add a null char if it was valid */
|
||||
if (NT_SUCCESS(Status)) ServerString[-1] = ANSI_NULL;
|
||||
|
||||
/* Load it */
|
||||
if (CsrDebug & 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue, EntryPoint);
|
||||
Status = CsrLoadServerDll(ParameterValue, EntryPoint, DllIndex);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
|
||||
ParameterValue, Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else if (!_stricmp(ParameterName, "Windows"))
|
||||
{
|
||||
/* Ignored */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid parameter on the command line */
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrCreateLocalSystemSD
|
||||
*
|
||||
* The CsrCreateLocalSystemSD routine creates a Security Descriptor for
|
||||
* the local account with PORT_ALL_ACCESS.
|
||||
*
|
||||
* @param LocalSystemSd
|
||||
* Pointer to a pointer to the security descriptor to create.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd)
|
||||
{
|
||||
SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
|
||||
PSID SystemSid;
|
||||
ULONG Length;
|
||||
PSECURITY_DESCRIPTOR SystemSd;
|
||||
PACL Dacl;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Initialize the System SID */
|
||||
RtlAllocateAndInitializeSid(&NtSidAuthority, 1,
|
||||
SECURITY_LOCAL_SYSTEM_RID,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
&SystemSid);
|
||||
|
||||
/* Get the length of the SID */
|
||||
Length = RtlLengthSid(SystemSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
|
||||
|
||||
/* Allocate a buffer for the Security Descriptor, with SID and DACL */
|
||||
SystemSd = RtlAllocateHeap(CsrHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
|
||||
|
||||
/* Set the pointer to the DACL */
|
||||
Dacl = (PACL)((ULONG_PTR)SystemSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
|
||||
/* Now create the SD itself */
|
||||
Status = RtlCreateSecurityDescriptor(SystemSd, SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
RtlFreeHeap(CsrHeap, 0, SystemSd);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create the DACL for it*/
|
||||
RtlCreateAcl(Dacl, Length, ACL_REVISION2);
|
||||
|
||||
/* Create the ACE */
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PORT_ALL_ACCESS, SystemSid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
RtlFreeHeap(CsrHeap, 0, SystemSd);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Clear the DACL in the SD */
|
||||
Status = RtlSetDaclSecurityDescriptor(SystemSd, TRUE, Dacl, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
RtlFreeHeap(CsrHeap, 0, SystemSd);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Free the SID and return*/
|
||||
RtlFreeSid(SystemSid);
|
||||
*LocalSystemSd = SystemSd;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name GetDosDevicesProtection
|
||||
*
|
||||
* The GetDosDevicesProtection creates a security descriptor for the DOS Devices
|
||||
* Object Directory.
|
||||
*
|
||||
* @param DosDevicesSd
|
||||
* Pointer to the Security Descriptor to return.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks Depending on the DOS Devices Protection Mode (set in the registry),
|
||||
* regular users may or may not have full access to the directory.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd)
|
||||
{
|
||||
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
||||
SID_IDENTIFIER_AUTHORITY CreatorAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
|
||||
SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
|
||||
PSID WorldSid, CreatorSid, AdminSid, SystemSid;
|
||||
UCHAR KeyValueBuffer[0x40];
|
||||
PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
|
||||
UNICODE_STRING KeyName;
|
||||
ULONG ProtectionMode = 0;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PACL Dacl;
|
||||
PACCESS_ALLOWED_ACE Ace;
|
||||
HANDLE hKey;
|
||||
NTSTATUS Status;
|
||||
ULONG ResultLength, SidLength, AclLength;
|
||||
|
||||
/* Create the SD */
|
||||
Status = RtlCreateSecurityDescriptor(DosDevicesSd, SECURITY_DESCRIPTOR_REVISION);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Initialize the System SID */
|
||||
Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 1,
|
||||
SECURITY_LOCAL_SYSTEM_RID,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
&SystemSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Initialize the World SID */
|
||||
Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1,
|
||||
SECURITY_WORLD_RID,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
&WorldSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Initialize the Admin SID */
|
||||
Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
&AdminSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Initialize the Creator SID */
|
||||
Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1,
|
||||
SECURITY_CREATOR_OWNER_RID,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
&CreatorSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Open the Session Manager Key */
|
||||
RtlInitUnicodeString(&KeyName, SM_REG_KEY);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Read the key value */
|
||||
RtlInitUnicodeString(&KeyName, L"ProtectionMode");
|
||||
Status = NtQueryValueKey(hKey,
|
||||
&KeyName,
|
||||
KeyValuePartialInformation,
|
||||
KeyValueBuffer,
|
||||
sizeof(KeyValueBuffer),
|
||||
&ResultLength);
|
||||
|
||||
/* Make sure it's what we expect it to be */
|
||||
KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
|
||||
if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
|
||||
(*(PULONG)KeyValuePartialInfo->Data))
|
||||
{
|
||||
/* Save the Protection Mode */
|
||||
ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
|
||||
}
|
||||
|
||||
/* Close the handle */
|
||||
NtClose(hKey);
|
||||
}
|
||||
|
||||
/* Check the Protection Mode */
|
||||
if (ProtectionMode & 3)
|
||||
{
|
||||
/* Calculate SID Lengths */
|
||||
SidLength = RtlLengthSid(CreatorSid) + RtlLengthSid(SystemSid) +
|
||||
RtlLengthSid(AdminSid);
|
||||
AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
|
||||
|
||||
/* Allocate memory for the DACL */
|
||||
Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength);
|
||||
ASSERT(Dacl != NULL);
|
||||
|
||||
/* Build the ACL and add 3 ACEs */
|
||||
Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, AdminSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, CreatorSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Edit the ACEs to make them inheritable */
|
||||
Status = RtlGetAce(Dacl, 0, (PVOID*)&Ace);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
|
||||
Status = RtlGetAce(Dacl, 1, (PVOID*)&Ace);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
|
||||
Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
|
||||
|
||||
/* Set this DACL with the SD */
|
||||
Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
goto Quickie;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate SID Lengths */
|
||||
SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(SystemSid);
|
||||
AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
|
||||
|
||||
/* Allocate memory for the DACL */
|
||||
Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength);
|
||||
ASSERT(Dacl != NULL);
|
||||
|
||||
/* Build the ACL and add 3 ACEs */
|
||||
Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, WorldSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, WorldSid);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Edit the last ACE to make it inheritable */
|
||||
Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
|
||||
|
||||
/* Set this DACL with the SD */
|
||||
Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* FIXME: failure cases! Fail: */
|
||||
/* Free the memory */
|
||||
RtlFreeHeap(CsrHeap, 0, Dacl);
|
||||
|
||||
/* FIXME: semi-failure cases! Quickie: */
|
||||
Quickie:
|
||||
/* Free the SIDs */
|
||||
RtlFreeSid(SystemSid);
|
||||
RtlFreeSid(WorldSid);
|
||||
RtlFreeSid(AdminSid);
|
||||
RtlFreeSid(CreatorSid);
|
||||
|
||||
/* Return */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name FreeDosDevicesProtection
|
||||
*
|
||||
* The FreeDosDevicesProtection frees the security descriptor that was created
|
||||
* by GetDosDevicesProtection
|
||||
*
|
||||
* @param DosDevicesSd
|
||||
* Pointer to the security descriptor to free.
|
||||
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd)
|
||||
{
|
||||
PACL Dacl;
|
||||
BOOLEAN Present, Default;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Get the DACL corresponding to this SD */
|
||||
Status = RtlGetDaclSecurityDescriptor(DosDevicesSd, &Present, &Dacl, &Default);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
ASSERT(Present);
|
||||
ASSERT(Dacl != NULL);
|
||||
|
||||
/* Free it */
|
||||
if ((NT_SUCCESS(Status)) && (Dacl)) RtlFreeHeap(CsrHeap, 0, Dacl);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrCreateSessionObjectDirectory
|
||||
*
|
||||
* The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
|
||||
* Session and Dos Devices directories for the specified session.
|
||||
*
|
||||
* @param Session
|
||||
* Session ID for which to create the directories.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateSessionObjectDirectory(IN ULONG Session)
|
||||
{
|
||||
WCHAR SessionBuffer[512], BnoBuffer[512];
|
||||
UNICODE_STRING SessionString, BnoString;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE BnoHandle;
|
||||
SECURITY_DESCRIPTOR DosDevicesSd;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Generate the Session BNOLINKS Directory name */
|
||||
swprintf(SessionBuffer, L"%ws\\BNOLINKS", SESSION_ROOT);
|
||||
RtlInitUnicodeString(&SessionString, SessionBuffer);
|
||||
|
||||
/* Create it */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SessionString,
|
||||
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtCreateDirectoryObject(&BNOLinksDirectory,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
|
||||
"CsrCreateSessionObjectDirectory - status = %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Now add the Session ID */
|
||||
swprintf(SessionBuffer, L"%ld", Session);
|
||||
RtlInitUnicodeString(&SessionString, SessionBuffer);
|
||||
|
||||
/* Check if this is the first Session */
|
||||
if (Session)
|
||||
{
|
||||
/* Not the first, so the name will be slighly more complex */
|
||||
swprintf(BnoBuffer, L"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT, Session);
|
||||
RtlInitUnicodeString(&BnoString, BnoBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the direct name */
|
||||
RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
|
||||
}
|
||||
|
||||
/* Create the symlink */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SessionString,
|
||||
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
||||
BNOLinksDirectory,
|
||||
NULL);
|
||||
Status = NtCreateSymbolicLinkObject(&BnoHandle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
&BnoString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
|
||||
"CsrCreateSessionObjectDirectory - status = %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create the \DosDevices Security Descriptor */
|
||||
Status = GetDosDevicesProtection(&DosDevicesSd);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Now create a directory for this session */
|
||||
swprintf(SessionBuffer, L"%ws\\%ld", SESSION_ROOT, Session);
|
||||
RtlInitUnicodeString(&SessionString, SessionBuffer);
|
||||
|
||||
/* Create the directory */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SessionString,
|
||||
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
||||
0,
|
||||
&DosDevicesSd);
|
||||
Status = NtCreateDirectoryObject(&SessionObjectDirectory,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
|
||||
"CsrCreateSessionObjectDirectory - status = %lx\n", Status);
|
||||
FreeDosDevicesProtection(&DosDevicesSd);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Next, create a directory for this session's DOS Devices */
|
||||
RtlInitUnicodeString(&SessionString, L"DosDevices");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&SessionString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
SessionObjectDirectory,
|
||||
&DosDevicesSd);
|
||||
Status = NtCreateDirectoryObject(&DosDevicesDirectory,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
|
||||
"CsrCreateSessionObjectDirectory - status = %lx\n", Status);
|
||||
}
|
||||
|
||||
/* Release the Security Descriptor */
|
||||
FreeDosDevicesProtection(&DosDevicesSd);
|
||||
|
||||
/* Return */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSetProcessSecurity
|
||||
*
|
||||
* The CsrSetProcessSecurity routine protects access to the CSRSS process
|
||||
* from unauthorized tampering.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSetProcessSecurity(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE hToken, hProcess = NtCurrentProcess();
|
||||
ULONG ReturnLength, Length;
|
||||
PTOKEN_USER TokenInfo = NULL;
|
||||
PSECURITY_DESCRIPTOR ProcSd = NULL;
|
||||
PACL Dacl;
|
||||
PSID UserSid;
|
||||
|
||||
/* Open our token */
|
||||
Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Get the Token User Length */
|
||||
NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length);
|
||||
|
||||
/* Allocate space for it */
|
||||
TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length);
|
||||
if (!TokenInfo)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Now query the data */
|
||||
Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length);
|
||||
NtClose(hToken);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Now check the SID Length */
|
||||
UserSid = TokenInfo->User.Sid;
|
||||
ReturnLength = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
|
||||
|
||||
/* Allocate a buffer for the Security Descriptor, with SID and DACL */
|
||||
ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
|
||||
if (!ProcSd)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Set the pointer to the DACL */
|
||||
Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
|
||||
/* Now create the SD itself */
|
||||
Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Create the DACL for it*/
|
||||
RtlCreateAcl(Dacl, Length, ACL_REVISION2);
|
||||
|
||||
/* Create the ACE */
|
||||
Status = RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
PROCESS_VM_READ | PROCESS_VM_WRITE |
|
||||
PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE |
|
||||
PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME |
|
||||
PROCESS_QUERY_INFORMATION | READ_CONTROL,
|
||||
UserSid);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Clear the DACL in the SD */
|
||||
Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
/* Write the SD into the Process */
|
||||
Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd);
|
||||
|
||||
/* Free the memory and return */
|
||||
Quickie:
|
||||
if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd);
|
||||
RtlFreeHeap(CsrHeap, 0, TokenInfo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSetDirectorySecurity
|
||||
*
|
||||
* The CsrSetDirectorySecurity routine sets the security descriptor for the
|
||||
* specified Object Directory.
|
||||
*
|
||||
* @param ObjectDirectory
|
||||
* Handle fo the Object Directory to protect.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSetDirectorySecurity(IN HANDLE ObjectDirectory)
|
||||
{
|
||||
/* FIXME: Implement */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrServerInitialization
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrServerInitialization routine is the native (not Server) entrypoint
|
||||
* of this Server DLL. It serves as the entrypoint for csrss.
|
||||
*
|
||||
* @param ArgumentCount
|
||||
* Number of arguments on the command line.
|
||||
*
|
||||
* @param Arguments
|
||||
* Array of arguments from the command line.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrServerInitialization(IN ULONG ArgumentCount,
|
||||
IN PCHAR Arguments[])
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
ULONG i = 0;
|
||||
PVOID ProcessData;
|
||||
PCSR_SERVER_DLL ServerDll;
|
||||
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
|
||||
|
||||
/* Create the Init Event */
|
||||
Status = NtCreateEvent(&CsrInitializationEvent,
|
||||
EVENT_ALL_ACCESS,
|
||||
NULL,
|
||||
SynchronizationEvent,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Cache System Basic Information so we don't always request it */
|
||||
Status = NtQuerySystemInformation(SystemBasicInformation,
|
||||
&CsrNtSysInfo,
|
||||
sizeof(SYSTEM_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Save our Heap */
|
||||
CsrHeap = RtlGetProcessHeap();
|
||||
|
||||
/* Set our Security Descriptor to protect the process */
|
||||
Status = CsrSetProcessSecurity();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set up Session Support */
|
||||
Status = CsrInitializeNtSessionList();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set up Process Support */
|
||||
Status = CsrInitializeProcessStructure();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Parse the command line */
|
||||
Status = CsrParseServerCommandLine(ArgumentCount, Arguments);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* All Server DLLs are now loaded, allocate a heap for the Root Process */
|
||||
ProcessData = RtlAllocateHeap(CsrHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
CsrTotalPerProcessDataLength);
|
||||
if (!ProcessData)
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
|
||||
__FUNCTION__, STATUS_NO_MEMORY);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Our Root Process was never officially initalized, so write the data
|
||||
* for each Server DLL manually.
|
||||
*/
|
||||
for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
|
||||
{
|
||||
/* Get the current Server */
|
||||
ServerDll = CsrLoadedServerDll[i];
|
||||
|
||||
/* Is it loaded, and does it have per process data? */
|
||||
if ((ServerDll) && (ServerDll->SizeOfProcessData))
|
||||
{
|
||||
/* It does, give it part of our allocated heap */
|
||||
CsrRootProcess->ServerData[i] = ProcessData;
|
||||
|
||||
/* Move to the next heap position */
|
||||
ProcessData = (PVOID)((ULONG_PTR)ProcessData +
|
||||
ServerDll->SizeOfProcessData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing for this Server DLL */
|
||||
CsrRootProcess->ServerData[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now initialize the Root Process manually as well */
|
||||
for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
|
||||
{
|
||||
/* Get the current Server */
|
||||
ServerDll = CsrLoadedServerDll[i];
|
||||
|
||||
/* Is it loaded, and does it a callback for new processes? */
|
||||
if ((ServerDll) && (ServerDll->NewProcessCallback))
|
||||
{
|
||||
/* Call the callback */
|
||||
ServerDll->NewProcessCallback(NULL, CsrRootProcess);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now initialize our API Port */
|
||||
Status = CsrApiPortInitialize();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Initialize the API Port for SM communication */
|
||||
Status = CsrSbApiPortInitialize();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* We're all set! Connect to SM! */
|
||||
Status = SmConnectToSm(&CsrSbApiPortName,
|
||||
CsrSbApiPort,
|
||||
IMAGE_SUBSYSTEM_WINDOWS_GUI,
|
||||
&CsrSmApiPort);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Finito! Signal the event */
|
||||
Status = NtSetEvent(CsrInitializationEvent, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Close the event handle now */
|
||||
NtClose(CsrInitializationEvent);
|
||||
|
||||
/* Have us handle Hard Errors */
|
||||
Status = NtSetDefaultHardErrorPort(CsrApiPort);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
|
||||
__FUNCTION__, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrPopulateDosDevices
|
||||
* @unimplemented NT5.1
|
||||
*
|
||||
* The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
|
||||
* to populate the Dos Devices Object Directory for the session.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrPopulateDosDevices(VOID)
|
||||
{
|
||||
DPRINT1("Deprecated API\n");
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
DllMain(IN HANDLE hDll,
|
||||
IN DWORD dwReason,
|
||||
IN LPVOID lpReserved)
|
||||
{
|
||||
/* We don't do much */
|
||||
UNREFERENCED_PARAMETER(hDll);
|
||||
UNREFERENCED_PARAMETER(dwReason);
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,687 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsys/csr/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[5] =
|
||||
{
|
||||
CsrSrvClientConnect,
|
||||
CsrSrvUnusedFunction,
|
||||
CsrSrvUnusedFunction,
|
||||
CsrSrvIdentifyAlertableThread,
|
||||
CsrSrvSetPriorityClass
|
||||
};
|
||||
|
||||
BOOLEAN CsrServerApiServerValidTable[5] =
|
||||
{
|
||||
TRUE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE
|
||||
};
|
||||
|
||||
PCHAR CsrServerApiNameTable[5] =
|
||||
{
|
||||
"ClientConnect",
|
||||
"ThreadConnect",
|
||||
"ProfileControl",
|
||||
"IdentifyAlertableThread",
|
||||
"SetPriorityClass"
|
||||
};
|
||||
|
||||
PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
|
||||
PVOID CsrSrvSharedSectionHeap;
|
||||
PVOID CsrSrvSharedSectionBase;
|
||||
PVOID *CsrSrvSharedStaticServerData;
|
||||
ULONG CsrSrvSharedSectionSize;
|
||||
HANDLE CsrSrvSharedSection;
|
||||
|
||||
/* PRIVATE FUNCTIONS**********************************************************/
|
||||
|
||||
/*++
|
||||
* @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
|
||||
* othwerwise.
|
||||
*
|
||||
* @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;
|
||||
|
||||
/* 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 != CSR_SRV_SERVER)
|
||||
{
|
||||
/* 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;
|
||||
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) ? "ServerDllInitialization" :
|
||||
EntryPoint);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Check for Success */
|
||||
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 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.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll)
|
||||
{
|
||||
/* Setup the DLL Object */
|
||||
LoadedServerDll->ApiBase = 0;
|
||||
LoadedServerDll->HighestApiSupported = 5;
|
||||
LoadedServerDll->DispatchTable = CsrServerApiDispatchTable;
|
||||
LoadedServerDll->ValidTable = CsrServerApiServerValidTable;
|
||||
LoadedServerDll->NameTable = CsrServerApiNameTable;
|
||||
LoadedServerDll->SizeOfProcessData = 0;
|
||||
LoadedServerDll->ConnectCallback = NULL;
|
||||
LoadedServerDll->DisconnectCallback = NULL;
|
||||
|
||||
/* All done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @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 Reply
|
||||
* 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.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSR_CLIENT_CONNECT ClientConnect;
|
||||
PCSR_SERVER_DLL ServerDll;
|
||||
PCSR_PROCESS CurrentProcess = ((PCSR_THREAD)NtCurrentTeb()->CsrClientThread)->Process;
|
||||
|
||||
/* Load the Message, set default reply */
|
||||
ClientConnect = (PCSR_CLIENT_CONNECT)&ApiMessage->CsrClientConnect;
|
||||
*Reply = 0;
|
||||
|
||||
/* 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,
|
||||
1)))
|
||||
{
|
||||
/* 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
|
||||
* othwerwise.
|
||||
*
|
||||
* @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,
|
||||
0,
|
||||
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
|
||||
* othwerwise.
|
||||
*
|
||||
* @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 sectio into this process */
|
||||
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 Reply
|
||||
* Pointer to an optional reply to this request.
|
||||
*
|
||||
* @return STATUS_SUCCESS.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply)
|
||||
{
|
||||
PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
|
||||
|
||||
/* Set the alertable flag */
|
||||
CsrThread->Flags |= CsrThreadAltertable;
|
||||
|
||||
/* 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 Reply
|
||||
* Pointer to an optional reply to this request.
|
||||
*
|
||||
* @return STATUS_SUCCESS.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply)
|
||||
{
|
||||
/* 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 Reply
|
||||
* Pointer to an optional reply to this request.
|
||||
*
|
||||
* @return STATUS_INVALID_PARAMETER.
|
||||
*
|
||||
* @remarks CsrSrvSetPriorityClass does not use this stub because it must
|
||||
* return success.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply)
|
||||
{
|
||||
/* 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.
|
||||
*
|
||||
*--*/
|
||||
LONG
|
||||
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 */
|
||||
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsys/csr/csrsrv/session.c
|
||||
* PURPOSE: CSR Server DLL Session Implementation
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "srv.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
RTL_CRITICAL_SECTION CsrNtSessionLock;
|
||||
LIST_ENTRY CsrNtSessionList;
|
||||
HANDLE CsrSmApiPort;
|
||||
|
||||
PSB_API_ROUTINE CsrServerSbApiDispatch[5] =
|
||||
{
|
||||
CsrSbCreateSession,
|
||||
CsrSbTerminateSession,
|
||||
CsrSbForeignSessionComplete,
|
||||
CsrSbCreateProcess,
|
||||
NULL
|
||||
};
|
||||
|
||||
PCHAR CsrServerSbApiName[5] =
|
||||
{
|
||||
"SbCreateSession",
|
||||
"SbTerminateSession",
|
||||
"SbForeignSessionComplete",
|
||||
"SbCreateProcess",
|
||||
"Unknown Csr Sb Api Number"
|
||||
};
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrInitializeNtSessionList
|
||||
*
|
||||
* The CsrInitializeNtSessionList routine sets up support for CSR Sessions.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrInitializeNtSessionList(VOID)
|
||||
{
|
||||
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
|
||||
|
||||
/* Initialize the Session List */
|
||||
InitializeListHead(&CsrNtSessionList);
|
||||
|
||||
/* Initialize the Session Lock */
|
||||
return RtlInitializeCriticalSection(&CsrNtSessionLock);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrAllocateNtSession
|
||||
*
|
||||
* The CsrAllocateNtSession routine allocates a new CSR NT Session.
|
||||
*
|
||||
* @param SessionId
|
||||
* Session ID of the CSR NT Session to allocate.
|
||||
*
|
||||
* @return Pointer to the newly allocated CSR NT Session.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
PCSR_NT_SESSION
|
||||
NTAPI
|
||||
CsrAllocateNtSession(IN ULONG SessionId)
|
||||
{
|
||||
PCSR_NT_SESSION NtSession;
|
||||
|
||||
/* Allocate an NT Session Object */
|
||||
NtSession = RtlAllocateHeap(CsrHeap, 0, sizeof(CSR_NT_SESSION));
|
||||
if (NtSession)
|
||||
{
|
||||
/* Setup the Session Object */
|
||||
NtSession->SessionId = SessionId;
|
||||
NtSession->ReferenceCount = 1;
|
||||
|
||||
/* Insert it into the Session List */
|
||||
CsrAcquireNtSessionLock();
|
||||
InsertHeadList(&CsrNtSessionList, &NtSession->SessionLink);
|
||||
CsrReleaseNtSessionLock();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(NtSession != NULL);
|
||||
}
|
||||
|
||||
/* Return the Session (or NULL) */
|
||||
return NtSession;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrReferenceNtSession
|
||||
*
|
||||
* The CsrReferenceNtSession increases the reference count of a CSR NT Session.
|
||||
*
|
||||
* @param Session
|
||||
* Pointer to the CSR NT Session to reference.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrReferenceNtSession(IN PCSR_NT_SESSION Session)
|
||||
{
|
||||
/* Acquire the lock */
|
||||
CsrAcquireNtSessionLock();
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(!IsListEmpty(&Session->SessionLink));
|
||||
ASSERT(Session->SessionId != 0);
|
||||
ASSERT(Session->ReferenceCount != 0);
|
||||
|
||||
/* Increase the reference count */
|
||||
Session->ReferenceCount++;
|
||||
|
||||
/* Release the lock */
|
||||
CsrReleaseNtSessionLock();
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDereferenceNtSession
|
||||
*
|
||||
* The CsrDereferenceNtSession decreases the reference count of a
|
||||
* CSR NT Session.
|
||||
*
|
||||
* @param Session
|
||||
* Pointer to the CSR NT Session to reference.
|
||||
*
|
||||
* @param ExitStatus
|
||||
* If this is the last reference to the session, this argument
|
||||
* specifies the exit status.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks CsrDereferenceNtSession will complete the session if
|
||||
* the last reference to it has been closed.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceNtSession(IN PCSR_NT_SESSION Session,
|
||||
IN NTSTATUS ExitStatus)
|
||||
{
|
||||
/* Acquire the lock */
|
||||
CsrAcquireNtSessionLock();
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(!IsListEmpty(&Session->SessionLink));
|
||||
ASSERT(Session->SessionId != 0);
|
||||
ASSERT(Session->ReferenceCount != 0);
|
||||
|
||||
/* Dereference the Session Object */
|
||||
if (!(--Session->ReferenceCount))
|
||||
{
|
||||
/* Remove it from the list */
|
||||
RemoveEntryList(&Session->SessionLink);
|
||||
|
||||
/* Release the lock */
|
||||
CsrReleaseNtSessionLock();
|
||||
|
||||
/* Tell SM that we're done here */
|
||||
SmSessionComplete(CsrSmApiPort, Session->SessionId, ExitStatus);
|
||||
|
||||
/* Free the Session Object */
|
||||
RtlFreeHeap(CsrHeap, 0, Session);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Release the lock, the Session is still active */
|
||||
CsrReleaseNtSessionLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* SESSION MANAGER FUNCTIONS**************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrSbCreateSession
|
||||
*
|
||||
* The CsrSbCreateSession API is called by the Session Manager whenever a new
|
||||
* session is created.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE othwerwise.
|
||||
*
|
||||
* @remarks The CsrSbCreateSession routine will initialize a new CSR NT
|
||||
* Session and allocate a new CSR Process for the subsystem process.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbCreateSession(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
PSB_CREATE_SESSION_MSG CreateSession = &ApiMessage->CreateSession;
|
||||
HANDLE hProcess, hThread;
|
||||
PCSR_PROCESS CsrProcess;
|
||||
NTSTATUS Status;
|
||||
KERNEL_USER_TIMES KernelTimes;
|
||||
PCSR_THREAD CsrThread;
|
||||
PVOID ProcessData;
|
||||
ULONG i;
|
||||
|
||||
/* Save the Process and Thread Handles */
|
||||
hProcess = CreateSession->ProcessInfo.ProcessHandle;
|
||||
hThread = CreateSession->ProcessInfo.ThreadHandle;
|
||||
|
||||
/* Lock the Processes */
|
||||
CsrAcquireProcessLock();
|
||||
|
||||
/* Allocate a new process */
|
||||
CsrProcess = CsrAllocateProcess();
|
||||
if (!CsrProcess)
|
||||
{
|
||||
/* Fail */
|
||||
ApiMessage->ReturnValue = STATUS_NO_MEMORY;
|
||||
CsrReleaseProcessLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set the exception port */
|
||||
Status = NtSetInformationProcess(hProcess,
|
||||
ProcessExceptionPort,
|
||||
&CsrApiPort,
|
||||
sizeof(HANDLE));
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail the request */
|
||||
CsrDeallocateProcess(CsrProcess);
|
||||
CsrReleaseProcessLock();
|
||||
|
||||
/* Strange as it seems, NTSTATUSes are actually returned */
|
||||
return (BOOLEAN)STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Get the Create Time */
|
||||
Status = NtQueryInformationThread(hThread,
|
||||
ThreadTimes,
|
||||
&KernelTimes,
|
||||
sizeof(KERNEL_USER_TIMES),
|
||||
NULL);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail the request */
|
||||
CsrDeallocateProcess(CsrProcess);
|
||||
CsrReleaseProcessLock();
|
||||
|
||||
/* Strange as it seems, NTSTATUSes are actually returned */
|
||||
return (BOOLEAN)Status;
|
||||
}
|
||||
|
||||
/* Allocate a new Thread */
|
||||
CsrThread = CsrAllocateThread(CsrProcess);
|
||||
if (!CsrThread)
|
||||
{
|
||||
/* Fail the request */
|
||||
CsrDeallocateProcess(CsrProcess);
|
||||
ApiMessage->ReturnValue = STATUS_NO_MEMORY;
|
||||
CsrReleaseProcessLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Setup the Thread Object */
|
||||
CsrThread->CreateTime = KernelTimes.CreateTime;
|
||||
CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
|
||||
CsrThread->ThreadHandle = hThread;
|
||||
ProtectHandle(hThread);
|
||||
CsrThread->Flags = 0;
|
||||
|
||||
/* Insert it into the Process List */
|
||||
CsrInsertThread(CsrProcess, CsrThread);
|
||||
|
||||
/* Setup Process Data */
|
||||
CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
|
||||
CsrProcess->ProcessHandle = hProcess;
|
||||
CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId);
|
||||
|
||||
/* Set the Process Priority */
|
||||
CsrSetBackgroundPriority(CsrProcess);
|
||||
|
||||
/* Get the first data location */
|
||||
ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX];
|
||||
|
||||
/* Loop every DLL */
|
||||
for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
|
||||
{
|
||||
/* Check if the DLL is loaded and has Process Data */
|
||||
if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData)
|
||||
{
|
||||
/* Write the pointer to the data */
|
||||
CsrProcess->ServerData[i] = ProcessData;
|
||||
|
||||
/* Move to the next data location */
|
||||
ProcessData = (PVOID)((ULONG_PTR)ProcessData +
|
||||
CsrLoadedServerDll[i]->SizeOfProcessData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing for this Process */
|
||||
CsrProcess->ServerData[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert the Process */
|
||||
CsrInsertProcess(NULL, NULL, CsrProcess);
|
||||
|
||||
/* Activate the Thread */
|
||||
ApiMessage->ReturnValue = NtResumeThread(hThread, NULL);
|
||||
|
||||
/* Release lock and return */
|
||||
CsrReleaseProcessLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbForeignSessionComplete
|
||||
*
|
||||
* The CsrSbForeignSessionComplete API is called by the Session Manager
|
||||
* whenever a foreign session is completed (ie: terminated).
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE othwerwise.
|
||||
*
|
||||
* @remarks The CsrSbForeignSessionComplete API is not yet implemented.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
/* Deprecated/Unimplemented in NT */
|
||||
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbTerminateSession
|
||||
*
|
||||
* The CsrSbTerminateSession API is called by the Session Manager
|
||||
* whenever a foreign session should be destroyed.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE othwerwise.
|
||||
*
|
||||
* @remarks The CsrSbTerminateSession API is not yet implemented.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbTerminateSession(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbCreateProcess
|
||||
*
|
||||
* The CsrSbCreateProcess API is called by the Session Manager
|
||||
* whenever a foreign session is created and a new process should be started.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE othwerwise.
|
||||
*
|
||||
* @remarks The CsrSbCreateProcess API is not yet implemented.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbCreateProcess(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,395 @@
|
||||
#ifndef _SRV_H
|
||||
#define _SRV_H
|
||||
|
||||
/* PSDK/NDK Headers */
|
||||
#define NTOS_MODE_USER
|
||||
#include <stdio.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
#include <ndk/ntndk.h>
|
||||
|
||||
/* CSR Header */
|
||||
#include <csr/server.h>
|
||||
#include <sm/smmsg.h>
|
||||
|
||||
/* PSEH for SEH Support */
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
#define CSR_SERVER_DLL_MAX 4
|
||||
|
||||
#define CsrAcquireProcessLock() \
|
||||
RtlEnterCriticalSection(&CsrProcessLock);
|
||||
|
||||
#define CsrReleaseProcessLock() \
|
||||
RtlLeaveCriticalSection(&CsrProcessLock);
|
||||
|
||||
#define CsrAcquireWaitLock() \
|
||||
RtlEnterCriticalSection(&CsrWaitListsLock);
|
||||
|
||||
#define CsrReleaseWaitLock() \
|
||||
RtlLeaveCriticalSection(&CsrWaitListsLock);
|
||||
|
||||
#define CsrAcquireNtSessionLock() \
|
||||
RtlEnterCriticalSection(&CsrNtSessionLock)
|
||||
|
||||
#define CsrReleaseNtSessionLock() \
|
||||
RtlLeaveCriticalSection(&CsrNtSessionLock)
|
||||
|
||||
#define CsrHashThread(t) \
|
||||
(HandleToUlong(t)&(256 - 1))
|
||||
|
||||
#define ProcessStructureListLocked() \
|
||||
(CsrProcessLock.OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
|
||||
|
||||
#define SM_REG_KEY \
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager"
|
||||
|
||||
#define SESSION_ROOT L"\\Sessions"
|
||||
#define GLOBAL_ROOT L"\\GLOBAL??"
|
||||
#define SYMLINK_NAME L"SymbolicLink"
|
||||
#define SB_PORT_NAME L"SbAbiPort"
|
||||
#define CSR_PORT_NAME L"ApiPort"
|
||||
#define UNICODE_PATH_SEP L"\\"
|
||||
|
||||
#define ROUND_UP(n, align) ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
|
||||
#define ROUND_DOWN(n, align) (((ULONG)n) & ~((align) - 1l))
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
extern ULONG CsrTotalPerProcessDataLength;
|
||||
extern ULONG CsrMaxApiRequestThreads;
|
||||
extern PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
|
||||
extern PCSR_PROCESS CsrRootProcess;
|
||||
extern UNICODE_STRING CsrSbApiPortName;
|
||||
extern UNICODE_STRING CsrApiPortName;
|
||||
extern HANDLE CsrSbApiPort;
|
||||
extern HANDLE CsrSmApiPort;
|
||||
extern HANDLE CsrApiPort;
|
||||
extern HANDLE CsrHeap;
|
||||
extern RTL_CRITICAL_SECTION CsrProcessLock;
|
||||
extern RTL_CRITICAL_SECTION CsrWaitListsLock;
|
||||
extern LIST_ENTRY CsrThreadHashTable[256];
|
||||
extern HANDLE CsrInitializationEvent;
|
||||
extern SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
|
||||
extern UNICODE_STRING CsrDirectoryName;
|
||||
extern HANDLE CsrObjectDirectory;
|
||||
extern PSB_API_ROUTINE CsrServerSbApiDispatch[5];
|
||||
extern ULONG CsrDebug;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/* FIXME: Public APIs should go in the CSR Server Include */
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrCaptureArguments(
|
||||
IN PCSR_THREAD CsrThread,
|
||||
IN PCSR_API_MESSAGE ApiMessage
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrLoadServerDll(
|
||||
IN PCHAR DllString,
|
||||
IN PCHAR EntryPoint,
|
||||
IN ULONG ServerId
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrServerInitialization(
|
||||
ULONG ArgumentCount,
|
||||
PCHAR Arguments[]
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
UnProtectHandle(IN HANDLE ObjectHandle);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedReferenceThread(IN PCSR_THREAD CsrThread);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateSessionObjectDirectory(IN ULONG SessionId);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateObjectDirectory(IN PCHAR ObjectDirectory);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvCreateSharedSection(IN PCHAR ParameterValue);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrInitializeNtSessionList(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrInitializeProcessStructure(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrApiPortInitialize(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSbApiPortInitialize(VOID);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbCreateSession(IN PSB_API_MSG ApiMessage);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbTerminateSession(IN PSB_API_MSG ApiMessage);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbCreateProcess(IN PSB_API_MSG ApiMessage);
|
||||
|
||||
PCSR_PROCESS
|
||||
NTAPI
|
||||
CsrAllocateProcess(VOID);
|
||||
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrAllocateThread(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrInsertThread(
|
||||
IN PCSR_PROCESS Process,
|
||||
IN PCSR_THREAD Thread
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrGetProcessLuid(
|
||||
HANDLE hProcess,
|
||||
PLUID Luid
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrImpersonateClient(IN PCSR_THREAD CsrThread);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrRevertToSelf(VOID);
|
||||
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrLocateThreadByClientId(
|
||||
OUT PCSR_PROCESS *Process,
|
||||
IN PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceNtSession(
|
||||
IN PCSR_NT_SESSION Session,
|
||||
NTSTATUS ExitStatus
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrReferenceNtSession(PCSR_NT_SESSION Session);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedDereferenceThread(PCSR_THREAD CsrThread);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrLockProcessByClientId(
|
||||
IN HANDLE Pid,
|
||||
OUT PCSR_PROCESS *CsrProcess OPTIONAL
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrUnlockProcess(PCSR_PROCESS CsrProcess);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvClientConnect(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvUnusedFunction(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvIdentifyAlertableThread(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvSetPriorityClass(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceThread(PCSR_THREAD CsrThread);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrSbApiRequestThread(IN PVOID Parameter);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrApiRequestThread(IN PVOID Parameter);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ProtectHandle(IN HANDLE ObjectHandle);
|
||||
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrAddStaticServerThread(
|
||||
IN HANDLE hThread,
|
||||
IN PCLIENT_ID ClientId,
|
||||
IN ULONG ThreadFlags
|
||||
);
|
||||
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrConnectToUser(VOID);
|
||||
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrLocateThreadInProcess(
|
||||
IN PCSR_PROCESS CsrProcess OPTIONAL,
|
||||
IN PCLIENT_ID Cid
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvAttachSharedSection(
|
||||
IN PCSR_PROCESS CsrProcess OPTIONAL,
|
||||
OUT PCSR_CONNECTION_INFO ConnectInfo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrNotifyWaitBlock(
|
||||
IN PCSR_WAIT_BLOCK WaitBlock,
|
||||
IN PLIST_ENTRY WaitList,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags,
|
||||
IN BOOLEAN DereferenceThread
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceProcess(PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrInsertProcess(
|
||||
IN PCSR_PROCESS Parent OPTIONAL,
|
||||
IN PCSR_PROCESS CurrentProcess OPTIONAL,
|
||||
IN PCSR_PROCESS CsrProcess
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrPopulateDosDevicesDirectory(
|
||||
IN HANDLE DosDevicesDirectory,
|
||||
IN PPROCESS_DEVICEMAP_INFORMATION DeviceMap
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrValidateMessageBuffer(
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN PVOID *Buffer,
|
||||
IN ULONG ArgumentSize,
|
||||
IN ULONG ArgumentCount
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrDestroyThread(IN PCLIENT_ID Cid);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrDestroyProcess(
|
||||
IN PCLIENT_ID Cid,
|
||||
IN NTSTATUS ExitStatus
|
||||
);
|
||||
|
||||
LONG
|
||||
NTAPI
|
||||
CsrUnhandledExceptionFilter(
|
||||
IN PEXCEPTION_POINTERS ExceptionInfo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrThreadRefcountZero(IN PCSR_THREAD CsrThread);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSetDirectorySecurity(IN HANDLE ObjectDirectory);
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* CSRSRV Status
|
||||
*/
|
||||
|
||||
/* Organization
|
||||
*
|
||||
* api.c - Handles the LPC Reply/Request Threads which wait on Sb and Csr APIs.
|
||||
* Also in charge of creating those threads and setting up the ports.
|
||||
* Finally, it provides external APIs for validating the API buffers
|
||||
* and doing server-to-server API calls.
|
||||
*
|
||||
* init.c - Handles initialization of CSRSRV, including command-line parsing,
|
||||
* loading the Server DLLs, creating the Session Directories, setting
|
||||
* up the DosDevices Object Directory, and initializing each component.
|
||||
*
|
||||
* process.c - Handles all internal functions dealing with the CSR Process Object,
|
||||
* including de/allocation, de/referencing, un/locking, prority, and
|
||||
* lookups. Also handles all external APIs which touch the CSR Process Object.
|
||||
*
|
||||
* server.c - Handles all internal functions related to loading and managing Server
|
||||
* DLLs, as well as the routines handling the Shared Static Memory Section.
|
||||
* Holds the API Dispatch/Valid/Name Tables and the public CSR_SERVER API
|
||||
* interface. Also home of the SEH handler.
|
||||
*
|
||||
* session.c - Handles all internal functions dealing with the CSR Session Object,
|
||||
* including de/allocation, de/referencing, and un/locking. Holds the SB API
|
||||
* Dispatch/Name Tables and the public CsrSv API Interface for commmunication
|
||||
* with the Session Manager.
|
||||
*
|
||||
* thread.c - Handles all internal functions dealing with the CSR Thread Object,
|
||||
* including de/allocation, de/referencing, un/locking, impersonation, and
|
||||
* lookups. Also handles all external APIs which touch the CSR Thread Object.
|
||||
*
|
||||
* wait.c - Handles all internal functions dealing with the CSR Wait Object,
|
||||
* including de/allocation, de/referencing and un/locking. Also implements
|
||||
* the external Wait API for creating, removing and/or notifying waits.
|
||||
*/
|
||||
|
||||
/* Exported APIs, their location, and their status
|
||||
* CsrAddStaticServerThread 753E679E 1 - server.c - IMPLEMENTED
|
||||
* CsrCallServerFromServer 753E4FD9 2 - api.c - IMPLEMENTED
|
||||
* CsrConnectToUser 753E4E48 3 - api.c - IMPLEMENTED
|
||||
* CsrCreateProcess 753E6FD3 4 - process.c - IMPLEMENTED
|
||||
* CsrCreateRemoteThread 753E73BD 5 - thread.c - IMPLEMENTED
|
||||
* CsrCreateThread 753E72DA 6 - thread.c - IMPLEMENTED
|
||||
* CsrCreateWait 753E770E 7 - wait.c - IMPLEMENTED
|
||||
* CsrDebugProcess 753E7682 8 - process.c - IMPLEMENTED
|
||||
* CsrDebugProcessStop 753E768A 9 - process.c - IMPLEMENTED
|
||||
* CsrDereferenceProcess 753E6281 10 - process.c - IMPLEMENTED
|
||||
* CsrDereferenceThread 753E6964 11 - thread.c - IMPLEMENTED
|
||||
* CsrDereferenceWait 753E7886 12 - wait.c - IMPLEMENTED
|
||||
* CsrDestroyProcess 753E7225 13 - process.c - IMPLEMENTED
|
||||
* CsrDestroyThread 753E7478 14 - thread.c - IMPLEMENTED
|
||||
* CsrExecServerThread 753E6841 15 - thread.c - IMPLEMENTED
|
||||
* CsrGetProcessLuid 753E632F 16 - process.c - IMPLEMENTED
|
||||
* CsrImpersonateClient 753E60F8 17 - thread.c - IMPLEMENTED
|
||||
* CsrLockProcessByClientId 753E668F 18 - process.c - IMPLEMENTED
|
||||
* CsrLockThreadByClientId 753E6719 19 - thread.c - IMPLEMENTED
|
||||
* CsrMoveSatisfiedWait 753E7909 20 - wait.c - IMPLEMENTED
|
||||
* CsrNotifyWait 753E782F 21 - wait.c - IMPLEMENTED
|
||||
* CsrPopulateDosDevices 753E37A5 22 - init.c - IMPLEMENTED
|
||||
* CsrQueryApiPort 753E4E42 23 - api.c - IMPLEMENTED
|
||||
* CsrReferenceThread 753E61E5 24 - thread.c - IMPLEMENTED
|
||||
* CsrRevertToSelf 753E615A 25 - thread.c - IMPLEMENTED
|
||||
* CsrServerInitialization 753E3D75 26 - server.c - IMPLEMENTED
|
||||
* CsrSetBackgroundPriority 753E5E87 27 - process.c - IMPLEMENTED
|
||||
* CsrSetCallingSpooler 753E6425 28 - server.c - IMPLEMENTED
|
||||
* CsrSetForegroundPriority 753E5E67 29 - process.c - IMPLEMENTED
|
||||
* CsrShutdownProcesses 753E7547 30 - process.c - IMPLEMENTED
|
||||
* CsrUnhandledExceptionFilter 753E3FE3 31 - server.c - IMPLEMENTED
|
||||
* CsrUnlockProcess 753E66FD 32 - process.c - IMPLEMENTED
|
||||
* CsrUnlockThread 753E7503 33 - thread.c - IMPLEMENTED
|
||||
* CsrValidateMessageBuffer 753E528D 34 - api.c - IMPLEMENTED
|
||||
* CsrValidateMessageString 753E5323 35 - api.c - UNIMPLEMENTED
|
||||
*/
|
||||
|
||||
/* Public CSR API Interface Status (server.c)
|
||||
* CsrSrvClientConnect - IMPLEMENTED
|
||||
* CsrSrvUnusedFunction - IMPLEMENTED
|
||||
* CsrSrvIdentifyAlertableThread - IMPLEMENTED
|
||||
* CsrSrvSetPriorityClass - IMPLEMENTED
|
||||
*/
|
||||
|
||||
/* Public SB API Interface Status (session.c)
|
||||
* CsrSbCreateSession - IMPLEMENTED
|
||||
* CsrSbForeignSessionComplete - IMPLEMENTED
|
||||
* CsrSbTerminateSession - UNIMPLEMENTED
|
||||
* CsrSbCreateProcess - UNIMPLEMENTED
|
||||
*/
|
||||
|
||||
/* What's missing:
|
||||
*
|
||||
* - SMSS needs to be partly re-written to match some things done here.
|
||||
* Among other things, SmConnectToSm, SmCompleteSession and the other
|
||||
* Sm* Exported APIs have to be properly implemented, as well as the
|
||||
* callback calling and SM LPC APIs. [DONE!]
|
||||
*
|
||||
* - NTDLL needs to get the Csr* routines properly implemented. [DONE!]
|
||||
*
|
||||
* - KERNEL32, USER32 need to register with their servers properly.
|
||||
* Additionally, user32 needs to have ClientThreadStartup implemented
|
||||
* properly and do the syscall NtUserInitialize (I think) which also
|
||||
* needs to be implemented in win32k.sys. All this should be less then
|
||||
* 100 lines of code. [KERNEL32 50% DONE, USER32 NOT DONE]
|
||||
*
|
||||
* - The skeleton code for winsrv and basesrv which connects with CSR/CSRSRV
|
||||
* needs to be written. [NOT DONE]
|
||||
*
|
||||
* - The kernel's LPC implementation needs to be made compatible. [DONE!]
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsys/csr/csrsrv/wait.c
|
||||
* PURPOSE: CSR Server DLL Wait Implementation
|
||||
* PROGRAMMERS: Emanuele Aliberti
|
||||
* Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "srv.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
RTL_CRITICAL_SECTION CsrWaitListsLock;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrInitializeWait
|
||||
*
|
||||
* The CsrInitializeWait routine initializes a CSR Wait Object.
|
||||
*
|
||||
* @param WaitFunction
|
||||
* Pointer to the function that will handle this wait.
|
||||
*
|
||||
* @param CsrWaitThread
|
||||
* Pointer to the CSR Thread that will perform the wait.
|
||||
*
|
||||
* @param WaitApiMessage
|
||||
* Pointer to the CSR API Message associated to this wait.
|
||||
*
|
||||
* @param WaitContext
|
||||
* Pointer to a user-defined parameter associated to this wait.
|
||||
*
|
||||
* @param NewWaitBlock
|
||||
* Pointed to the initialized CSR Wait Block for this wait.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrInitializeWait(IN CSR_WAIT_FUNCTION WaitFunction,
|
||||
IN PCSR_THREAD CsrWaitThread,
|
||||
IN OUT PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
OUT PCSR_WAIT_BLOCK *NewWaitBlock)
|
||||
{
|
||||
ULONG Size;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Calculate the size of the wait block */
|
||||
Size = sizeof(CSR_WAIT_BLOCK) -
|
||||
sizeof(WaitBlock->WaitApiMessage) +
|
||||
WaitApiMessage->Header.u1.s1.TotalLength;
|
||||
|
||||
/* Allocate the Wait Block */
|
||||
WaitBlock = RtlAllocateHeap(CsrHeap, 0, Size);
|
||||
if (!WaitBlock)
|
||||
{
|
||||
/* Fail */
|
||||
WaitApiMessage->Status = STATUS_NO_MEMORY;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
WaitBlock->Size = Size;
|
||||
WaitBlock->WaitThread = CsrWaitThread;
|
||||
WaitBlock->WaitContext = WaitContext;
|
||||
WaitBlock->WaitFunction = WaitFunction;
|
||||
WaitBlock->UserWaitList.Flink = NULL;
|
||||
WaitBlock->UserWaitList.Blink = NULL;
|
||||
WaitBlock->WaitList = WaitBlock->UserWaitList;
|
||||
|
||||
/* Copy the message */
|
||||
RtlMoveMemory(&WaitBlock->WaitApiMessage,
|
||||
WaitApiMessage,
|
||||
WaitApiMessage->Header.u1.s1.TotalLength);
|
||||
|
||||
/* Return the block */
|
||||
*NewWaitBlock = WaitBlock;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrNotifyWaitBlock
|
||||
*
|
||||
* The CsrNotifyWaitBlock routine calls the wait function for a registered
|
||||
* CSR Wait Block, and replies to the attached CSR API Message, if any.
|
||||
*
|
||||
* @param WaitBlock
|
||||
* Pointer to the CSR Wait Block
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to the wait list for this wait.
|
||||
*
|
||||
* @param WaitArgument[1-2]
|
||||
* User-defined values to pass to the wait function.
|
||||
*
|
||||
* @param WaitFlags
|
||||
* Wait flags for this wait.
|
||||
*
|
||||
* @param DereferenceThread
|
||||
* Specifies whether the CSR Thread should be dereferenced at the
|
||||
* end of this wait.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks After a wait block is notified, the wait function becomes invalid.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock,
|
||||
IN PLIST_ENTRY WaitList,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags,
|
||||
IN BOOLEAN DereferenceThread)
|
||||
{
|
||||
/* Call the wait function */
|
||||
if ((WaitBlock->WaitFunction)(WaitList,
|
||||
WaitBlock->WaitThread,
|
||||
&WaitBlock->WaitApiMessage,
|
||||
WaitBlock->WaitContext,
|
||||
WaitArgument1,
|
||||
WaitArgument2,
|
||||
WaitFlags))
|
||||
{
|
||||
/* The wait is done, clear the block */
|
||||
WaitBlock->WaitThread->WaitBlock = NULL;
|
||||
|
||||
/* Check for captured arguments */
|
||||
if (WaitBlock->WaitApiMessage.CsrCaptureData)
|
||||
{
|
||||
/* Release them */
|
||||
CsrReleaseCapturedArguments(&WaitBlock->WaitApiMessage);
|
||||
}
|
||||
|
||||
/* Reply to the port */
|
||||
NtReplyPort(WaitBlock->WaitThread->Process->ClientPort,
|
||||
(PPORT_MESSAGE)&WaitBlock->WaitApiMessage);
|
||||
|
||||
/* Check if we should dereference the thread */
|
||||
if (DereferenceThread)
|
||||
{
|
||||
/* Remove it from the Wait List */
|
||||
if (WaitBlock->WaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->WaitList);
|
||||
}
|
||||
|
||||
/* Remove it from the User Wait List */
|
||||
if (WaitBlock->UserWaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->UserWaitList);
|
||||
}
|
||||
|
||||
/* Dereference teh thread */
|
||||
CsrDereferenceThread(WaitBlock->WaitThread);
|
||||
|
||||
/* Free the wait block */
|
||||
RtlFreeHeap(CsrHeap, 0, WaitBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wait is complete, but the thread is being kept alive */
|
||||
WaitBlock->WaitFunction = NULL;
|
||||
}
|
||||
|
||||
/* The wait suceeded */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The wait failed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrCreateWait
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrCreateWait routine creates a CSR Wait.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to a list entry of the waits to associate.
|
||||
*
|
||||
* @param WaitFunction
|
||||
* Pointer to the function that will handle this wait.
|
||||
*
|
||||
* @param CsrWaitThread
|
||||
* Pointer to the CSR Thread that will perform the wait.
|
||||
*
|
||||
* @param WaitApiMessage
|
||||
* Pointer to the CSR API Message associated to this wait.
|
||||
*
|
||||
* @param WaitContext
|
||||
* Pointer to a user-defined parameter associated to this wait.
|
||||
*
|
||||
* @param UserWaitList
|
||||
* Pointer to a list entry of the user-defined waits to associate.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrCreateWait(IN PLIST_ENTRY WaitList,
|
||||
IN CSR_WAIT_FUNCTION WaitFunction,
|
||||
IN PCSR_THREAD CsrWaitThread,
|
||||
IN OUT PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PLIST_ENTRY UserWaitList OPTIONAL)
|
||||
{
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Initialize the wait */
|
||||
if (!CsrInitializeWait(WaitFunction,
|
||||
CsrWaitThread,
|
||||
WaitApiMessage,
|
||||
WaitContext,
|
||||
&WaitBlock))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Make sure the thread wasn't destroyed */
|
||||
if (CsrWaitThread->Flags & CsrThreadTerminated)
|
||||
{
|
||||
/* Fail the wait */
|
||||
RtlFreeHeap(CsrHeap, 0, WaitBlock);
|
||||
CsrReleaseWaitLock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Insert the wait in the queue */
|
||||
InsertTailList(WaitList, &WaitBlock->WaitList);
|
||||
|
||||
/* Insert the User Wait too, if one was given */
|
||||
if (UserWaitList) InsertTailList(UserWaitList, &WaitBlock->UserWaitList);
|
||||
|
||||
/* Return */
|
||||
CsrReleaseWaitLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDereferenceWait
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrDereferenceWait routine derefences a CSR Wait Block.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to the Wait List associated to the wait.
|
||||
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceWait(IN PLIST_ENTRY WaitList)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Acquire the Process and Wait Locks */
|
||||
CsrAcquireProcessLock();
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Set the list pointers */
|
||||
NextEntry = WaitList->Flink;
|
||||
|
||||
/* Start the loop */
|
||||
while (NextEntry != WaitList)
|
||||
{
|
||||
/* Get the wait block */
|
||||
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
|
||||
|
||||
/* Move to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
/* Check if there's no Wait Routine */
|
||||
if (!WaitBlock->WaitFunction)
|
||||
{
|
||||
/* Remove it from the Wait List */
|
||||
if (WaitBlock->WaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->WaitList);
|
||||
}
|
||||
|
||||
/* Remove it from the User Wait List */
|
||||
if (WaitBlock->UserWaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->UserWaitList);
|
||||
}
|
||||
|
||||
/* Dereference the thread waiting on it */
|
||||
CsrDereferenceThread(WaitBlock->WaitThread);
|
||||
|
||||
/* Free the block */
|
||||
RtlFreeHeap(CsrHeap, 0, WaitBlock);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the locks */
|
||||
CsrReleaseWaitLock();
|
||||
CsrReleaseProcessLock();
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrMoveSatisfiedWait
|
||||
* @implemented NT5
|
||||
*
|
||||
* The CsrMoveSatisfiedWait routine moves satisfied waits from a wait list
|
||||
* to another list entry.
|
||||
*
|
||||
* @param NewEntry
|
||||
* Pointer to a list entry where the satisfied waits will be added.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to a list entry to analyze for satisfied waits.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrMoveSatisfiedWait(IN PLIST_ENTRY NewEntry,
|
||||
IN PLIST_ENTRY WaitList)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Set the List pointers */
|
||||
NextEntry = WaitList->Flink;
|
||||
|
||||
/* Start looping */
|
||||
while (NextEntry != WaitList)
|
||||
{
|
||||
/* Get the Wait block */
|
||||
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
|
||||
|
||||
/* Go to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
/* Check if there is a Wait Callback */
|
||||
if (WaitBlock->WaitFunction)
|
||||
{
|
||||
/* Remove it from the Wait Block Queue */
|
||||
RemoveEntryList(&WaitBlock->WaitList);
|
||||
|
||||
/* Insert the new entry */
|
||||
InsertTailList(&WaitBlock->WaitList, NewEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the wait lock */
|
||||
CsrReleaseWaitLock();
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrNotifyWait
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrNotifyWait notifies a CSR Wait Block.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to the list entry for this wait.
|
||||
*
|
||||
* @param WaitType
|
||||
* Type of the wait to perform, either WaitAny or WaitAll.
|
||||
*
|
||||
* @param WaitArgument[1-2]
|
||||
* User-defined argument to pass on to the wait function.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE othwerwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrNotifyWait(IN PLIST_ENTRY WaitList,
|
||||
IN ULONG WaitType,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
BOOLEAN NotifySuccess = FALSE;
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Set the List pointers */
|
||||
NextEntry = WaitList->Flink;
|
||||
|
||||
/* Start looping */
|
||||
while (NextEntry != WaitList)
|
||||
{
|
||||
/* Get the Wait block */
|
||||
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
|
||||
|
||||
/* Go to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
/* Check if there is a Wait Callback */
|
||||
if (WaitBlock->WaitFunction)
|
||||
{
|
||||
/* Notify the Waiter */
|
||||
NotifySuccess |= CsrNotifyWaitBlock(WaitBlock,
|
||||
WaitList,
|
||||
WaitArgument1,
|
||||
WaitArgument2,
|
||||
0,
|
||||
FALSE);
|
||||
|
||||
/* We've already done a wait, so leave unless this is a Wait All */
|
||||
if (WaitType != WaitAll) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the wait lock and return */
|
||||
CsrReleaseWaitLock();
|
||||
return NotifySuccess;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsys/csr/csrss.c
|
||||
* PURPOSE: CSR Executable
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/ntndk.h>
|
||||
#include <csr/server.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrpSetDefaultProcessHardErrorMode (VOID)
|
||||
{
|
||||
ULONG DefaultHardErrorMode = 0;
|
||||
|
||||
/* Disable hard errors */
|
||||
NtSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessDefaultHardErrorMode,
|
||||
&DefaultHardErrorMode,
|
||||
sizeof(DefaultHardErrorMode));
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: Standard entrypoint for Native C Programs.
|
||||
* The OS backend (NtProcessStartup) which calls this routine is
|
||||
* implemented in a CRT-like static library (much like mainCRTStartup).
|
||||
* Do NOT manually add the NtProcessStartup entrypoint or anything else.
|
||||
*/
|
||||
int
|
||||
_cdecl
|
||||
_main(int argc,
|
||||
char *argv[],
|
||||
char *envp[],
|
||||
int DebugFlag)
|
||||
{
|
||||
KPRIORITY BasePriority = (8 + 1) + 4;
|
||||
NTSTATUS Status;
|
||||
ULONG Response;
|
||||
UNREFERENCED_PARAMETER(envp);
|
||||
UNREFERENCED_PARAMETER(DebugFlag);
|
||||
|
||||
/* Set the Priority */
|
||||
NtSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessBasePriority,
|
||||
&BasePriority,
|
||||
sizeof(KPRIORITY));
|
||||
|
||||
/* Give us IOPL so that we can access the VGA registers */
|
||||
Status = NtSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessUserModeIOPL,
|
||||
NULL,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Raise a hard error */
|
||||
DPRINT1("CSRSS: Could not raise IOPL: %x\n", Status);
|
||||
Status = NtRaiseHardError(STATUS_IO_PRIVILEGE_FAILED,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
OptionOk,
|
||||
&Response);
|
||||
}
|
||||
|
||||
/* Initialize CSR through CSRSRV */
|
||||
Status = CsrServerInitialization(argc, argv);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Kill us */
|
||||
DPRINT1("CSRSS: CsrServerInitialization failed:% lx\n", Status);
|
||||
NtTerminateProcess(NtCurrentProcess(), Status);
|
||||
}
|
||||
|
||||
/* Disable errors */
|
||||
CsrpSetDefaultProcessHardErrorMode();
|
||||
|
||||
/* If this is Session 0, make sure killing us bugchecks the system */
|
||||
if (!NtCurrentPeb()->SessionId) RtlSetProcessIsCritical(TRUE, NULL, FALSE);
|
||||
|
||||
/* Kill this thread. CSRSRV keeps us going */
|
||||
NtTerminateThread(NtCurrentThread(), Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/subsystems/win32/csrss/include)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
|
||||
|
||||
spec2def(csrsrv.dll csrsrv.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
api/process.c
|
||||
api/user.c
|
||||
api/wapi.c
|
||||
procsup.c
|
||||
thredsup.c
|
||||
init.c
|
||||
wait.c
|
||||
session.c
|
||||
server.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/csrsrv.def)
|
||||
|
||||
add_library(csrsrv SHARED ${SOURCE})
|
||||
|
||||
target_link_libraries(csrsrv ${PSEH_LIB} smlib)
|
||||
|
||||
set_module_type(csrsrv nativedll)
|
||||
|
||||
add_importlibs(csrsrv ntdll smdll)
|
||||
|
||||
add_pch(csrsrv srv.h)
|
||||
|
||||
add_dependencies(csrsrv psdk bugcodes)
|
||||
add_cd_file(TARGET csrsrv DESTINATION reactos/system32 FOR all)
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* subsystems/win32/csrss/csrsrv/api/process.c
|
||||
*
|
||||
* "\windows\ApiPort" port process management functions
|
||||
*
|
||||
* ReactOS Operating System
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <srv.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
extern NTSTATUS CallProcessCreated(PCSR_PROCESS, PCSR_PROCESS);
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* CSRSS API
|
||||
*********************************************************************/
|
||||
|
||||
CSR_API(CsrSrvCreateProcess)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE ProcessHandle, ThreadHandle;
|
||||
PCSR_THREAD CsrThread;
|
||||
PCSR_PROCESS NewProcessData;
|
||||
ULONG Flags, VdmPower = 0, DebugFlags = 0;
|
||||
|
||||
/* Get the current client thread */
|
||||
CsrThread = NtCurrentTeb()->CsrClientThread;
|
||||
ASSERT(CsrThread != NULL);
|
||||
|
||||
/* Extract the flags out of the process handle */
|
||||
Flags = (ULONG_PTR)Request->Data.CreateProcessRequest.ProcessHandle & 3;
|
||||
Request->Data.CreateProcessRequest.ProcessHandle = (HANDLE)((ULONG_PTR)Request->Data.CreateProcessRequest.ProcessHandle & ~3);
|
||||
|
||||
/* Duplicate the process handle */
|
||||
Status = NtDuplicateObject(CsrThread->Process->ProcessHandle,
|
||||
Request->Data.CreateProcessRequest.ProcessHandle,
|
||||
NtCurrentProcess(),
|
||||
&ProcessHandle,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to duplicate process handle\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Duplicate the thread handle */
|
||||
Status = NtDuplicateObject(CsrThread->Process->ProcessHandle,
|
||||
Request->Data.CreateProcessRequest.ThreadHandle,
|
||||
NtCurrentProcess(),
|
||||
&ThreadHandle,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to duplicate process handle\n");
|
||||
NtClose(ProcessHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* See if this is a VDM process */
|
||||
if (VdmPower)
|
||||
{
|
||||
/* Request VDM powers */
|
||||
Status = NtSetInformationProcess(ProcessHandle,
|
||||
ProcessWx86Information,
|
||||
&VdmPower,
|
||||
sizeof(VdmPower));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get VDM powers\n");
|
||||
NtClose(ProcessHandle);
|
||||
NtClose(ThreadHandle);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert some flags. FIXME: More need conversion */
|
||||
if (Request->Data.CreateProcessRequest.CreationFlags & CREATE_NEW_PROCESS_GROUP)
|
||||
{
|
||||
DebugFlags |= CsrProcessCreateNewGroup;
|
||||
}
|
||||
|
||||
/* FIXME: SxS Stuff */
|
||||
|
||||
/* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
|
||||
Status = CsrCreateProcess(ProcessHandle,
|
||||
ThreadHandle,
|
||||
&Request->Data.CreateProcessRequest.ClientId,
|
||||
CsrThread->Process->NtSession,
|
||||
DebugFlags,
|
||||
NULL);
|
||||
if (Status == STATUS_THREAD_IS_TERMINATING)
|
||||
{
|
||||
DPRINT1("Thread already dead\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check for other failures */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to create process/thread structures: %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* FIXME: Should notify user32 */
|
||||
|
||||
/* FIXME: VDM vodoo */
|
||||
|
||||
/* ReactOS Compatibility */
|
||||
Status = CsrLockProcessByClientId(Request->Data.CreateProcessRequest.ClientId.UniqueProcess, &NewProcessData);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
if (!(Request->Data.CreateProcessRequest.CreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
|
||||
{
|
||||
NewProcessData->ParentConsole = ProcessData->Console;
|
||||
NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
|
||||
}
|
||||
RtlInitializeCriticalSection(&NewProcessData->HandleTableLock);
|
||||
CallProcessCreated(ProcessData, NewProcessData);
|
||||
CsrUnlockProcess(NewProcessData);
|
||||
|
||||
/* Return the result of this operation */
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrSrvCreateThread)
|
||||
{
|
||||
PCSR_THREAD CurrentThread;
|
||||
HANDLE ThreadHandle;
|
||||
NTSTATUS Status;
|
||||
PCSR_PROCESS CsrProcess;
|
||||
|
||||
/* Get the current CSR thread */
|
||||
CurrentThread = NtCurrentTeb()->CsrClientThread;
|
||||
if (!CurrentThread)
|
||||
{
|
||||
DPRINT1("Server Thread TID: [%lx.%lx]\n",
|
||||
Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
|
||||
Request->Data.CreateThreadRequest.ClientId.UniqueThread);
|
||||
return STATUS_SUCCESS; // server-to-server
|
||||
}
|
||||
|
||||
/* Get the CSR Process for this request */
|
||||
CsrProcess = CurrentThread->Process;
|
||||
if (CsrProcess->ClientId.UniqueProcess !=
|
||||
Request->Data.CreateThreadRequest.ClientId.UniqueProcess)
|
||||
{
|
||||
/* This is a remote thread request -- is it within the server itself? */
|
||||
if (Request->Data.CreateThreadRequest.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
|
||||
{
|
||||
/* Accept this without any further work */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the real CSR Process for the remote thread's process */
|
||||
Status = CsrLockProcessByClientId(Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
|
||||
&CsrProcess);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Duplicate the thread handle so we can own it */
|
||||
Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle,
|
||||
Request->Data.CreateThreadRequest.ThreadHandle,
|
||||
NtCurrentProcess(),
|
||||
&ThreadHandle,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Call CSRSRV to tell it about the new thread */
|
||||
Status = CsrCreateThread(CsrProcess,
|
||||
ThreadHandle,
|
||||
&Request->Data.CreateThreadRequest.ClientId);
|
||||
}
|
||||
|
||||
/* Unlock the process and return */
|
||||
if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrTerminateProcess)
|
||||
{
|
||||
PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
|
||||
ASSERT(CsrThread != NULL);
|
||||
|
||||
/* Set magic flag so we don't reply this message back */
|
||||
Request->Type = 0xBABE;
|
||||
|
||||
/* Remove the CSR_THREADs and CSR_PROCESS */
|
||||
return CsrDestroyProcess(&CsrThread->ClientId,
|
||||
(NTSTATUS)Request->Data.TerminateProcessRequest.uExitCode);
|
||||
}
|
||||
|
||||
CSR_API(CsrConnectProcess)
|
||||
{
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
CSR_API(CsrGetShutdownParameters)
|
||||
{
|
||||
|
||||
Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
|
||||
Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
CSR_API(CsrSetShutdownParameters)
|
||||
{
|
||||
|
||||
ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
|
||||
ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* subsystems/win32/csrss/csrsrv/api/user.c
|
||||
*
|
||||
* User functions
|
||||
*
|
||||
* ReactOS Operating System
|
||||
*
|
||||
* PROGRAMMER: Eric Kohl
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <srv.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
static BOOLEAN ServicesProcessIdValid = FALSE;
|
||||
static ULONG_PTR ServicesProcessId;
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
CSR_API(CsrRegisterServicesProcess)
|
||||
{
|
||||
if (ServicesProcessIdValid == TRUE)
|
||||
{
|
||||
/* Only accept a single call */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
ServicesProcessId = (ULONG_PTR)Request->Data.RegisterServicesProcessRequest.ProcessId;
|
||||
ServicesProcessIdValid = TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Client/Server Runtime SubSystem Process\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "csrsrv\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "csrsrv.dll\0"
|
||||
#include <reactos/version.rc>
|
||||
@@ -0,0 +1,36 @@
|
||||
@ stdcall CsrAddStaticServerThread(ptr ptr long)
|
||||
@ stdcall CsrCallServerFromServer(ptr ptr)
|
||||
;@ stdcall CsrConnectToUser()
|
||||
;@ stdcall CsrCreateProcess(ptr ptr ptr ptr long ptr)
|
||||
@ stdcall CsrCreateRemoteThread(ptr ptr)
|
||||
@ stdcall CsrCreateThread(ptr ptr ptr)
|
||||
;@ stdcall CsrCreateWait(ptr ptr ptr ptr ptr ptr)
|
||||
;@ stdcall CsrDebugProcess(ptr)
|
||||
;@ stdcall CsrDebugProcessStop(ptr)
|
||||
;@ stdcall CsrDereferenceProcess(ptr)
|
||||
;@ stdcall CsrDereferenceThread(ptr)
|
||||
;@ stdcall CsrDereferenceWait(ptr)
|
||||
;@ stdcall CsrDestroyProcess(ptr long)
|
||||
;@ stdcall CsrDestroyThread(ptr)
|
||||
@ stdcall CsrEnumProcesses(ptr ptr) ; Temporary hack
|
||||
;@ stdcall CsrExecServerThread(ptr long)
|
||||
@ stdcall CsrGetProcessLuid(ptr ptr)
|
||||
@ stdcall CsrImpersonateClient(ptr)
|
||||
@ stdcall CsrLockProcessByClientId(ptr ptr)
|
||||
;@ stdcall CsrLockThreadByClientId(ptr ptr)
|
||||
;@ stdcall CsrMoveSatisfiedWait(ptr ptr)
|
||||
;@ stdcall CsrNotifyWait(ptr long ptr ptr)
|
||||
;@ stdcall CsrPopulateDosDevices()
|
||||
;@ stdcall CsrQueryApiPort()
|
||||
;@ stdcall CsrReferenceThread(ptr)
|
||||
@ stdcall CsrRevertToSelf()
|
||||
@ stdcall CsrServerInitialization(long ptr)
|
||||
;@ stdcall CsrSetBackgroundPriority(ptr)
|
||||
;@ stdcall CsrSetCallingSpooler(long)
|
||||
;@ stdcall CsrSetForegroundPriority(ptr)
|
||||
;@ stdcall CsrShutdownProcesses(ptr long)
|
||||
;@ stdcall CsrUnhandledExceptionFilter(ptr)
|
||||
@ stdcall CsrUnlockProcess(ptr)
|
||||
;@ stdcall CsrUnlockThread(ptr)
|
||||
;@ stdcall CsrValidateMessageBuffer(ptr ptr long long)
|
||||
;@ stdcall CsrValidateMessageString(ptr ptr)
|
||||
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/include/api.h
|
||||
* PURPOSE: CSRSS API interface
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/psfuncs.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
|
||||
#include <csrss/csrss.h>
|
||||
|
||||
#define CSR_SRV_SERVER 0
|
||||
#define CSR_SERVER_DLL_MAX 4
|
||||
#define LOCK RtlEnterCriticalSection(&ProcessDataLock)
|
||||
#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
|
||||
#define CsrAcquireProcessLock() LOCK
|
||||
#define CsrReleaseProcessLock() UNLOCK
|
||||
#define ProcessStructureListLocked() \
|
||||
(ProcessDataLock.OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
|
||||
|
||||
#define CsrAcquireWaitLock() \
|
||||
RtlEnterCriticalSection(&CsrWaitListsLock);
|
||||
|
||||
#define CsrReleaseWaitLock() \
|
||||
RtlLeaveCriticalSection(&CsrWaitListsLock);
|
||||
|
||||
#define CsrAcquireNtSessionLock() \
|
||||
RtlEnterCriticalSection(&CsrNtSessionLock);
|
||||
|
||||
#define CsrReleaseNtSessionLock() \
|
||||
RtlLeaveCriticalSection(&CsrNtSessionLock);
|
||||
|
||||
typedef enum _CSR_THREAD_FLAGS
|
||||
{
|
||||
CsrThreadAltertable = 0x1,
|
||||
CsrThreadInTermination = 0x2,
|
||||
CsrThreadTerminated = 0x4,
|
||||
CsrThreadIsServerThread = 0x10
|
||||
} CSR_THREAD_FLAGS, *PCSR_THREAD_FLAGS;
|
||||
|
||||
typedef enum _SHUTDOWN_RESULT
|
||||
{
|
||||
CsrShutdownCsrProcess = 1,
|
||||
CsrShutdownNonCsrProcess,
|
||||
CsrShutdownCancelled
|
||||
} SHUTDOWN_RESULT, *PSHUTDOWN_RESULT;
|
||||
|
||||
typedef enum _CSR_SHUTDOWN_FLAGS
|
||||
{
|
||||
CsrShutdownSystem = 4,
|
||||
CsrShutdownOther = 8
|
||||
} CSR_SHUTDOWN_FLAGS, *PCSR_SHUTDOWN_FLAGS;
|
||||
|
||||
typedef enum _CSR_DEBUG_FLAGS
|
||||
{
|
||||
CsrDebugOnlyThisProcess = 1,
|
||||
CsrDebugProcessChildren = 2
|
||||
} CSR_PROCESS_DEBUG_FLAGS, *PCSR_PROCESS_DEBUG_FLAGS;
|
||||
|
||||
typedef enum _CSR_PROCESS_FLAGS
|
||||
{
|
||||
CsrProcessTerminating = 0x1,
|
||||
CsrProcessSkipShutdown = 0x2,
|
||||
CsrProcessNormalPriority = 0x10,
|
||||
CsrProcessIdlePriority = 0x20,
|
||||
CsrProcessHighPriority = 0x40,
|
||||
CsrProcessRealtimePriority = 0x80,
|
||||
CsrProcessCreateNewGroup = 0x100,
|
||||
CsrProcessTerminated = 0x200,
|
||||
CsrProcessLastThreadTerminated = 0x400,
|
||||
CsrProcessIsConsoleApp = 0x800
|
||||
} CSR_PROCESS_FLAGS, *PCSR_PROCESS_FLAGS;
|
||||
|
||||
#define CsrProcessPriorityFlags (CsrProcessNormalPriority | \
|
||||
CsrProcessIdlePriority | \
|
||||
CsrProcessHighPriority | \
|
||||
CsrProcessRealtimePriority)
|
||||
|
||||
typedef struct _CSRSS_CON_PROCESS_DATA
|
||||
{
|
||||
HANDLE ConsoleEvent;
|
||||
struct tagCSRSS_CONSOLE *Console;
|
||||
struct tagCSRSS_CONSOLE *ParentConsole;
|
||||
BOOL bInheritHandles;
|
||||
RTL_CRITICAL_SECTION HandleTableLock;
|
||||
ULONG HandleTableSize;
|
||||
struct _CSRSS_HANDLE *HandleTable;
|
||||
PCONTROLDISPATCHER CtrlDispatcher;
|
||||
LIST_ENTRY ConsoleLink;
|
||||
} CSRSS_CON_PROCESS_DATA, *PCSRSS_CON_PROCESS_DATA;
|
||||
|
||||
typedef struct _CSR_NT_SESSION
|
||||
{
|
||||
ULONG ReferenceCount;
|
||||
LIST_ENTRY SessionLink;
|
||||
ULONG SessionId;
|
||||
} CSR_NT_SESSION, *PCSR_NT_SESSION;
|
||||
|
||||
typedef struct _CSR_PROCESS
|
||||
{
|
||||
CLIENT_ID ClientId;
|
||||
LIST_ENTRY ListLink;
|
||||
LIST_ENTRY ThreadList;
|
||||
struct _CSR_PROCESS *Parent;
|
||||
PCSR_NT_SESSION NtSession;
|
||||
ULONG ExpectedVersion;
|
||||
HANDLE ClientPort;
|
||||
ULONG_PTR ClientViewBase;
|
||||
ULONG_PTR ClientViewBounds;
|
||||
HANDLE ProcessHandle;
|
||||
ULONG SequenceNumber;
|
||||
ULONG Flags;
|
||||
ULONG DebugFlags;
|
||||
CLIENT_ID DebugCid;
|
||||
ULONG ReferenceCount;
|
||||
ULONG ProcessGroupId;
|
||||
ULONG ProcessGroupSequence;
|
||||
ULONG fVDM;
|
||||
ULONG ThreadCount;
|
||||
ULONG PriorityClass;
|
||||
ULONG Reserved;
|
||||
ULONG ShutdownLevel;
|
||||
ULONG ShutdownFlags;
|
||||
// PVOID ServerData[ANYSIZE_ARRAY];
|
||||
CSRSS_CON_PROCESS_DATA;
|
||||
} CSR_PROCESS, *PCSR_PROCESS;
|
||||
|
||||
typedef struct _CSR_THREAD
|
||||
{
|
||||
LARGE_INTEGER CreateTime;
|
||||
LIST_ENTRY Link;
|
||||
LIST_ENTRY HashLinks;
|
||||
CLIENT_ID ClientId;
|
||||
PCSR_PROCESS Process;
|
||||
struct _CSR_WAIT_BLOCK *WaitBlock;
|
||||
HANDLE ThreadHandle;
|
||||
ULONG Flags;
|
||||
ULONG ReferenceCount;
|
||||
ULONG ImpersonationCount;
|
||||
} CSR_THREAD, *PCSR_THREAD;
|
||||
|
||||
typedef
|
||||
BOOLEAN
|
||||
(*CSR_WAIT_FUNCTION)(
|
||||
IN PLIST_ENTRY WaitList,
|
||||
IN PCSR_THREAD WaitThread,
|
||||
IN PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags
|
||||
);
|
||||
|
||||
typedef struct _CSR_WAIT_BLOCK
|
||||
{
|
||||
ULONG Size;
|
||||
LIST_ENTRY WaitList;
|
||||
LIST_ENTRY UserWaitList;
|
||||
PVOID WaitContext;
|
||||
PCSR_THREAD WaitThread;
|
||||
CSR_WAIT_FUNCTION WaitFunction;
|
||||
CSR_API_MESSAGE WaitApiMessage;
|
||||
} CSR_WAIT_BLOCK, *PCSR_WAIT_BLOCK;
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(NTAPI *PCSR_CONNECT_CALLBACK)(
|
||||
IN PCSR_PROCESS CsrProcess,
|
||||
IN OUT PVOID ConnectionInfo,
|
||||
IN OUT PULONG ConnectionInfoLength
|
||||
);
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(NTAPI *PCSR_DISCONNECT_CALLBACK)(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(NTAPI *PCSR_NEWPROCESS_CALLBACK)(
|
||||
IN PCSR_PROCESS Parent,
|
||||
IN PCSR_PROCESS CsrProcess
|
||||
);
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(NTAPI *PCSR_HARDERROR_CALLBACK)(
|
||||
IN PCSR_THREAD CsrThread,
|
||||
IN PHARDERROR_MSG HardErrorMessage
|
||||
);
|
||||
|
||||
typedef
|
||||
ULONG
|
||||
(NTAPI *PCSR_SHUTDOWNPROCESS_CALLBACK)(
|
||||
IN PCSR_PROCESS CsrProcess,
|
||||
IN ULONG Flags,
|
||||
IN BOOLEAN FirstPhase
|
||||
);
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(NTAPI *PCSR_API_ROUTINE)(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
typedef struct _CSR_SERVER_DLL
|
||||
{
|
||||
ULONG Length;
|
||||
HANDLE Event;
|
||||
ANSI_STRING Name;
|
||||
HANDLE ServerHandle;
|
||||
ULONG ServerId;
|
||||
ULONG Unknown;
|
||||
ULONG ApiBase;
|
||||
ULONG HighestApiSupported;
|
||||
PCSR_API_ROUTINE *DispatchTable;
|
||||
PBOOLEAN ValidTable;
|
||||
PCHAR *NameTable;
|
||||
ULONG SizeOfProcessData;
|
||||
PCSR_CONNECT_CALLBACK ConnectCallback;
|
||||
PCSR_DISCONNECT_CALLBACK DisconnectCallback;
|
||||
PCSR_HARDERROR_CALLBACK HardErrorCallback;
|
||||
PVOID SharedSection;
|
||||
PCSR_NEWPROCESS_CALLBACK NewProcessCallback;
|
||||
PCSR_SHUTDOWNPROCESS_CALLBACK ShutdownProcessCallback;
|
||||
ULONG Unknown2[3];
|
||||
} CSR_SERVER_DLL, *PCSR_SERVER_DLL;
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(NTAPI *PCSR_SERVER_DLL_INIT_CALLBACK)(IN PCSR_SERVER_DLL ServerDll);
|
||||
|
||||
|
||||
typedef NTSTATUS (WINAPI *CSRSS_API_PROC)(PCSR_PROCESS ProcessData,
|
||||
PCSR_API_MESSAGE Request);
|
||||
|
||||
typedef struct _CSRSS_API_DEFINITION
|
||||
{
|
||||
ULONG Type;
|
||||
ULONG MinRequestSize;
|
||||
CSRSS_API_PROC Handler;
|
||||
} CSRSS_API_DEFINITION, *PCSRSS_API_DEFINITION;
|
||||
|
||||
#define CSRSS_DEFINE_API(Func, Handler) \
|
||||
{ Func, sizeof(CSRSS_##Func), Handler }
|
||||
|
||||
typedef struct _CSRSS_LISTEN_DATA
|
||||
{
|
||||
HANDLE ApiPortHandle;
|
||||
ULONG ApiDefinitionsCount;
|
||||
PCSRSS_API_DEFINITION *ApiDefinitions;
|
||||
} CSRSS_LISTEN_DATA, *PCSRSS_LISTEN_DATA;
|
||||
|
||||
#define CSR_API(n) NTSTATUS WINAPI n ( \
|
||||
PCSR_PROCESS ProcessData, \
|
||||
PCSR_API_MESSAGE Request)
|
||||
|
||||
/* init.c */
|
||||
extern HANDLE hBootstrapOk;
|
||||
NTSTATUS NTAPI CsrServerInitialization(ULONG ArgumentCount, PCHAR Arguments[]);
|
||||
|
||||
/* api/process.c */
|
||||
CSR_API(CsrConnectProcess);
|
||||
CSR_API(CsrSrvCreateProcess);
|
||||
CSR_API(CsrTerminateProcess);
|
||||
CSR_API(CsrSrvCreateThread);
|
||||
CSR_API(CsrGetShutdownParameters);
|
||||
CSR_API(CsrSetShutdownParameters);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrAllocateThread(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
PCSR_PROCESS
|
||||
NTAPI
|
||||
CsrAllocateProcess(VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrRemoveProcess(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceThread(IN PCSR_THREAD CsrThread);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
|
||||
IN PCSR_PROCESS CurrentProcess OPTIONAL,
|
||||
IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
|
||||
/* api/wapi.c */
|
||||
NTSTATUS FASTCALL CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions);
|
||||
VOID FASTCALL CsrApiCallHandler(PCSR_PROCESS ProcessData,
|
||||
PCSR_API_MESSAGE Request);
|
||||
VOID WINAPI CsrSbApiRequestThread (PVOID PortHandle);
|
||||
VOID NTAPI ClientConnectionThread(HANDLE ServerPort);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage);
|
||||
|
||||
extern HANDLE CsrApiPort;
|
||||
extern HANDLE CsrSmApiPort;
|
||||
extern HANDLE CsrSbApiPort;
|
||||
extern LIST_ENTRY CsrThreadHashTable[256];
|
||||
extern PCSR_PROCESS CsrRootProcess;
|
||||
extern RTL_CRITICAL_SECTION ProcessDataLock, CsrWaitListsLock;
|
||||
extern UNICODE_STRING CsrDirectoryName;
|
||||
extern ULONG CsrDebug;
|
||||
extern ULONG CsrTotalPerProcessDataLength;
|
||||
extern SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
|
||||
extern PVOID CsrSrvSharedSectionHeap;
|
||||
extern PVOID *CsrSrvSharedStaticServerData;
|
||||
extern HANDLE CsrInitializationEvent;
|
||||
extern PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
|
||||
extern ULONG CsrMaxApiRequestThreads;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrApiPortInitialize(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateProcess(IN HANDLE hProcess,
|
||||
IN HANDLE hThread,
|
||||
IN PCLIENT_ID ClientId,
|
||||
IN PCSR_NT_SESSION NtSession,
|
||||
IN ULONG Flags,
|
||||
IN PCLIENT_ID DebugCid);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ProtectHandle(IN HANDLE ObjectHandle);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrInsertThread(IN PCSR_PROCESS Process,
|
||||
IN PCSR_THREAD Thread);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedReferenceThread(IN PCSR_THREAD CsrThread);
|
||||
|
||||
/* api/process.c */
|
||||
typedef NTSTATUS (WINAPI *CSRSS_ENUM_PROCESS_PROC)(PCSR_PROCESS ProcessData,
|
||||
PVOID Context);
|
||||
NTSTATUS WINAPI CsrInitializeProcessStructure(VOID);
|
||||
|
||||
NTSTATUS WINAPI CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context);
|
||||
PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN ULONG ThreadFlags);
|
||||
PCSR_THREAD NTAPI CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL, IN PCLIENT_ID Cid);
|
||||
PCSR_THREAD NTAPI CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL, IN PCLIENT_ID ClientId);
|
||||
NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess OPTIONAL);
|
||||
NTSTATUS NTAPI CsrCreateThread(IN PCSR_PROCESS CsrProcess, IN HANDLE hThread, IN PCLIENT_ID ClientId);
|
||||
NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
//hack
|
||||
VOID NTAPI CsrThreadRefcountZero(IN PCSR_THREAD CsrThread);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrInitializeNtSessionList(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,
|
||||
OUT PCSR_CONNECTION_INFO ConnectInfo);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvCreateSharedSection(IN PCHAR ParameterValue);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvClientConnect(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvUnusedFunction(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvIdentifyAlertableThread(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvSetPriorityClass(
|
||||
IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrDestroyProcess(IN PCLIENT_ID Cid,
|
||||
IN NTSTATUS ExitStatus);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrDestroyThread(IN PCLIENT_ID Cid);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock,
|
||||
IN PLIST_ENTRY WaitList,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags,
|
||||
IN BOOLEAN DereferenceThread);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrReferenceNtSession(IN PCSR_NT_SESSION Session);
|
||||
|
||||
LONG
|
||||
NTAPI
|
||||
CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceNtSession(IN PCSR_NT_SESSION Session,
|
||||
IN NTSTATUS ExitStatus);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrLoadServerDll(IN PCHAR DllString,
|
||||
IN PCHAR EntryPoint OPTIONAL,
|
||||
IN ULONG ServerId);
|
||||
|
||||
/* api/user.c */
|
||||
CSR_API(CsrRegisterServicesProcess);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/include/csrplugin.h
|
||||
* PURPOSE: CSRSS plugin interface
|
||||
*/
|
||||
|
||||
/*
|
||||
* CSRSS is a native application and can only implicitly link against native
|
||||
* DLLs. Since e.g. user32.dll and gdi32.dll are win32 DLLs and not native
|
||||
* DLLs it is not possible to call functions in those DLLs directly from
|
||||
* CSRSS.
|
||||
* However, it is possible to explicitly load a non-native DLL. Such a DLL
|
||||
* can then in turn be implicitly linked against other DLLs in its own
|
||||
* subsystem.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api.h"
|
||||
|
||||
typedef NTSTATUS (WINAPI *CSRSS_ENUM_PROCESSES_PROC)(CSRSS_ENUM_PROCESS_PROC EnumProc,
|
||||
PVOID Context);
|
||||
|
||||
typedef struct tagCSRSS_EXPORTED_FUNCS
|
||||
{
|
||||
CSRSS_ENUM_PROCESSES_PROC CsrEnumProcessesProc;
|
||||
} CSRSS_EXPORTED_FUNCS, *PCSRSS_EXPORTED_FUNCS;
|
||||
|
||||
typedef BOOL (WINAPI *CSRPLUGIN_INIT_COMPLETE_PROC)(void);
|
||||
|
||||
typedef VOID (WINAPI *CSRPLUGIN_HARDERROR_PROC)(IN PCSR_THREAD ThreadData,
|
||||
IN PHARDERROR_MSG HardErrorMessage);
|
||||
|
||||
typedef NTSTATUS (WINAPI *CSRPLUGIN_PROCESS_INHERIT_PROC)(IN PCSR_PROCESS SourceProcessData,
|
||||
IN PCSR_PROCESS TargetProcessData);
|
||||
|
||||
typedef ULONG (WINAPI *CSRPLUGIN_PROCESS_DELETED_PROC)(IN PCSR_PROCESS ProcessData, IN ULONG Unused, IN BOOLEAN Flag);
|
||||
|
||||
typedef struct tagCSRSS_SERVER_PROCS
|
||||
{
|
||||
CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc;
|
||||
CSRPLUGIN_HARDERROR_PROC HardErrorProc;
|
||||
CSRPLUGIN_PROCESS_INHERIT_PROC ProcessInheritProc;
|
||||
CSRPLUGIN_PROCESS_DELETED_PROC ProcessDeletedProc;
|
||||
} CSRPLUGIN_SERVER_PROCS, *PCSRPLUGIN_SERVER_PROCS;
|
||||
|
||||
typedef BOOL (WINAPI *CSRPLUGIN_INITIALIZE_PROC)(PCSRSS_API_DEFINITION *ApiDefinitions,
|
||||
PCSRPLUGIN_SERVER_PROCS ServerProcs);
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsystems/win32/csrss/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[5] =
|
||||
{
|
||||
CsrSrvClientConnect,
|
||||
CsrSrvUnusedFunction,
|
||||
CsrSrvUnusedFunction,
|
||||
CsrSrvIdentifyAlertableThread,
|
||||
CsrSrvSetPriorityClass
|
||||
};
|
||||
|
||||
BOOLEAN CsrServerApiServerValidTable[5] =
|
||||
{
|
||||
TRUE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE
|
||||
};
|
||||
|
||||
PCHAR CsrServerApiNameTable[5] =
|
||||
{
|
||||
"ClientConnect",
|
||||
"ThreadConnect",
|
||||
"ProfileControl",
|
||||
"IdentifyAlertableThread",
|
||||
"SetPriorityClass"
|
||||
};
|
||||
|
||||
PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
|
||||
PVOID CsrSrvSharedSectionHeap;
|
||||
PVOID CsrSrvSharedSectionBase;
|
||||
PVOID *CsrSrvSharedStaticServerData;
|
||||
ULONG CsrSrvSharedSectionSize;
|
||||
HANDLE CsrSrvSharedSection;
|
||||
|
||||
/* 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.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* 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 != CSR_SRV_SERVER)
|
||||
{
|
||||
/* 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;
|
||||
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) ? "ServerDllInitialization" :
|
||||
EntryPoint);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Check for Success */
|
||||
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;
|
||||
}
|
||||
|
||||
/* ReactOS Specific hax */
|
||||
if (ServerDll->HighestApiSupported == 0xDEADBABE)
|
||||
{
|
||||
Status = CsrApiRegisterDefinitions((PVOID)ServerDll->DispatchTable);
|
||||
}
|
||||
}
|
||||
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 Reply
|
||||
* 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.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply OPTIONAL)
|
||||
{
|
||||
/* Hack */
|
||||
return STATUS_SUCCESS;
|
||||
#if 0
|
||||
NTSTATUS Status;
|
||||
PCSR_CLIENT_CONNECT ClientConnect;
|
||||
PCSR_SERVER_DLL ServerDll;
|
||||
PCSR_PROCESS CurrentProcess = ((PCSR_THREAD)NtCurrentTeb()->CsrClientThread)->Process;
|
||||
|
||||
/* Load the Message, set default reply */
|
||||
ClientConnect = (PCSR_CLIENT_CONNECT)&ApiMessage->CsrClientConnect;
|
||||
*Reply = 0;
|
||||
|
||||
/* 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,
|
||||
1)))
|
||||
{
|
||||
/* 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;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*++
|
||||
* @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,
|
||||
0,
|
||||
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 Reply
|
||||
* Pointer to an optional reply to this request.
|
||||
*
|
||||
* @return STATUS_SUCCESS.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply)
|
||||
{
|
||||
PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
|
||||
|
||||
/* Set the alertable flag */
|
||||
CsrThread->Flags |= CsrThreadAltertable;
|
||||
|
||||
/* 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 Reply
|
||||
* Pointer to an optional reply to this request.
|
||||
*
|
||||
* @return STATUS_SUCCESS.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply)
|
||||
{
|
||||
/* 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 Reply
|
||||
* Pointer to an optional reply to this request.
|
||||
*
|
||||
* @return STATUS_INVALID_PARAMETER.
|
||||
*
|
||||
* @remarks CsrSrvSetPriorityClass does not use this stub because it must
|
||||
* return success.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||
IN OUT PULONG Reply)
|
||||
{
|
||||
/* 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.
|
||||
*
|
||||
*--*/
|
||||
LONG
|
||||
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 */
|
||||
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsystems/win32/csrss/csrsrv/session.c
|
||||
* PURPOSE: CSR Server DLL Session Implementation
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "srv.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
RTL_CRITICAL_SECTION CsrNtSessionLock;
|
||||
LIST_ENTRY CsrNtSessionList;
|
||||
|
||||
PCHAR CsrServerSbApiName[5] =
|
||||
{
|
||||
"SbCreateSession",
|
||||
"SbTerminateSession",
|
||||
"SbForeignSessionComplete",
|
||||
"SbCreateProcess",
|
||||
"Unknown Csr Sb Api Number"
|
||||
};
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrInitializeNtSessionList
|
||||
*
|
||||
* The CsrInitializeNtSessionList routine sets up support for CSR Sessions.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrInitializeNtSessionList(VOID)
|
||||
{
|
||||
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
|
||||
|
||||
/* Initialize the Session List */
|
||||
InitializeListHead(&CsrNtSessionList);
|
||||
|
||||
/* Initialize the Session Lock */
|
||||
return RtlInitializeCriticalSection(&CsrNtSessionLock);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrAllocateNtSession
|
||||
*
|
||||
* The CsrAllocateNtSession routine allocates a new CSR NT Session.
|
||||
*
|
||||
* @param SessionId
|
||||
* Session ID of the CSR NT Session to allocate.
|
||||
*
|
||||
* @return Pointer to the newly allocated CSR NT Session.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
PCSR_NT_SESSION
|
||||
NTAPI
|
||||
CsrAllocateNtSession(IN ULONG SessionId)
|
||||
{
|
||||
PCSR_NT_SESSION NtSession;
|
||||
|
||||
/* Allocate an NT Session Object */
|
||||
NtSession = RtlAllocateHeap(CsrHeap, 0, sizeof(CSR_NT_SESSION));
|
||||
if (NtSession)
|
||||
{
|
||||
/* Setup the Session Object */
|
||||
NtSession->SessionId = SessionId;
|
||||
NtSession->ReferenceCount = 1;
|
||||
|
||||
/* Insert it into the Session List */
|
||||
CsrAcquireNtSessionLock();
|
||||
InsertHeadList(&CsrNtSessionList, &NtSession->SessionLink);
|
||||
CsrReleaseNtSessionLock();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(NtSession != NULL);
|
||||
}
|
||||
|
||||
/* Return the Session (or NULL) */
|
||||
return NtSession;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrReferenceNtSession
|
||||
*
|
||||
* The CsrReferenceNtSession increases the reference count of a CSR NT Session.
|
||||
*
|
||||
* @param Session
|
||||
* Pointer to the CSR NT Session to reference.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrReferenceNtSession(IN PCSR_NT_SESSION Session)
|
||||
{
|
||||
/* Acquire the lock */
|
||||
CsrAcquireNtSessionLock();
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(!IsListEmpty(&Session->SessionLink));
|
||||
ASSERT(Session->SessionId != 0);
|
||||
ASSERT(Session->ReferenceCount != 0);
|
||||
|
||||
/* Increase the reference count */
|
||||
Session->ReferenceCount++;
|
||||
|
||||
/* Release the lock */
|
||||
CsrReleaseNtSessionLock();
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDereferenceNtSession
|
||||
*
|
||||
* The CsrDereferenceNtSession decreases the reference count of a
|
||||
* CSR NT Session.
|
||||
*
|
||||
* @param Session
|
||||
* Pointer to the CSR NT Session to reference.
|
||||
*
|
||||
* @param ExitStatus
|
||||
* If this is the last reference to the session, this argument
|
||||
* specifies the exit status.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks CsrDereferenceNtSession will complete the session if
|
||||
* the last reference to it has been closed.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceNtSession(IN PCSR_NT_SESSION Session,
|
||||
IN NTSTATUS ExitStatus)
|
||||
{
|
||||
/* Acquire the lock */
|
||||
CsrAcquireNtSessionLock();
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(!IsListEmpty(&Session->SessionLink));
|
||||
ASSERT(Session->SessionId != 0);
|
||||
ASSERT(Session->ReferenceCount != 0);
|
||||
|
||||
/* Dereference the Session Object */
|
||||
if (!(--Session->ReferenceCount))
|
||||
{
|
||||
/* Remove it from the list */
|
||||
RemoveEntryList(&Session->SessionLink);
|
||||
|
||||
/* Release the lock */
|
||||
CsrReleaseNtSessionLock();
|
||||
|
||||
/* Tell SM that we're done here */
|
||||
SmSessionComplete(CsrSmApiPort, Session->SessionId, ExitStatus);
|
||||
|
||||
/* Free the Session Object */
|
||||
RtlFreeHeap(CsrHeap, 0, Session);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Release the lock, the Session is still active */
|
||||
CsrReleaseNtSessionLock();
|
||||
}
|
||||
}
|
||||
|
||||
/* SESSION MANAGER FUNCTIONS**************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrSbCreateSession
|
||||
*
|
||||
* The CsrSbCreateSession API is called by the Session Manager whenever a new
|
||||
* session is created.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks The CsrSbCreateSession routine will initialize a new CSR NT
|
||||
* Session and allocate a new CSR Process for the subsystem process.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbCreateSession(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
PSB_CREATE_SESSION_MSG CreateSession = &ApiMessage->CreateSession;
|
||||
HANDLE hProcess, hThread;
|
||||
PCSR_PROCESS CsrProcess;
|
||||
NTSTATUS Status;
|
||||
KERNEL_USER_TIMES KernelTimes;
|
||||
PCSR_THREAD CsrThread;
|
||||
//PVOID ProcessData;
|
||||
//ULONG i;
|
||||
|
||||
/* Save the Process and Thread Handles */
|
||||
hProcess = CreateSession->ProcessInfo.ProcessHandle;
|
||||
hThread = CreateSession->ProcessInfo.ThreadHandle;
|
||||
|
||||
/* Lock the Processes */
|
||||
CsrAcquireProcessLock();
|
||||
|
||||
/* Allocate a new process */
|
||||
CsrProcess = CsrAllocateProcess();
|
||||
if (!CsrProcess)
|
||||
{
|
||||
/* Fail */
|
||||
ApiMessage->ReturnValue = STATUS_NO_MEMORY;
|
||||
CsrReleaseProcessLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set the exception port */
|
||||
Status = NtSetInformationProcess(hProcess,
|
||||
ProcessExceptionPort,
|
||||
&CsrApiPort,
|
||||
sizeof(HANDLE));
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail the request */
|
||||
CsrDeallocateProcess(CsrProcess);
|
||||
CsrReleaseProcessLock();
|
||||
|
||||
/* Strange as it seems, NTSTATUSes are actually returned */
|
||||
return (BOOLEAN)STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Get the Create Time */
|
||||
Status = NtQueryInformationThread(hThread,
|
||||
ThreadTimes,
|
||||
&KernelTimes,
|
||||
sizeof(KERNEL_USER_TIMES),
|
||||
NULL);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail the request */
|
||||
CsrDeallocateProcess(CsrProcess);
|
||||
CsrReleaseProcessLock();
|
||||
|
||||
/* Strange as it seems, NTSTATUSes are actually returned */
|
||||
return (BOOLEAN)Status;
|
||||
}
|
||||
|
||||
/* Allocate a new Thread */
|
||||
CsrThread = CsrAllocateThread(CsrProcess);
|
||||
if (!CsrThread)
|
||||
{
|
||||
/* Fail the request */
|
||||
CsrDeallocateProcess(CsrProcess);
|
||||
CsrReleaseProcessLock();
|
||||
|
||||
ApiMessage->ReturnValue = STATUS_NO_MEMORY;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Setup the Thread Object */
|
||||
CsrThread->CreateTime = KernelTimes.CreateTime;
|
||||
CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
|
||||
CsrThread->ThreadHandle = hThread;
|
||||
ProtectHandle(hThread);
|
||||
CsrThread->Flags = 0;
|
||||
|
||||
/* Insert it into the Process List */
|
||||
CsrInsertThread(CsrProcess, CsrThread);
|
||||
|
||||
/* Setup Process Data */
|
||||
CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
|
||||
CsrProcess->ProcessHandle = hProcess;
|
||||
CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId);
|
||||
|
||||
/* Set the Process Priority */
|
||||
CsrSetBackgroundPriority(CsrProcess);
|
||||
#if 0
|
||||
/* Get the first data location */
|
||||
ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX];
|
||||
|
||||
/* Loop every DLL */
|
||||
for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
|
||||
{
|
||||
/* Check if the DLL is loaded and has Process Data */
|
||||
if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData)
|
||||
{
|
||||
/* Write the pointer to the data */
|
||||
CsrProcess->ServerData[i] = ProcessData;
|
||||
|
||||
/* Move to the next data location */
|
||||
ProcessData = (PVOID)((ULONG_PTR)ProcessData +
|
||||
CsrLoadedServerDll[i]->SizeOfProcessData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing for this Process */
|
||||
CsrProcess->ServerData[i] = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* HACKZ: should go in BaseSrv part of CreateCallback done in Insert below */
|
||||
RtlInitializeCriticalSection(&CsrProcess->HandleTableLock);
|
||||
#endif
|
||||
/* Insert the Process */
|
||||
CsrInsertProcess(NULL, NULL, CsrProcess);
|
||||
|
||||
/* Activate the Thread */
|
||||
ApiMessage->ReturnValue = NtResumeThread(hThread, NULL);
|
||||
|
||||
/* Release lock and return */
|
||||
CsrReleaseProcessLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbForeignSessionComplete
|
||||
*
|
||||
* The CsrSbForeignSessionComplete API is called by the Session Manager
|
||||
* whenever a foreign session is completed (ie: terminated).
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks The CsrSbForeignSessionComplete API is not yet implemented.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
/* Deprecated/Unimplemented in NT */
|
||||
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbTerminateSession
|
||||
*
|
||||
* The CsrSbTerminateSession API is called by the Session Manager
|
||||
* whenever a foreign session should be destroyed.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks The CsrSbTerminateSession API is not yet implemented.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbTerminateSession(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbCreateProcess
|
||||
*
|
||||
* The CsrSbCreateProcess API is called by the Session Manager
|
||||
* whenever a foreign session is created and a new process should be started.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the Session Manager API Message.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks The CsrSbCreateProcess API is not yet implemented.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrSbCreateProcess(IN PSB_API_MSG ApiMessage)
|
||||
{
|
||||
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PSB_API_ROUTINE CsrServerSbApiDispatch[5] =
|
||||
{
|
||||
CsrSbCreateSession,
|
||||
CsrSbTerminateSession,
|
||||
CsrSbForeignSessionComplete,
|
||||
CsrSbCreateProcess,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*++
|
||||
* @name CsrSbApiHandleConnectionRequest
|
||||
*
|
||||
* The CsrSbApiHandleConnectionRequest routine handles and accepts a new
|
||||
* connection request to the SM API LPC Port.
|
||||
*
|
||||
* @param ApiMessage
|
||||
* Pointer to the incoming CSR API Message which contains the
|
||||
* connection request.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, or status code which caused
|
||||
* the routine to error.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
REMOTE_PORT_VIEW RemotePortView;
|
||||
HANDLE hPort;
|
||||
|
||||
/* Set the Port View Structure Length */
|
||||
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
|
||||
|
||||
/* Accept the connection */
|
||||
Status = NtAcceptConnectPort(&hPort,
|
||||
NULL,
|
||||
(PPORT_MESSAGE)Message,
|
||||
TRUE,
|
||||
NULL,
|
||||
&RemotePortView);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Complete the Connection */
|
||||
Status = NtCompleteConnectPort(hPort);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status);
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrSbApiRequestThread
|
||||
*
|
||||
* The CsrSbApiRequestThread routine handles incoming messages or connection
|
||||
* requests on the SM API LPC Port.
|
||||
*
|
||||
* @param Parameter
|
||||
* System-default user-defined parameter. Unused.
|
||||
*
|
||||
* @return The thread exit code, if the thread is terminated.
|
||||
*
|
||||
* @remarks Before listening on the port, the routine will first attempt
|
||||
* to connect to the user subsystem.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrSbApiRequestThread(IN PVOID Parameter)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
SB_API_MSG ReceiveMsg;
|
||||
PSB_API_MSG ReplyMsg = NULL;
|
||||
PVOID PortContext;
|
||||
ULONG MessageType;
|
||||
|
||||
/* Start the loop */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Wait for a message to come in */
|
||||
Status = NtReplyWaitReceivePort(CsrSbApiPort,
|
||||
&PortContext,
|
||||
&ReplyMsg->h,
|
||||
&ReceiveMsg.h);
|
||||
|
||||
/* Check if we didn't get success */
|
||||
if (Status != STATUS_SUCCESS)
|
||||
{
|
||||
/* If we only got a warning, keep going */
|
||||
if (NT_SUCCESS(Status)) continue;
|
||||
|
||||
/* We failed big time, so start out fresh */
|
||||
ReplyMsg = NULL;
|
||||
DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Save the message type */
|
||||
MessageType = ReceiveMsg.h.u2.s2.Type;
|
||||
|
||||
/* Check if this is a connection request */
|
||||
if (MessageType == LPC_CONNECTION_REQUEST)
|
||||
{
|
||||
/* Handle connection request */
|
||||
CsrSbApiHandleConnectionRequest(&ReceiveMsg);
|
||||
|
||||
/* Start over */
|
||||
ReplyMsg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if the port died */
|
||||
if (MessageType == LPC_PORT_CLOSED)
|
||||
{
|
||||
/* Close the handle if we have one */
|
||||
if (PortContext) NtClose((HANDLE)PortContext);
|
||||
|
||||
/* Client died, start over */
|
||||
ReplyMsg = NULL;
|
||||
continue;
|
||||
}
|
||||
else if (MessageType == LPC_CLIENT_DIED)
|
||||
{
|
||||
/* Client died, start over */
|
||||
ReplyMsg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's an API Message, check if it's within limits. If it's not, the
|
||||
* NT Behaviour is to set this to the Maximum API.
|
||||
*/
|
||||
if (ReceiveMsg.ApiNumber > SbpMaxApiNumber)
|
||||
{
|
||||
ReceiveMsg.ApiNumber = SbpMaxApiNumber;
|
||||
DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber);
|
||||
}
|
||||
|
||||
/* Reuse the message */
|
||||
ReplyMsg = &ReceiveMsg;
|
||||
|
||||
/* Make sure that the message is supported */
|
||||
if (ReceiveMsg.ApiNumber < SbpMaxApiNumber)
|
||||
{
|
||||
/* Call the API */
|
||||
if (!CsrServerSbApiDispatch[ReceiveMsg.ApiNumber](&ReceiveMsg))
|
||||
{
|
||||
/* It failed, so return nothing */
|
||||
ReplyMsg = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't support this API Number */
|
||||
ReplyMsg->ReturnValue = STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef _SRV_H
|
||||
#define _SRV_H
|
||||
|
||||
/* PSDK/NDK Headers */
|
||||
#define NTOS_MODE_USER
|
||||
#include <stdio.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <wincon.h>
|
||||
#include <winreg.h>
|
||||
#include <ndk/setypes.h>
|
||||
#include <ndk/sefuncs.h>
|
||||
#include <ndk/exfuncs.h>
|
||||
#include <ndk/cmfuncs.h>
|
||||
#include <ndk/obfuncs.h>
|
||||
#include <ndk/lpctypes.h>
|
||||
#include <ndk/lpcfuncs.h>
|
||||
#include <ndk/kefuncs.h>
|
||||
#include <ndk/dbgktypes.h>
|
||||
#include <ndk/mmfuncs.h>
|
||||
#include <ndk/umfuncs.h>
|
||||
|
||||
/* CSR Header */
|
||||
//#include <csr/server.h>
|
||||
|
||||
/* PSEH for SEH Support */
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
/* Subsystem Manager Header */
|
||||
#include <sm/helper.h>
|
||||
#include <sm/smmsg.h>
|
||||
|
||||
/* Internal CSRSS Headers */
|
||||
#include <api.h>
|
||||
#include <csrplugin.h>
|
||||
|
||||
extern HANDLE CsrHeap;
|
||||
|
||||
#define SM_REG_KEY \
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager"
|
||||
|
||||
#define SESSION_ROOT L"\\Sessions"
|
||||
#define GLOBAL_ROOT L"\\GLOBAL??"
|
||||
#define SYMLINK_NAME L"SymbolicLink"
|
||||
#define SB_PORT_NAME L"SbAbiPort"
|
||||
#define CSR_PORT_NAME L"ApiPort"
|
||||
#define UNICODE_PATH_SEP L"\\"
|
||||
|
||||
/* Defines */
|
||||
#define ROUND_UP(n, align) ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
|
||||
#define ROUND_DOWN(n, align) (((ULONG)n) & ~((align) - 1l))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,819 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsystems/win32/csrss/csrsrv/thredsup.c
|
||||
* PURPOSE: CSR Server DLL Thread Implementation
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
* Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <srv.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define CsrHashThread(t) \
|
||||
(HandleToUlong(t)&(256 - 1))
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
LIST_ENTRY CsrThreadHashTable[256];
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/*++
|
||||
* @name ProtectHandle
|
||||
* @implemented NT5.2
|
||||
*
|
||||
* The ProtectHandle routine protects an object handle against closure.
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ProtectHandle(IN HANDLE ObjectHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
|
||||
|
||||
/* Query current state */
|
||||
Status = NtQueryObject(ObjectHandle,
|
||||
ObjectHandleFlagInformation,
|
||||
&HandleInfo,
|
||||
sizeof(HandleInfo),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Enable protect from close */
|
||||
HandleInfo.ProtectFromClose = TRUE;
|
||||
Status = NtSetInformationObject(ObjectHandle,
|
||||
ObjectHandleFlagInformation,
|
||||
&HandleInfo,
|
||||
sizeof(HandleInfo));
|
||||
if (NT_SUCCESS(Status)) return TRUE;
|
||||
}
|
||||
|
||||
/* We failed to or set the state */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name UnProtectHandle
|
||||
* @implemented NT5.2
|
||||
*
|
||||
* The UnProtectHandle routine unprotects an object handle against closure.
|
||||
*
|
||||
* @return TRUE or FALSE.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
UnProtectHandle(IN HANDLE ObjectHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
|
||||
|
||||
/* Query current state */
|
||||
Status = NtQueryObject(ObjectHandle,
|
||||
ObjectHandleFlagInformation,
|
||||
&HandleInfo,
|
||||
sizeof(HandleInfo),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Disable protect from close */
|
||||
HandleInfo.ProtectFromClose = FALSE;
|
||||
Status = NtSetInformationObject(ObjectHandle,
|
||||
ObjectHandleFlagInformation,
|
||||
&HandleInfo,
|
||||
sizeof(HandleInfo));
|
||||
if (NT_SUCCESS(Status)) return TRUE;
|
||||
}
|
||||
|
||||
/* We failed to or set the state */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrAllocateThread
|
||||
*
|
||||
* The CsrAllocateThread routine allocates a new CSR Thread object.
|
||||
*
|
||||
* @param CsrProcess
|
||||
* Pointer to the CSR Process which will contain this CSR Thread.
|
||||
*
|
||||
* @return Pointer to the newly allocated CSR Thread.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrAllocateThread(IN PCSR_PROCESS CsrProcess)
|
||||
{
|
||||
PCSR_THREAD CsrThread;
|
||||
|
||||
/* Allocate the structure */
|
||||
CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
|
||||
if (!CsrThread) return(NULL);
|
||||
|
||||
/* Reference the Thread and Process */
|
||||
CsrThread->ReferenceCount++;
|
||||
CsrProcess->ReferenceCount++;
|
||||
|
||||
/* Set the Parent Process */
|
||||
CsrThread->Process = CsrProcess;
|
||||
|
||||
/* Return Thread */
|
||||
return CsrThread;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrLockedReferenceThread
|
||||
*
|
||||
* The CsrLockedReferenceThread references a CSR Thread while the
|
||||
* Process Lock is already being held.
|
||||
*
|
||||
* @param CsrThread
|
||||
* Pointer to the CSR Thread to be referenced.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks This routine will return with the Process Lock held.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedReferenceThread(IN PCSR_THREAD CsrThread)
|
||||
{
|
||||
/* Increment the reference count */
|
||||
++CsrThread->ReferenceCount;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrLocateThreadByClientId
|
||||
*
|
||||
* The CsrLocateThreadByClientId routine locates the CSR Thread and,
|
||||
* optionally, its parent CSR Process, corresponding to a Client ID.
|
||||
*
|
||||
* @param Process
|
||||
* Optional pointer to a CSR Process pointer which will contain
|
||||
* the CSR Thread's parent.
|
||||
*
|
||||
* @param ClientId
|
||||
* Pointer to a Client ID structure containing the Unique Thread ID
|
||||
* to look up.
|
||||
*
|
||||
* @return Pointer to the CSR Thread corresponding to this CID, or NULL if
|
||||
* none was found.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL,
|
||||
IN PCLIENT_ID ClientId)
|
||||
{
|
||||
ULONG i;
|
||||
PLIST_ENTRY ListHead, NextEntry;
|
||||
PCSR_THREAD FoundThread;
|
||||
// ASSERT(ProcessStructureListLocked());
|
||||
|
||||
/* Hash the Thread */
|
||||
i = CsrHashThread(ClientId->UniqueThread);
|
||||
|
||||
/* Set the list pointers */
|
||||
ListHead = &CsrThreadHashTable[i];
|
||||
NextEntry = ListHead->Flink;
|
||||
|
||||
/* Star the loop */
|
||||
while (NextEntry != ListHead)
|
||||
{
|
||||
/* Get the thread */
|
||||
FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
|
||||
|
||||
/* Compare the CID */
|
||||
if (FoundThread->ClientId.UniqueThread == ClientId->UniqueThread)
|
||||
{
|
||||
/* Match found, return the process */
|
||||
*Process = FoundThread->Process;
|
||||
|
||||
/* Return thread too */
|
||||
// DPRINT1("Found: %p %p\n", FoundThread, FoundThread->Process);
|
||||
return FoundThread;
|
||||
}
|
||||
|
||||
/* Next */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Nothing found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrLocateThreadInProcess
|
||||
*
|
||||
* The CsrLocateThreadInProcess routine locates the CSR Thread
|
||||
* corresponding to a Client ID inside a specific CSR Process.
|
||||
*
|
||||
* @param Process
|
||||
* Optional pointer to the CSR Process which contains the CSR Thread
|
||||
* that will be looked up.
|
||||
*
|
||||
* @param ClientId
|
||||
* Pointer to a Client ID structure containing the Unique Thread ID
|
||||
* to look up.
|
||||
*
|
||||
* @return Pointer to the CSR Thread corresponding to this CID, or NULL if
|
||||
* none was found.
|
||||
*
|
||||
* @remarks If the CsrProcess argument is NULL, the lookup will be done inside
|
||||
* CsrRootProcess.
|
||||
*
|
||||
*--*/
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL,
|
||||
IN PCLIENT_ID Cid)
|
||||
{
|
||||
PLIST_ENTRY ListHead, NextEntry;
|
||||
PCSR_THREAD FoundThread = NULL;
|
||||
|
||||
/* Use the Root Process if none was specified */
|
||||
if (!CsrProcess) CsrProcess = CsrRootProcess;
|
||||
|
||||
/* Save the List pointers */
|
||||
// DPRINT1("Searching in: %p %d\n", CsrProcess, CsrProcess->ThreadCount);
|
||||
ListHead = &CsrProcess->ThreadList;
|
||||
NextEntry = ListHead->Flink;
|
||||
|
||||
/* Start the Loop */
|
||||
while (NextEntry != ListHead)
|
||||
{
|
||||
/* Get Thread Entry */
|
||||
FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
|
||||
|
||||
/* Check for TID Match */
|
||||
if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
|
||||
|
||||
/* Next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Return what we found */
|
||||
// DPRINT1("Found: %p\n", FoundThread);
|
||||
return FoundThread;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrInsertThread
|
||||
*
|
||||
* The CsrInsertThread routine inserts a CSR Thread into its parent's
|
||||
* Thread List and into the Thread Hash Table.
|
||||
*
|
||||
* @param Process
|
||||
* Pointer to the CSR Process containing this CSR Thread.
|
||||
*
|
||||
* @param Thread
|
||||
* Pointer to the CSR Thread to be inserted.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrInsertThread(IN PCSR_PROCESS Process,
|
||||
IN PCSR_THREAD Thread)
|
||||
{
|
||||
ULONG i;
|
||||
// ASSERT(ProcessStructureListLocked());
|
||||
|
||||
/* Insert it into the Regular List */
|
||||
InsertTailList(&Process->ThreadList, &Thread->Link);
|
||||
|
||||
/* Increase Thread Count */
|
||||
Process->ThreadCount++;
|
||||
|
||||
/* Hash the Thread */
|
||||
i = CsrHashThread(Thread->ClientId.UniqueThread);
|
||||
// DPRINT1("TID %lx HASH: %lx\n", Thread->ClientId.UniqueThread, i);
|
||||
|
||||
/* Insert it there too */
|
||||
InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDeallocateThread
|
||||
*
|
||||
* The CsrDeallocateThread frees the memory associated with a CSR Thread.
|
||||
*
|
||||
* @param CsrThread
|
||||
* Pointer to the CSR Thread to be freed.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks Do not call this routine. It is reserved for the internal
|
||||
* thread management routines when a CSR Thread has been cleanly
|
||||
* dereferenced and killed.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDeallocateThread(IN PCSR_THREAD CsrThread)
|
||||
{
|
||||
/* Free the process object from the heap */
|
||||
// ASSERT(CsrThread->WaitBlock == NULL);
|
||||
RtlFreeHeap(CsrHeap, 0, CsrThread);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrRemoveThread
|
||||
*
|
||||
* The CsrRemoveThread function undoes a CsrInsertThread operation and
|
||||
* removes the CSR Thread from the the Hash Table and Thread List.
|
||||
*
|
||||
* @param CsrThread
|
||||
* Pointer to the CSR Thread to remove.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks If this CSR Thread is the last one inside a CSR Process, the
|
||||
* parent will be dereferenced and the CsrProcessLastThreadTerminated
|
||||
* flag will be set.
|
||||
*
|
||||
* After executing this routine, the CSR Thread will have the
|
||||
* CsrThreadInTermination flag set.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrRemoveThread(IN PCSR_THREAD CsrThread)
|
||||
{
|
||||
ASSERT(ProcessStructureListLocked());
|
||||
|
||||
/* Remove it from the List */
|
||||
RemoveEntryList(&CsrThread->Link);
|
||||
|
||||
/* Decreate the thread count of the process */
|
||||
CsrThread->Process->ThreadCount--;
|
||||
|
||||
/* Remove it from the Hash List as well */
|
||||
if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
|
||||
|
||||
/* Check if this is the last Thread */
|
||||
if (!CsrThread->Process->ThreadCount)
|
||||
{
|
||||
/* Check if it's not already been marked for deletion */
|
||||
if (!(CsrThread->Process->Flags & CsrProcessLastThreadTerminated))
|
||||
{
|
||||
/* Let everyone know this process is about to lose the thread */
|
||||
CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
|
||||
|
||||
/* Reference the Process */
|
||||
CsrLockedDereferenceProcess(CsrThread->Process);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark the thread for deletion */
|
||||
CsrThread->Flags |= CsrThreadInTermination;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrCreateRemoteThread
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrCreateRemoteThread routine creates a CSR Thread object for
|
||||
* an NT Thread which is not part of the current NT Process.
|
||||
*
|
||||
* @param hThread
|
||||
* Handle to an existing NT Thread to which to associate this
|
||||
* CSR Thread.
|
||||
*
|
||||
* @param ClientId
|
||||
* Pointer to the Client ID structure of the NT Thread to associate
|
||||
* with this CSR Thread.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* otherwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateRemoteThread(IN HANDLE hThread,
|
||||
IN PCLIENT_ID ClientId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE ThreadHandle;
|
||||
PCSR_THREAD CsrThread;
|
||||
PCSR_PROCESS CsrProcess;
|
||||
KERNEL_USER_TIMES KernelTimes;
|
||||
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
|
||||
|
||||
/* Get the Thread Create Time */
|
||||
Status = NtQueryInformationThread(hThread,
|
||||
ThreadTimes,
|
||||
&KernelTimes,
|
||||
sizeof(KernelTimes),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to query thread times: %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Lock the Owner Process */
|
||||
Status = CsrLockProcessByClientId(&ClientId->UniqueProcess, &CsrProcess);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("No known process for %lx\n", ClientId->UniqueProcess);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Make sure the thread didn't terminate */
|
||||
if (KernelTimes.ExitTime.QuadPart)
|
||||
{
|
||||
/* Unlock the process and return */
|
||||
CsrUnlockProcess(CsrProcess);
|
||||
DPRINT1("Dead thread: %I64x\n", KernelTimes.ExitTime.QuadPart);
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
}
|
||||
|
||||
/* Allocate a CSR Thread Structure */
|
||||
CsrThread = CsrAllocateThread(CsrProcess);
|
||||
if (!CsrThread)
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
|
||||
CsrUnlockProcess(CsrProcess);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Duplicate the Thread Handle */
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
hThread,
|
||||
NtCurrentProcess(),
|
||||
&ThreadHandle,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
/* Allow failure */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Thread duplication failed: %lx\n", Status);
|
||||
ThreadHandle = hThread;
|
||||
}
|
||||
|
||||
/* Save the data we have */
|
||||
CsrThread->CreateTime = KernelTimes.CreateTime;
|
||||
CsrThread->ClientId = *ClientId;
|
||||
CsrThread->ThreadHandle = ThreadHandle;
|
||||
ProtectHandle(ThreadHandle);
|
||||
CsrThread->Flags = 0;
|
||||
|
||||
/* Insert the Thread into the Process */
|
||||
CsrInsertThread(CsrProcess, CsrThread);
|
||||
|
||||
/* Release the lock and return */
|
||||
CsrUnlockProcess(CsrProcess);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrThreadRefcountZero
|
||||
*
|
||||
* The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
|
||||
* all its active references. It removes and de-allocates the CSR Thread.
|
||||
*
|
||||
* @param CsrThread
|
||||
* Pointer to the CSR Thread that is to be deleted.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks Do not call this routine. It is reserved for the internal
|
||||
* thread management routines when a CSR Thread has lost all
|
||||
* its references.
|
||||
*
|
||||
* This routine is called with the Process Lock held.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
|
||||
{
|
||||
PCSR_PROCESS CsrProcess = CsrThread->Process;
|
||||
NTSTATUS Status;
|
||||
ASSERT(ProcessStructureListLocked());
|
||||
|
||||
/* Remove this thread */
|
||||
CsrRemoveThread(CsrThread);
|
||||
|
||||
/* Release the Process Lock */
|
||||
CsrReleaseProcessLock();
|
||||
|
||||
/* Close the NT Thread Handle */
|
||||
if (CsrThread->ThreadHandle)
|
||||
{
|
||||
UnProtectHandle(CsrThread->ThreadHandle);
|
||||
Status = NtClose(CsrThread->ThreadHandle);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
}
|
||||
|
||||
/* De-allocate the CSR Thread Object */
|
||||
CsrDeallocateThread(CsrThread);
|
||||
|
||||
/* Remove a reference from the process */
|
||||
CsrDereferenceProcess(CsrProcess);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDestroyThread
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrDestroyThread routine destroys the CSR Thread corresponding to
|
||||
* a given Thread ID.
|
||||
*
|
||||
* @param Cid
|
||||
* Pointer to the Client ID Structure corresponding to the CSR
|
||||
* Thread which is about to be destroyed.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
|
||||
* if the CSR Thread is already terminating.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrDestroyThread(IN PCLIENT_ID Cid)
|
||||
{
|
||||
CLIENT_ID ClientId = *Cid;
|
||||
PCSR_THREAD CsrThread;
|
||||
PCSR_PROCESS CsrProcess;
|
||||
|
||||
/* Acquire lock */
|
||||
CsrAcquireProcessLock();
|
||||
|
||||
/* Find the thread */
|
||||
CsrThread = CsrLocateThreadByClientId(&CsrProcess,
|
||||
&ClientId);
|
||||
|
||||
/* Make sure we got one back, and that it's not already gone */
|
||||
if (!CsrThread || CsrThread->Flags & CsrThreadTerminated)
|
||||
{
|
||||
/* Release the lock and return failure */
|
||||
CsrReleaseProcessLock();
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
}
|
||||
|
||||
/* Set the terminated flag */
|
||||
CsrThread->Flags |= CsrThreadTerminated;
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Do we have an active wait block? */
|
||||
if (CsrThread->WaitBlock)
|
||||
{
|
||||
/* Notify waiters of termination */
|
||||
CsrNotifyWaitBlock(CsrThread->WaitBlock,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CsrProcessTerminating,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
/* Release the Wait Lock */
|
||||
CsrReleaseWaitLock();
|
||||
|
||||
/* Dereference the thread */
|
||||
CsrLockedDereferenceThread(CsrThread);
|
||||
|
||||
/* Release the Process Lock and return success */
|
||||
CsrReleaseProcessLock();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrLockedDereferenceThread
|
||||
*
|
||||
* The CsrLockedDereferenceThread dereferences a CSR Thread while the
|
||||
* Process Lock is already being held.
|
||||
*
|
||||
* @param CsrThread
|
||||
* Pointer to the CSR Thread to be dereferenced.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks This routine will return with the Process Lock held.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread)
|
||||
{
|
||||
LONG LockCount;
|
||||
|
||||
/* Decrease reference count */
|
||||
LockCount = --CsrThread->ReferenceCount;
|
||||
ASSERT(LockCount >= 0);
|
||||
if (!LockCount)
|
||||
{
|
||||
/* Call the generic cleanup code */
|
||||
CsrThreadRefcountZero(CsrThread);
|
||||
CsrAcquireProcessLock();
|
||||
}
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrCreateThread
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
|
||||
*
|
||||
* @param CsrProcess
|
||||
* Pointer to the CSR Process which will contain the CSR Thread.
|
||||
*
|
||||
* @param hThread
|
||||
* Handle to an existing NT Thread to which to associate this
|
||||
* CSR Thread.
|
||||
*
|
||||
* @param ClientId
|
||||
* Pointer to the Client ID structure of the NT Thread to associate
|
||||
* with this CSR Thread.
|
||||
*
|
||||
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
|
||||
* otherwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CsrCreateThread(IN PCSR_PROCESS CsrProcess,
|
||||
IN HANDLE hThread,
|
||||
IN PCLIENT_ID ClientId)
|
||||
{
|
||||
PCSR_THREAD CsrThread;
|
||||
PCSR_PROCESS CurrentProcess;
|
||||
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
|
||||
CLIENT_ID CurrentCid;
|
||||
KERNEL_USER_TIMES KernelTimes;
|
||||
|
||||
/* Get the current thread and CID */
|
||||
CurrentCid = CurrentThread->ClientId;
|
||||
|
||||
/* Acquire the Process Lock */
|
||||
CsrAcquireProcessLock();
|
||||
|
||||
/* Get the current Process and make sure the Thread is valid with this CID */
|
||||
CurrentThread = CsrLocateThreadByClientId(&CurrentProcess,
|
||||
&CurrentCid);
|
||||
|
||||
/* Something is wrong if we get an empty thread back */
|
||||
if (!CurrentThread)
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__);
|
||||
CsrReleaseProcessLock();
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
}
|
||||
|
||||
/* Get the Thread Create Time */
|
||||
NtQueryInformationThread(hThread,
|
||||
ThreadTimes,
|
||||
(PVOID)&KernelTimes,
|
||||
sizeof(KernelTimes),
|
||||
NULL);
|
||||
|
||||
/* Allocate a CSR Thread Structure */
|
||||
if (!(CsrThread = CsrAllocateThread(CsrProcess)))
|
||||
{
|
||||
DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
|
||||
CsrReleaseProcessLock();
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Save the data we have */
|
||||
CsrThread->CreateTime = KernelTimes.CreateTime;
|
||||
CsrThread->ClientId = *ClientId;
|
||||
CsrThread->ThreadHandle = hThread;
|
||||
CsrThread->Flags = 0;
|
||||
|
||||
/* Insert the Thread into the Process */
|
||||
CsrInsertThread(CsrProcess, CsrThread);
|
||||
|
||||
/* Release the lock and return */
|
||||
CsrReleaseProcessLock();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrAddStaticServerThread
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrAddStaticServerThread routine adds a new CSR Thread to the
|
||||
* CSR Server Process (CsrRootProcess).
|
||||
*
|
||||
* @param hThread
|
||||
* Handle to an existing NT Thread to which to associate this
|
||||
* CSR Thread.
|
||||
*
|
||||
* @param ClientId
|
||||
* Pointer to the Client ID structure of the NT Thread to associate
|
||||
* with this CSR Thread.
|
||||
*
|
||||
* @param ThreadFlags
|
||||
* Initial CSR Thread Flags to associate to this CSR Thread. Usually
|
||||
* CsrThreadIsServerThread.
|
||||
*
|
||||
* @return Pointer to the newly allocated CSR Thread.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
PCSR_THREAD
|
||||
NTAPI
|
||||
CsrAddStaticServerThread(IN HANDLE hThread,
|
||||
IN PCLIENT_ID ClientId,
|
||||
IN ULONG ThreadFlags)
|
||||
{
|
||||
PCSR_THREAD CsrThread;
|
||||
|
||||
/* Get the Lock */
|
||||
CsrAcquireProcessLock();
|
||||
|
||||
/* Allocate the Server Thread */
|
||||
CsrThread = CsrAllocateThread(CsrRootProcess);
|
||||
if (CsrThread)
|
||||
{
|
||||
/* Setup the Object */
|
||||
CsrThread->ThreadHandle = hThread;
|
||||
ProtectHandle(hThread);
|
||||
CsrThread->ClientId = *ClientId;
|
||||
CsrThread->Flags = ThreadFlags;
|
||||
|
||||
/* Insert it into the Thread List */
|
||||
InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
|
||||
|
||||
/* Increment the thread count */
|
||||
CsrRootProcess->ThreadCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread);
|
||||
}
|
||||
|
||||
/* Release the Process Lock and return */
|
||||
CsrReleaseProcessLock();
|
||||
return CsrThread;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDereferenceThread
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrDereferenceThread routine removes a reference from a CSR Thread.
|
||||
*
|
||||
* @param CsrThread
|
||||
* Pointer to the CSR Thread to dereference.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks If the reference count has reached zero (ie: the CSR Thread has
|
||||
* no more active references), it will be deleted.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceThread(IN PCSR_THREAD CsrThread)
|
||||
{
|
||||
/* Acquire process lock */
|
||||
CsrAcquireProcessLock();
|
||||
|
||||
/* Decrease reference count */
|
||||
ASSERT(CsrThread->ReferenceCount > 0);
|
||||
if (!(--CsrThread->ReferenceCount))
|
||||
{
|
||||
/* Call the generic cleanup code */
|
||||
CsrThreadRefcountZero(CsrThread);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just release the lock */
|
||||
CsrReleaseProcessLock();
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSR Sub System
|
||||
* FILE: subsystems/win32/csrss/csrsrv/wait.c
|
||||
* PURPOSE: CSR Server DLL Wait Implementation
|
||||
* PROGRAMMERS: Emanuele Aliberti
|
||||
* Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "srv.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
RTL_CRITICAL_SECTION CsrWaitListsLock;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrInitializeWait
|
||||
*
|
||||
* The CsrInitializeWait routine initializes a CSR Wait Object.
|
||||
*
|
||||
* @param WaitFunction
|
||||
* Pointer to the function that will handle this wait.
|
||||
*
|
||||
* @param CsrWaitThread
|
||||
* Pointer to the CSR Thread that will perform the wait.
|
||||
*
|
||||
* @param WaitApiMessage
|
||||
* Pointer to the CSR API Message associated to this wait.
|
||||
*
|
||||
* @param WaitContext
|
||||
* Pointer to a user-defined parameter associated to this wait.
|
||||
*
|
||||
* @param NewWaitBlock
|
||||
* Pointed to the initialized CSR Wait Block for this wait.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrInitializeWait(IN CSR_WAIT_FUNCTION WaitFunction,
|
||||
IN PCSR_THREAD CsrWaitThread,
|
||||
IN OUT PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
OUT PCSR_WAIT_BLOCK *NewWaitBlock)
|
||||
{
|
||||
ULONG Size;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Calculate the size of the wait block */
|
||||
Size = sizeof(CSR_WAIT_BLOCK) -
|
||||
sizeof(WaitBlock->WaitApiMessage) +
|
||||
WaitApiMessage->Header.u1.s1.TotalLength;
|
||||
|
||||
/* Allocate the Wait Block */
|
||||
WaitBlock = RtlAllocateHeap(CsrHeap, 0, Size);
|
||||
if (!WaitBlock)
|
||||
{
|
||||
/* Fail */
|
||||
WaitApiMessage->Status = STATUS_NO_MEMORY;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
WaitBlock->Size = Size;
|
||||
WaitBlock->WaitThread = CsrWaitThread;
|
||||
WaitBlock->WaitContext = WaitContext;
|
||||
WaitBlock->WaitFunction = WaitFunction;
|
||||
WaitBlock->UserWaitList.Flink = NULL;
|
||||
WaitBlock->UserWaitList.Blink = NULL;
|
||||
WaitBlock->WaitList = WaitBlock->UserWaitList;
|
||||
|
||||
/* Copy the message */
|
||||
RtlMoveMemory(&WaitBlock->WaitApiMessage,
|
||||
WaitApiMessage,
|
||||
WaitApiMessage->Header.u1.s1.TotalLength);
|
||||
|
||||
/* Return the block */
|
||||
*NewWaitBlock = WaitBlock;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrNotifyWaitBlock
|
||||
*
|
||||
* The CsrNotifyWaitBlock routine calls the wait function for a registered
|
||||
* CSR Wait Block, and replies to the attached CSR API Message, if any.
|
||||
*
|
||||
* @param WaitBlock
|
||||
* Pointer to the CSR Wait Block
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to the wait list for this wait.
|
||||
*
|
||||
* @param WaitArgument[1-2]
|
||||
* User-defined values to pass to the wait function.
|
||||
*
|
||||
* @param WaitFlags
|
||||
* Wait flags for this wait.
|
||||
*
|
||||
* @param DereferenceThread
|
||||
* Specifies whether the CSR Thread should be dereferenced at the
|
||||
* end of this wait.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks After a wait block is notified, the wait function becomes invalid.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock,
|
||||
IN PLIST_ENTRY WaitList,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags,
|
||||
IN BOOLEAN DereferenceThread)
|
||||
{
|
||||
/* Call the wait function */
|
||||
if ((WaitBlock->WaitFunction)(WaitList,
|
||||
WaitBlock->WaitThread,
|
||||
&WaitBlock->WaitApiMessage,
|
||||
WaitBlock->WaitContext,
|
||||
WaitArgument1,
|
||||
WaitArgument2,
|
||||
WaitFlags))
|
||||
{
|
||||
/* The wait is done, clear the block */
|
||||
WaitBlock->WaitThread->WaitBlock = NULL;
|
||||
|
||||
/* Check for captured arguments */
|
||||
if (WaitBlock->WaitApiMessage.CsrCaptureData)
|
||||
{
|
||||
/* Release them */
|
||||
CsrReleaseCapturedArguments(&WaitBlock->WaitApiMessage);
|
||||
}
|
||||
|
||||
/* Reply to the port */
|
||||
NtReplyPort(WaitBlock->WaitThread->Process->ClientPort,
|
||||
(PPORT_MESSAGE)&WaitBlock->WaitApiMessage);
|
||||
|
||||
/* Check if we should dereference the thread */
|
||||
if (DereferenceThread)
|
||||
{
|
||||
/* Remove it from the Wait List */
|
||||
if (WaitBlock->WaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->WaitList);
|
||||
}
|
||||
|
||||
/* Remove it from the User Wait List */
|
||||
if (WaitBlock->UserWaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->UserWaitList);
|
||||
}
|
||||
|
||||
/* Dereference teh thread */
|
||||
CsrDereferenceThread(WaitBlock->WaitThread);
|
||||
|
||||
/* Free the wait block */
|
||||
RtlFreeHeap(CsrHeap, 0, WaitBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wait is complete, but the thread is being kept alive */
|
||||
WaitBlock->WaitFunction = NULL;
|
||||
}
|
||||
|
||||
/* The wait suceeded */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The wait failed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*++
|
||||
* @name CsrCreateWait
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrCreateWait routine creates a CSR Wait.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to a list entry of the waits to associate.
|
||||
*
|
||||
* @param WaitFunction
|
||||
* Pointer to the function that will handle this wait.
|
||||
*
|
||||
* @param CsrWaitThread
|
||||
* Pointer to the CSR Thread that will perform the wait.
|
||||
*
|
||||
* @param WaitApiMessage
|
||||
* Pointer to the CSR API Message associated to this wait.
|
||||
*
|
||||
* @param WaitContext
|
||||
* Pointer to a user-defined parameter associated to this wait.
|
||||
*
|
||||
* @param UserWaitList
|
||||
* Pointer to a list entry of the user-defined waits to associate.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrCreateWait(IN PLIST_ENTRY WaitList,
|
||||
IN CSR_WAIT_FUNCTION WaitFunction,
|
||||
IN PCSR_THREAD CsrWaitThread,
|
||||
IN OUT PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PLIST_ENTRY UserWaitList OPTIONAL)
|
||||
{
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Initialize the wait */
|
||||
if (!CsrInitializeWait(WaitFunction,
|
||||
CsrWaitThread,
|
||||
WaitApiMessage,
|
||||
WaitContext,
|
||||
&WaitBlock))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Make sure the thread wasn't destroyed */
|
||||
if (CsrWaitThread->Flags & CsrThreadTerminated)
|
||||
{
|
||||
/* Fail the wait */
|
||||
RtlFreeHeap(CsrHeap, 0, WaitBlock);
|
||||
CsrReleaseWaitLock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Insert the wait in the queue */
|
||||
InsertTailList(WaitList, &WaitBlock->WaitList);
|
||||
|
||||
/* Insert the User Wait too, if one was given */
|
||||
if (UserWaitList) InsertTailList(UserWaitList, &WaitBlock->UserWaitList);
|
||||
|
||||
/* Return */
|
||||
CsrReleaseWaitLock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrDereferenceWait
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrDereferenceWait routine dereferences a CSR Wait Block.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to the Wait List associated to the wait.
|
||||
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrDereferenceWait(IN PLIST_ENTRY WaitList)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Acquire the Process and Wait Locks */
|
||||
CsrAcquireProcessLock();
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Set the list pointers */
|
||||
NextEntry = WaitList->Flink;
|
||||
|
||||
/* Start the loop */
|
||||
while (NextEntry != WaitList)
|
||||
{
|
||||
/* Get the wait block */
|
||||
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
|
||||
|
||||
/* Move to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
/* Check if there's no Wait Routine */
|
||||
if (!WaitBlock->WaitFunction)
|
||||
{
|
||||
/* Remove it from the Wait List */
|
||||
if (WaitBlock->WaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->WaitList);
|
||||
}
|
||||
|
||||
/* Remove it from the User Wait List */
|
||||
if (WaitBlock->UserWaitList.Flink)
|
||||
{
|
||||
RemoveEntryList(&WaitBlock->UserWaitList);
|
||||
}
|
||||
|
||||
/* Dereference the thread waiting on it */
|
||||
CsrDereferenceThread(WaitBlock->WaitThread);
|
||||
|
||||
/* Free the block */
|
||||
RtlFreeHeap(CsrHeap, 0, WaitBlock);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the locks */
|
||||
CsrReleaseWaitLock();
|
||||
CsrReleaseProcessLock();
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrMoveSatisfiedWait
|
||||
* @implemented NT5
|
||||
*
|
||||
* The CsrMoveSatisfiedWait routine moves satisfied waits from a wait list
|
||||
* to another list entry.
|
||||
*
|
||||
* @param NewEntry
|
||||
* Pointer to a list entry where the satisfied waits will be added.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to a list entry to analyze for satisfied waits.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
CsrMoveSatisfiedWait(IN PLIST_ENTRY NewEntry,
|
||||
IN PLIST_ENTRY WaitList)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Set the List pointers */
|
||||
NextEntry = WaitList->Flink;
|
||||
|
||||
/* Start looping */
|
||||
while (NextEntry != WaitList)
|
||||
{
|
||||
/* Get the Wait block */
|
||||
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
|
||||
|
||||
/* Go to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
/* Check if there is a Wait Callback */
|
||||
if (WaitBlock->WaitFunction)
|
||||
{
|
||||
/* Remove it from the Wait Block Queue */
|
||||
RemoveEntryList(&WaitBlock->WaitList);
|
||||
|
||||
/* Insert the new entry */
|
||||
InsertTailList(&WaitBlock->WaitList, NewEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the wait lock */
|
||||
CsrReleaseWaitLock();
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name CsrNotifyWait
|
||||
* @implemented NT4
|
||||
*
|
||||
* The CsrNotifyWait notifies a CSR Wait Block.
|
||||
*
|
||||
* @param WaitList
|
||||
* Pointer to the list entry for this wait.
|
||||
*
|
||||
* @param WaitType
|
||||
* Type of the wait to perform, either WaitAny or WaitAll.
|
||||
*
|
||||
* @param WaitArgument[1-2]
|
||||
* User-defined argument to pass on to the wait function.
|
||||
*
|
||||
* @return TRUE in case of success, FALSE otherwise.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CsrNotifyWait(IN PLIST_ENTRY WaitList,
|
||||
IN ULONG WaitType,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PCSR_WAIT_BLOCK WaitBlock;
|
||||
BOOLEAN NotifySuccess = FALSE;
|
||||
|
||||
/* Acquire the Wait Lock */
|
||||
CsrAcquireWaitLock();
|
||||
|
||||
/* Set the List pointers */
|
||||
NextEntry = WaitList->Flink;
|
||||
|
||||
/* Start looping */
|
||||
while (NextEntry != WaitList)
|
||||
{
|
||||
/* Get the Wait block */
|
||||
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
|
||||
|
||||
/* Go to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
|
||||
/* Check if there is a Wait Callback */
|
||||
if (WaitBlock->WaitFunction)
|
||||
{
|
||||
/* Notify the Waiter */
|
||||
NotifySuccess |= CsrNotifyWaitBlock(WaitBlock,
|
||||
WaitList,
|
||||
WaitArgument1,
|
||||
WaitArgument2,
|
||||
0,
|
||||
FALSE);
|
||||
|
||||
/* We've already done a wait, so leave unless this is a Wait All */
|
||||
if (WaitType != WaitAll) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the wait lock and return */
|
||||
CsrReleaseWaitLock();
|
||||
return NotifySuccess;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
include_directories(
|
||||
BEFORE .
|
||||
${REACTOS_SOURCE_DIR}/subsystems/win32/csrss/include
|
||||
${REACTOS_SOURCE_DIR}/include/reactos/subsys
|
||||
${REACTOS_SOURCE_DIR}/include/reactos/drivers
|
||||
${REACTOS_SOURCE_DIR}/dll/cpl/console
|
||||
${REACTOS_SOURCE_DIR}/win32ss/include)
|
||||
|
||||
spec2def(win32csr.dll win32csr.spec)
|
||||
|
||||
list(APPEND SOURCE
|
||||
alias.c
|
||||
coninput.c
|
||||
conoutput.c
|
||||
console.c
|
||||
desktopbg.c
|
||||
dllmain.c
|
||||
exitros.c
|
||||
file.c
|
||||
guiconsole.c
|
||||
handle.c
|
||||
harderror.c
|
||||
lineinput.c
|
||||
tuiconsole.c
|
||||
win32csr.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/win32csr.def)
|
||||
|
||||
add_library(win32csr SHARED ${SOURCE})
|
||||
target_link_libraries(win32csr win32ksys ${PSEH_LIB})
|
||||
set_module_type(win32csr win32dll)
|
||||
add_importlibs(win32csr psapi msvcrt kernel32 ntdll csrsrv)
|
||||
add_delay_importlibs(win32csr user32 gdi32 advapi32)
|
||||
add_pch(win32csr w32csr.h)
|
||||
add_dependencies(win32csr bugcodes)
|
||||
add_cd_file(TARGET win32csr DESTINATION reactos/system32 FOR all)
|
||||
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: subsystems/win32/csrss/api/alias.c
|
||||
* PURPOSE: CSRSS alias support functions
|
||||
* COPYRIGHT: Christoph Wittich
|
||||
* Johannes Anderwald
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct tagALIAS_ENTRY
|
||||
{
|
||||
LPCWSTR lpSource;
|
||||
LPCWSTR lpTarget;
|
||||
struct tagALIAS_ENTRY * Next;
|
||||
} ALIAS_ENTRY, *PALIAS_ENTRY;
|
||||
|
||||
|
||||
typedef struct tagALIAS_HEADER
|
||||
{
|
||||
LPCWSTR lpExeName;
|
||||
PALIAS_ENTRY Data;
|
||||
struct tagALIAS_HEADER * Next;
|
||||
|
||||
} ALIAS_HEADER, *PALIAS_HEADER;
|
||||
|
||||
static
|
||||
PALIAS_HEADER
|
||||
IntFindAliasHeader(PALIAS_HEADER RootHeader, LPCWSTR lpExeName)
|
||||
{
|
||||
while(RootHeader)
|
||||
{
|
||||
INT diff = _wcsicmp(RootHeader->lpExeName, lpExeName);
|
||||
if (!diff)
|
||||
return RootHeader;
|
||||
|
||||
if (diff > 0)
|
||||
break;
|
||||
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PALIAS_HEADER
|
||||
IntCreateAliasHeader(LPCWSTR lpExeName)
|
||||
{
|
||||
PALIAS_HEADER Entry;
|
||||
UINT dwLength = wcslen(lpExeName) + 1;
|
||||
|
||||
Entry = RtlAllocateHeap(Win32CsrApiHeap, 0, sizeof(ALIAS_HEADER) + sizeof(WCHAR) * dwLength);
|
||||
if (!Entry)
|
||||
return Entry;
|
||||
|
||||
Entry->lpExeName = (LPCWSTR)(Entry + 1);
|
||||
wcscpy((WCHAR*)Entry->lpExeName, lpExeName);
|
||||
Entry->Data = NULL;
|
||||
Entry->Next = NULL;
|
||||
return Entry;
|
||||
}
|
||||
|
||||
VOID
|
||||
IntInsertAliasHeader(PALIAS_HEADER * RootHeader, PALIAS_HEADER NewHeader)
|
||||
{
|
||||
PALIAS_HEADER CurrentHeader;
|
||||
PALIAS_HEADER *LastLink = RootHeader;
|
||||
|
||||
while ((CurrentHeader = *LastLink) != NULL)
|
||||
{
|
||||
INT Diff = _wcsicmp(NewHeader->lpExeName, CurrentHeader->lpExeName);
|
||||
if (Diff < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
LastLink = &CurrentHeader->Next;
|
||||
}
|
||||
|
||||
*LastLink = NewHeader;
|
||||
NewHeader->Next = CurrentHeader;
|
||||
}
|
||||
|
||||
PALIAS_ENTRY
|
||||
IntGetAliasEntry(PALIAS_HEADER Header, LPCWSTR lpSrcName)
|
||||
{
|
||||
PALIAS_ENTRY RootHeader;
|
||||
|
||||
if (Header == NULL)
|
||||
return NULL;
|
||||
|
||||
RootHeader = Header->Data;
|
||||
while(RootHeader)
|
||||
{
|
||||
INT diff;
|
||||
DPRINT("IntGetAliasEntry>lpSource %S\n", RootHeader->lpSource);
|
||||
diff = _wcsicmp(RootHeader->lpSource, lpSrcName);
|
||||
if (!diff)
|
||||
return RootHeader;
|
||||
|
||||
if (diff > 0)
|
||||
break;
|
||||
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
IntInsertAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY NewEntry)
|
||||
{
|
||||
PALIAS_ENTRY CurrentEntry;
|
||||
PALIAS_ENTRY *LastLink = &Header->Data;
|
||||
|
||||
while ((CurrentEntry = *LastLink) != NULL)
|
||||
{
|
||||
INT Diff = _wcsicmp(NewEntry->lpSource, CurrentEntry->lpSource);
|
||||
if (Diff < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
LastLink = &CurrentEntry->Next;
|
||||
}
|
||||
|
||||
*LastLink = NewEntry;
|
||||
NewEntry->Next = CurrentEntry;
|
||||
}
|
||||
|
||||
PALIAS_ENTRY
|
||||
IntCreateAliasEntry(LPCWSTR lpSource, LPCWSTR lpTarget)
|
||||
{
|
||||
UINT dwSource;
|
||||
UINT dwTarget;
|
||||
PALIAS_ENTRY Entry;
|
||||
|
||||
dwSource = wcslen(lpSource) + 1;
|
||||
dwTarget = wcslen(lpTarget) + 1;
|
||||
|
||||
Entry = RtlAllocateHeap(Win32CsrApiHeap, 0, sizeof(ALIAS_ENTRY) + sizeof(WCHAR) * (dwSource + dwTarget));
|
||||
if (!Entry)
|
||||
return Entry;
|
||||
|
||||
Entry->lpSource = (LPCWSTR)(Entry + 1);
|
||||
wcscpy((LPWSTR)Entry->lpSource, lpSource);
|
||||
Entry->lpTarget = Entry->lpSource + dwSource;
|
||||
wcscpy((LPWSTR)Entry->lpTarget, lpTarget);
|
||||
Entry->Next = NULL;
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetConsoleAliasesExesLength(PALIAS_HEADER RootHeader)
|
||||
{
|
||||
UINT length = 0;
|
||||
|
||||
while(RootHeader)
|
||||
{
|
||||
length += (wcslen(RootHeader->lpExeName) + 1) * sizeof(WCHAR);
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
if (length)
|
||||
length += sizeof(WCHAR); // last entry entry is terminated with 2 zero bytes
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetConsoleAliasesExes(PALIAS_HEADER RootHeader, LPWSTR TargetBuffer, UINT TargetBufferSize)
|
||||
{
|
||||
UINT Offset = 0;
|
||||
UINT Length;
|
||||
|
||||
TargetBufferSize /= sizeof(WCHAR);
|
||||
while(RootHeader)
|
||||
{
|
||||
Length = wcslen(RootHeader->lpExeName) + 1;
|
||||
if (TargetBufferSize > Offset + Length)
|
||||
{
|
||||
wcscpy(&TargetBuffer[Offset], RootHeader->lpExeName);
|
||||
Offset += Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
RootHeader = RootHeader->Next;
|
||||
}
|
||||
Length = min(Offset+1, TargetBufferSize);
|
||||
TargetBuffer[Length] = L'\0';
|
||||
return Length * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
UINT
|
||||
IntGetAllConsoleAliasesLength(PALIAS_HEADER Header)
|
||||
{
|
||||
UINT Length = 0;
|
||||
PALIAS_ENTRY CurEntry = Header->Data;
|
||||
|
||||
while(CurEntry)
|
||||
{
|
||||
Length += wcslen(CurEntry->lpSource);
|
||||
Length += wcslen(CurEntry->lpTarget);
|
||||
Length += 2; // zero byte and '='
|
||||
CurEntry = CurEntry->Next;
|
||||
}
|
||||
|
||||
if (Length)
|
||||
{
|
||||
return (Length+1) * sizeof(WCHAR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
UINT
|
||||
IntGetAllConsoleAliases(PALIAS_HEADER Header, LPWSTR TargetBuffer, UINT TargetBufferLength)
|
||||
{
|
||||
PALIAS_ENTRY CurEntry = Header->Data;
|
||||
UINT Offset = 0;
|
||||
UINT SrcLength, TargetLength;
|
||||
|
||||
TargetBufferLength /= sizeof(WCHAR);
|
||||
while(CurEntry)
|
||||
{
|
||||
SrcLength = wcslen(CurEntry->lpSource) + 1;
|
||||
TargetLength = wcslen(CurEntry->lpTarget) + 1;
|
||||
if (Offset + TargetLength + SrcLength >= TargetBufferLength)
|
||||
break;
|
||||
|
||||
wcscpy(&TargetBuffer[Offset], CurEntry->lpSource);
|
||||
Offset += SrcLength;
|
||||
TargetBuffer[Offset] = L'=';
|
||||
wcscpy(&TargetBuffer[Offset], CurEntry->lpTarget);
|
||||
Offset += TargetLength;
|
||||
|
||||
CurEntry = CurEntry->Next;
|
||||
}
|
||||
TargetBuffer[Offset] = L'\0';
|
||||
return Offset * sizeof(WCHAR);
|
||||
}
|
||||
VOID
|
||||
IntDeleteAliasEntry(PALIAS_HEADER Header, PALIAS_ENTRY Entry)
|
||||
{
|
||||
PALIAS_ENTRY *LastLink = &Header->Data;
|
||||
PALIAS_ENTRY CurEntry;
|
||||
|
||||
while ((CurEntry = *LastLink) != NULL)
|
||||
{
|
||||
if (CurEntry == Entry)
|
||||
{
|
||||
*LastLink = Entry->Next;
|
||||
RtlFreeHeap(Win32CsrApiHeap, 0, Entry);
|
||||
return;
|
||||
}
|
||||
LastLink = &CurEntry->Next;
|
||||
}
|
||||
}
|
||||
VOID
|
||||
IntDeleteAllAliases(PALIAS_HEADER RootHeader)
|
||||
{
|
||||
PALIAS_HEADER Header, NextHeader;
|
||||
PALIAS_ENTRY Entry, NextEntry;
|
||||
for (Header = RootHeader; Header; Header = NextHeader)
|
||||
{
|
||||
NextHeader = Header->Next;
|
||||
for (Entry = Header->Data; Entry; Entry = NextEntry)
|
||||
{
|
||||
NextEntry = Entry->Next;
|
||||
RtlFreeHeap(Win32CsrApiHeap, 0, Entry);
|
||||
}
|
||||
RtlFreeHeap(Win32CsrApiHeap, 0, Header);
|
||||
}
|
||||
}
|
||||
|
||||
CSR_API(CsrAddConsoleAlias)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
PALIAS_HEADER Header;
|
||||
PALIAS_ENTRY Entry;
|
||||
WCHAR * lpExeName;
|
||||
WCHAR * lpSource;
|
||||
WCHAR * lpTarget;
|
||||
//ULONG TotalLength;
|
||||
//WCHAR * Ptr;
|
||||
|
||||
//TotalLength = Request->Data.AddConsoleAlias.SourceLength + Request->Data.AddConsoleAlias.ExeLength + Request->Data.AddConsoleAlias.TargetLength;
|
||||
//Ptr = (WCHAR*)((ULONG_PTR)Request + sizeof(CSR_API_MESSAGE));
|
||||
|
||||
lpSource = (WCHAR*)((ULONG_PTR)Request + sizeof(CSR_API_MESSAGE));
|
||||
lpExeName = (WCHAR*)((ULONG_PTR)Request + sizeof(CSR_API_MESSAGE) + Request->Data.AddConsoleAlias.SourceLength * sizeof(WCHAR));
|
||||
lpTarget = (Request->Data.AddConsoleAlias.TargetLength != 0 ? lpExeName + Request->Data.AddConsoleAlias.ExeLength : NULL);
|
||||
|
||||
DPRINT("CsrAddConsoleAlias entered Request %p lpSource %p lpExeName %p lpTarget %p\n", Request, lpSource, lpExeName, lpTarget);
|
||||
|
||||
if (lpExeName == NULL || lpSource == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Request->Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (!NT_SUCCESS(Request->Status))
|
||||
{
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
|
||||
if (!Header && lpTarget != NULL)
|
||||
{
|
||||
Header = IntCreateAliasHeader(lpExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
IntInsertAliasHeader(&Console->Aliases, Header);
|
||||
}
|
||||
|
||||
if (lpTarget == NULL) // delete the entry
|
||||
{
|
||||
Entry = IntGetAliasEntry(Header, lpSource);
|
||||
if (Entry)
|
||||
{
|
||||
IntDeleteAliasEntry(Header, Entry);
|
||||
Request->Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Request->Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
ConioUnlockConsole(Console);
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
Entry = IntCreateAliasEntry(lpSource, lpTarget);
|
||||
|
||||
if (!Entry)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
IntInsertAliasEntry(Header, Entry);
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleAlias)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
PALIAS_HEADER Header;
|
||||
PALIAS_ENTRY Entry;
|
||||
UINT Length;
|
||||
WCHAR * lpExeName;
|
||||
WCHAR * lpSource;
|
||||
WCHAR * lpTarget;
|
||||
|
||||
lpSource = (LPWSTR)((ULONG_PTR)Request + sizeof(CSR_API_MESSAGE));
|
||||
lpExeName = lpSource + Request->Data.GetConsoleAlias.SourceLength;
|
||||
lpTarget = Request->Data.GetConsoleAlias.TargetBuffer;
|
||||
|
||||
|
||||
DPRINT("CsrGetConsoleAlias entered lpExeName %p lpSource %p TargetBuffer %p TargetBufferLength %u\n",
|
||||
lpExeName, lpSource, lpTarget, Request->Data.GetConsoleAlias.TargetBufferLength);
|
||||
|
||||
if (Request->Data.GetConsoleAlias.ExeLength == 0 || lpTarget == NULL ||
|
||||
Request->Data.GetConsoleAlias.TargetBufferLength == 0 || Request->Data.GetConsoleAlias.SourceLength == 0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Request->Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (!NT_SUCCESS(Request->Status))
|
||||
{
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, lpExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Entry = IntGetAliasEntry(Header, lpSource);
|
||||
if (!Entry)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Length = (wcslen(Entry->lpTarget)+1) * sizeof(WCHAR);
|
||||
if (Length > Request->Data.GetConsoleAlias.TargetBufferLength)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, lpTarget,
|
||||
Request->Data.GetConsoleAlias.TargetBufferLength, 1))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
wcscpy(lpTarget, Entry->lpTarget);
|
||||
Request->Data.GetConsoleAlias.BytesWritten = Length;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetAllConsoleAliases)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
ULONG BytesWritten;
|
||||
PALIAS_HEADER Header;
|
||||
|
||||
if (Request->Data.GetAllConsoleAlias.lpExeName == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Request->Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (!NT_SUCCESS(Request->Status))
|
||||
{
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, Request->Data.GetAllConsoleAlias.lpExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (IntGetAllConsoleAliasesLength(Header) > Request->Data.GetAllConsoleAlias.AliasBufferLength)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData,
|
||||
Request->Data.GetAllConsoleAlias.AliasBuffer,
|
||||
Request->Data.GetAllConsoleAlias.AliasBufferLength,
|
||||
1))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
BytesWritten = IntGetAllConsoleAliases(Header,
|
||||
Request->Data.GetAllConsoleAlias.AliasBuffer,
|
||||
Request->Data.GetAllConsoleAlias.AliasBufferLength);
|
||||
|
||||
Request->Data.GetAllConsoleAlias.BytesWritten = BytesWritten;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetAllConsoleAliasesLength)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
PALIAS_HEADER Header;
|
||||
UINT Length;
|
||||
|
||||
if (Request->Data.GetAllConsoleAliasesLength.lpExeName == NULL)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Request->Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (!NT_SUCCESS(Request->Status))
|
||||
{
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
Header = IntFindAliasHeader(Console->Aliases, Request->Data.GetAllConsoleAliasesLength.lpExeName);
|
||||
if (!Header)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Length = IntGetAllConsoleAliasesLength(Header);
|
||||
Request->Data.GetAllConsoleAliasesLength.Length = Length;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleAliasesExes)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
UINT BytesWritten;
|
||||
UINT ExesLength;
|
||||
|
||||
DPRINT("CsrGetConsoleAliasesExes entered\n");
|
||||
|
||||
Request->Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (!NT_SUCCESS(Request->Status))
|
||||
{
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
ExesLength = IntGetConsoleAliasesExesLength(Console->Aliases);
|
||||
|
||||
if (ExesLength > Request->Data.GetConsoleAliasesExes.Length)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (Request->Data.GetConsoleAliasesExes.ExeNames == NULL)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData,
|
||||
Request->Data.GetConsoleAliasesExes.ExeNames,
|
||||
Request->Data.GetConsoleAliasesExes.Length,
|
||||
1))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
BytesWritten = IntGetConsoleAliasesExes(Console->Aliases,
|
||||
Request->Data.GetConsoleAliasesExes.ExeNames,
|
||||
Request->Data.GetConsoleAliasesExes.Length);
|
||||
|
||||
Request->Data.GetConsoleAliasesExes.BytesWritten = BytesWritten;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleAliasesExesLength)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
DPRINT("CsrGetConsoleAliasesExesLength entered\n");
|
||||
|
||||
Request->Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Request->Status))
|
||||
{
|
||||
Request->Data.GetConsoleAliasesExesLength.Length = IntGetConsoleAliasesExesLength(Console->Aliases);
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Request->Status;
|
||||
}
|
||||
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
* reactos/subsys/csrss/win32csr/conio.c
|
||||
*
|
||||
* Console I/O functions
|
||||
*
|
||||
* ReactOS Operating System
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
|
||||
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
|
||||
|
||||
#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
|
||||
MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
CSR_API(CsrReadConsole)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput *Input;
|
||||
PCHAR Buffer;
|
||||
PWCHAR UnicodeBuffer;
|
||||
ULONG i = 0;
|
||||
ULONG nNumberOfCharsToRead, CharSize;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrReadConsole\n");
|
||||
|
||||
CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
|
||||
|
||||
nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead;
|
||||
|
||||
Buffer = (PCHAR)Request->Data.ReadConsoleRequest.Buffer;
|
||||
UnicodeBuffer = (PWCHAR)Buffer;
|
||||
if (!Win32CsrValidateBuffer(ProcessData, Buffer, nNumberOfCharsToRead, CharSize))
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
|
||||
&Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
|
||||
|
||||
Status = STATUS_PENDING; /* we haven't read anything (yet) */
|
||||
if (Console->Mode & ENABLE_LINE_INPUT)
|
||||
{
|
||||
if (Console->LineBuffer == NULL)
|
||||
{
|
||||
/* Starting a new line */
|
||||
Console->LineMaxSize = max(256, nNumberOfCharsToRead);
|
||||
Console->LineBuffer = HeapAlloc(Win32CsrApiHeap, 0, Console->LineMaxSize * sizeof(WCHAR));
|
||||
if (Console->LineBuffer == NULL)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
Console->LineComplete = FALSE;
|
||||
Console->LineUpPressed = FALSE;
|
||||
Console->LineInsertToggle = 0;
|
||||
Console->LineWakeupMask = Request->Data.ReadConsoleRequest.CtrlWakeupMask;
|
||||
Console->LineSize = Request->Data.ReadConsoleRequest.NrCharactersRead;
|
||||
Console->LinePos = Console->LineSize;
|
||||
/* pre-filling the buffer is only allowed in the Unicode API,
|
||||
* so we don't need to worry about conversion */
|
||||
memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
|
||||
if (Console->LineSize == Console->LineMaxSize)
|
||||
{
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a complete line yet, process the pending input */
|
||||
while (!Console->LineComplete && !IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
/* remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&Console->InputEvents);
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* only pay attention to key down */
|
||||
if (KEY_EVENT == Input->InputEvent.EventType
|
||||
&& Input->InputEvent.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
|
||||
Request->Data.ReadConsoleRequest.ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
|
||||
/* Check if we have a complete line to read from */
|
||||
if (Console->LineComplete)
|
||||
{
|
||||
while (i < nNumberOfCharsToRead && Console->LinePos != Console->LineSize)
|
||||
{
|
||||
WCHAR Char = Console->LineBuffer[Console->LinePos++];
|
||||
if (Request->Data.ReadConsoleRequest.Unicode)
|
||||
UnicodeBuffer[i++] = Char;
|
||||
else
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char);
|
||||
}
|
||||
if (Console->LinePos == Console->LineSize)
|
||||
{
|
||||
/* Entire line has been read */
|
||||
HeapFree(Win32CsrApiHeap, 0, Console->LineBuffer);
|
||||
Console->LineBuffer = NULL;
|
||||
}
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Character input */
|
||||
while (i < nNumberOfCharsToRead && !IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
/* remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&Console->InputEvents);
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* only pay attention to valid ascii chars, on key down */
|
||||
if (KEY_EVENT == Input->InputEvent.EventType
|
||||
&& Input->InputEvent.Event.KeyEvent.bKeyDown
|
||||
&& Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0')
|
||||
{
|
||||
WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
|
||||
if (Request->Data.ReadConsoleRequest.Unicode)
|
||||
UnicodeBuffer[i++] = Char;
|
||||
else
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char);
|
||||
Status = STATUS_SUCCESS; /* did read something */
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
}
|
||||
done:
|
||||
Request->Data.ReadConsoleRequest.NrCharactersRead = i;
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID FASTCALL
|
||||
ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
|
||||
{
|
||||
if (InputEvent->EventType == KEY_EVENT)
|
||||
{
|
||||
WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
|
||||
InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console,
|
||||
&InputEvent->Event.KeyEvent.uChar.AsciiChar,
|
||||
&UnicodeChar);
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS FASTCALL
|
||||
ConioProcessChar(PCSRSS_CONSOLE Console,
|
||||
PINPUT_RECORD InputEvent)
|
||||
{
|
||||
ConsoleInput *ConInRec;
|
||||
|
||||
/* Check for pause or unpause */
|
||||
if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
|
||||
if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
|
||||
{
|
||||
DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
|
||||
if (Console->Mode & ENABLE_LINE_INPUT &&
|
||||
(vk == VK_PAUSE || (vk == 'S' &&
|
||||
(cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
|
||||
!(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
|
||||
{
|
||||
ConioPause(Console, PAUSED_FROM_KEYBOARD);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN &&
|
||||
vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
|
||||
{
|
||||
ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add event to the queue */
|
||||
ConInRec = RtlAllocateHeap(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
|
||||
if (ConInRec == NULL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
ConInRec->InputEvent = *InputEvent;
|
||||
InsertTailList(&Console->InputEvents, &ConInRec->ListEntry);
|
||||
SetEvent(Console->ActiveEvent);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD FASTCALL
|
||||
ConioGetShiftState(PBYTE KeyState)
|
||||
{
|
||||
DWORD ssOut = 0;
|
||||
|
||||
if (KeyState[VK_CAPITAL] & 1)
|
||||
ssOut |= CAPSLOCK_ON;
|
||||
|
||||
if (KeyState[VK_NUMLOCK] & 1)
|
||||
ssOut |= NUMLOCK_ON;
|
||||
|
||||
if (KeyState[VK_SCROLL] & 1)
|
||||
ssOut |= SCROLLLOCK_ON;
|
||||
|
||||
if (KeyState[VK_SHIFT] & 0x80)
|
||||
ssOut |= SHIFT_PRESSED;
|
||||
|
||||
if (KeyState[VK_LCONTROL] & 0x80)
|
||||
ssOut |= LEFT_CTRL_PRESSED;
|
||||
if (KeyState[VK_RCONTROL] & 0x80)
|
||||
ssOut |= RIGHT_CTRL_PRESSED;
|
||||
|
||||
if (KeyState[VK_LMENU] & 0x80)
|
||||
ssOut |= LEFT_ALT_PRESSED;
|
||||
if (KeyState[VK_RMENU] & 0x80)
|
||||
ssOut |= RIGHT_ALT_PRESSED;
|
||||
|
||||
return ssOut;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
|
||||
{
|
||||
static BYTE KeyState[256] = { 0 };
|
||||
/* MSDN mentions that you should use the last virtual key code received
|
||||
* when putting a virtual key identity to a WM_CHAR message since multiple
|
||||
* or translated keys may be involved. */
|
||||
static UINT LastVirtualKey = 0;
|
||||
DWORD ShiftState;
|
||||
UINT RepeatCount;
|
||||
WCHAR UnicodeChar;
|
||||
UINT VirtualKeyCode;
|
||||
UINT VirtualScanCode;
|
||||
BOOL Down = FALSE;
|
||||
INPUT_RECORD er;
|
||||
BOOLEAN Fake; // synthesized, not a real event
|
||||
BOOLEAN NotChar; // message should not be used to return a character
|
||||
|
||||
RepeatCount = 1;
|
||||
VirtualScanCode = (msg->lParam >> 16) & 0xff;
|
||||
Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
|
||||
msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
|
||||
|
||||
GetKeyboardState(KeyState);
|
||||
ShiftState = ConioGetShiftState(KeyState);
|
||||
|
||||
if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
|
||||
{
|
||||
VirtualKeyCode = LastVirtualKey;
|
||||
UnicodeChar = msg->wParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR Chars[2];
|
||||
INT RetChars = 0;
|
||||
|
||||
VirtualKeyCode = msg->wParam;
|
||||
RetChars = ToUnicodeEx(VirtualKeyCode,
|
||||
VirtualScanCode,
|
||||
KeyState,
|
||||
Chars,
|
||||
2,
|
||||
0,
|
||||
0);
|
||||
UnicodeChar = (1 == RetChars ? Chars[0] : 0);
|
||||
}
|
||||
|
||||
er.EventType = KEY_EVENT;
|
||||
er.Event.KeyEvent.bKeyDown = Down;
|
||||
er.Event.KeyEvent.wRepeatCount = RepeatCount;
|
||||
er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
|
||||
er.Event.KeyEvent.dwControlKeyState = ShiftState;
|
||||
er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
|
||||
er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
|
||||
|
||||
if (TextMode)
|
||||
{
|
||||
if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
|
||||
&& VK_TAB == VirtualKeyCode)
|
||||
{
|
||||
if (Down)
|
||||
{
|
||||
TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (VK_MENU == VirtualKeyCode && ! Down)
|
||||
{
|
||||
if (TuiSwapConsole(0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) || KeyState[VK_MENU] & 0x80) &&
|
||||
(VirtualKeyCode == VK_ESCAPE || VirtualKeyCode == VK_TAB || VirtualKeyCode == VK_SPACE))
|
||||
{
|
||||
DefWindowProcW( msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == Console)
|
||||
{
|
||||
DPRINT1("No Active Console!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Fake = UnicodeChar &&
|
||||
(msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
|
||||
msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
|
||||
NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
|
||||
if (NotChar)
|
||||
LastVirtualKey = msg->wParam;
|
||||
|
||||
DPRINT ("csrss: %s %s %s %s %02x %02x '%lc' %04x\n",
|
||||
Down ? "down" : "up ",
|
||||
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
|
||||
"char" : "key ",
|
||||
Fake ? "fake" : "real",
|
||||
NotChar ? "notc" : "char",
|
||||
VirtualScanCode,
|
||||
VirtualKeyCode,
|
||||
(UnicodeChar >= L' ') ? UnicodeChar : L'.',
|
||||
ShiftState);
|
||||
|
||||
if (Fake)
|
||||
return;
|
||||
|
||||
/* process Ctrl-C and Ctrl-Break */
|
||||
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
|
||||
er.Event.KeyEvent.bKeyDown &&
|
||||
((er.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
|
||||
(er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
|
||||
(er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80))
|
||||
{
|
||||
PCSR_PROCESS current;
|
||||
PLIST_ENTRY current_entry;
|
||||
DPRINT1("Console_Api Ctrl-C\n");
|
||||
current_entry = Console->ProcessList.Flink;
|
||||
while (current_entry != &Console->ProcessList)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
|
||||
current_entry = current_entry->Flink;
|
||||
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
|
||||
}
|
||||
if (Console->LineBuffer && !Console->LineComplete)
|
||||
{
|
||||
/* Line input is in progress; end it */
|
||||
Console->LinePos = Console->LineSize = 0;
|
||||
Console->LineComplete = TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != (er.Event.KeyEvent.dwControlKeyState
|
||||
& (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
|
||||
&& (VK_UP == er.Event.KeyEvent.wVirtualKeyCode
|
||||
|| VK_DOWN == er.Event.KeyEvent.wVirtualKeyCode))
|
||||
{
|
||||
if (er.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
/* scroll up or down */
|
||||
if (VK_UP == er.Event.KeyEvent.wVirtualKeyCode)
|
||||
{
|
||||
/* only scroll up if there is room to scroll up into */
|
||||
if (Console->ActiveBuffer->CurrentY != Console->ActiveBuffer->MaxY - 1)
|
||||
{
|
||||
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
|
||||
Console->ActiveBuffer->MaxY - 1) %
|
||||
Console->ActiveBuffer->MaxY;
|
||||
Console->ActiveBuffer->CurrentY++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only scroll down if there is room to scroll down into */
|
||||
if (Console->ActiveBuffer->CurrentY != 0)
|
||||
{
|
||||
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
|
||||
Console->ActiveBuffer->MaxY;
|
||||
Console->ActiveBuffer->CurrentY--;
|
||||
}
|
||||
}
|
||||
ConioDrawConsole(Console);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ConioProcessChar(Console, &er);
|
||||
}
|
||||
|
||||
CSR_API(CsrReadInputEvent)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Done = FALSE;
|
||||
ConsoleInput *Input;
|
||||
|
||||
DPRINT("CsrReadInputEvent\n");
|
||||
|
||||
Request->Data.ReadInputRequest.Event = ProcessData->ConsoleEvent;
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* only get input if there is any */
|
||||
CurrentEntry = Console->InputEvents.Flink;
|
||||
while (CurrentEntry != &Console->InputEvents)
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
|
||||
if (Done)
|
||||
{
|
||||
Request->Data.ReadInputRequest.MoreEvents = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
|
||||
if (!Done)
|
||||
{
|
||||
Request->Data.ReadInputRequest.Input = Input->InputEvent;
|
||||
if (Request->Data.ReadInputRequest.Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, &Request->Data.ReadInputRequest.Input);
|
||||
}
|
||||
Done = TRUE;
|
||||
}
|
||||
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
|
||||
if (Done)
|
||||
Status = STATUS_SUCCESS;
|
||||
else
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrFlushInputBuffer)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCSRSS_CONSOLE Console;
|
||||
ConsoleInput* Input;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrFlushInputBuffer\n");
|
||||
|
||||
Status = ConioLockConsole(ProcessData,
|
||||
Request->Data.FlushInputBufferRequest.ConsoleInput,
|
||||
&Console,
|
||||
GENERIC_WRITE);
|
||||
if(! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Discard all entries in the input event queue */
|
||||
while (!IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&Console->InputEvents);
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
/* Destroy the event */
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetNumberOfConsoleInputEvents)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PLIST_ENTRY CurrentItem;
|
||||
DWORD NumEvents;
|
||||
|
||||
DPRINT("CsrGetNumberOfConsoleInputEvents\n");
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
CurrentItem = Console->InputEvents.Flink;
|
||||
NumEvents = 0;
|
||||
|
||||
/* If there are any events ... */
|
||||
while (CurrentItem != &Console->InputEvents)
|
||||
{
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
NumEvents++;
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.GetNumInputEventsRequest.NumInputEvents = NumEvents;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrPeekConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
DWORD Length;
|
||||
PLIST_ENTRY CurrentItem;
|
||||
PINPUT_RECORD InputRecord;
|
||||
ConsoleInput* Item;
|
||||
UINT NumItems;
|
||||
|
||||
DPRINT("CsrPeekConsoleInput\n");
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console, GENERIC_READ);
|
||||
if(! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord;
|
||||
Length = Request->Data.PeekConsoleInputRequest.Length;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD)))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
NumItems = 0;
|
||||
|
||||
if (! IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
CurrentItem = Console->InputEvents.Flink;
|
||||
|
||||
while (CurrentItem != &Console->InputEvents && NumItems < Length)
|
||||
{
|
||||
Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
|
||||
|
||||
++NumItems;
|
||||
*InputRecord = Item->InputEvent;
|
||||
|
||||
if (Request->Data.PeekConsoleInputRequest.Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, InputRecord);
|
||||
}
|
||||
|
||||
InputRecord++;
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.PeekConsoleInputRequest.Length = NumItems;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrWriteConsoleInput)
|
||||
{
|
||||
PINPUT_RECORD InputRecord;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
DWORD Length;
|
||||
DWORD i;
|
||||
|
||||
DPRINT("CsrWriteConsoleInput\n");
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, &Console, GENERIC_WRITE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord;
|
||||
Length = Request->Data.WriteConsoleInputRequest.Length;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, InputRecord, Length, sizeof(INPUT_RECORD)))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
for (i = 0; i < Length && NT_SUCCESS(Status); i++)
|
||||
{
|
||||
if (!Request->Data.WriteConsoleInputRequest.Unicode &&
|
||||
InputRecord->EventType == KEY_EVENT)
|
||||
{
|
||||
CHAR AsciiChar = InputRecord->Event.KeyEvent.uChar.AsciiChar;
|
||||
ConsoleInputAnsiCharToUnicodeChar(Console,
|
||||
&InputRecord->Event.KeyEvent.uChar.UnicodeChar,
|
||||
&AsciiChar);
|
||||
}
|
||||
Status = ConioProcessChar(Console, InputRecord++);
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.WriteConsoleInputRequest.Length = i;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/include/conio.h
|
||||
* PURPOSE: CSRSS internal console I/O interface
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api.h"
|
||||
#include "win32csr.h"
|
||||
|
||||
#define CSR_DEFAULT_CURSOR_SIZE 25
|
||||
|
||||
/* Object type magic numbers */
|
||||
|
||||
#define CONIO_CONSOLE_MAGIC 0x00000001
|
||||
#define CONIO_SCREEN_BUFFER_MAGIC 0x00000002
|
||||
|
||||
/************************************************************************
|
||||
* Screen buffer structure represents the win32 screen buffer object. *
|
||||
* Internally, the portion of the buffer being shown CAN loop past the *
|
||||
* bottom of the virtual buffer and wrap around to the top. Win32 does *
|
||||
* not do this. I decided to do this because it eliminates the need to *
|
||||
* do a massive memcpy() to scroll the contents of the buffer up to *
|
||||
* scroll the screen on output, instead I just shift down the position *
|
||||
* to be displayed, and let it wrap around to the top again. *
|
||||
* The VirtualY member keeps track of the top Y coord that win32 *
|
||||
* clients THINK is currently being displayed, because they think that *
|
||||
* when the display reaches the bottom of the buffer and another line *
|
||||
* being printed causes another line to scroll down, that the buffer IS *
|
||||
* memcpy()'s up, and the bottom of the buffer is still displayed, but *
|
||||
* internally, I just wrap back to the top of the buffer. *
|
||||
***********************************************************************/
|
||||
|
||||
typedef struct tagCSRSS_SCREEN_BUFFER
|
||||
{
|
||||
Object_t Header; /* Object header */
|
||||
BYTE *Buffer; /* pointer to screen buffer */
|
||||
USHORT MaxX, MaxY; /* size of the entire scrollback buffer */
|
||||
USHORT ShowX, ShowY; /* beginning offset for the actual display area */
|
||||
ULONG CurrentX; /* Current X cursor position */
|
||||
ULONG CurrentY; /* Current Y cursor position */
|
||||
WORD DefaultAttrib; /* default char attribute */
|
||||
USHORT VirtualY; /* top row of buffer being displayed, reported to callers */
|
||||
CONSOLE_CURSOR_INFO CursorInfo;
|
||||
USHORT Mode;
|
||||
LIST_ENTRY ListEntry; /* entry in console's list of buffers */
|
||||
} CSRSS_SCREEN_BUFFER, *PCSRSS_SCREEN_BUFFER;
|
||||
|
||||
typedef struct tagCSRSS_CONSOLE *PCSRSS_CONSOLE;
|
||||
|
||||
typedef struct tagCSRSS_CONSOLE_VTBL
|
||||
{
|
||||
VOID (WINAPI *InitScreenBuffer)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer);
|
||||
VOID (WINAPI *WriteStream)(PCSRSS_CONSOLE Console, SMALL_RECT *Block, LONG CursorStartX, LONG CursorStartY,
|
||||
UINT ScrolledLines, CHAR *Buffer, UINT Length);
|
||||
VOID (WINAPI *DrawRegion)(PCSRSS_CONSOLE Console, SMALL_RECT *Region);
|
||||
BOOL (WINAPI *SetCursorInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer);
|
||||
BOOL (WINAPI *SetScreenInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer,
|
||||
UINT OldCursorX, UINT OldCursorY);
|
||||
BOOL (WINAPI *UpdateScreenInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer);
|
||||
BOOL (WINAPI *ChangeTitle)(PCSRSS_CONSOLE Console);
|
||||
VOID (WINAPI *CleanupConsole)(PCSRSS_CONSOLE Console);
|
||||
BOOL (WINAPI *ChangeIcon)(PCSRSS_CONSOLE Console, HICON hWindowIcon);
|
||||
NTSTATUS (WINAPI *ResizeBuffer)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, COORD Size);
|
||||
} CSRSS_CONSOLE_VTBL, *PCSRSS_CONSOLE_VTBL;
|
||||
|
||||
typedef struct tagCSRSS_CONSOLE
|
||||
{
|
||||
Object_t Header; /* Object header */
|
||||
LONG ReferenceCount;
|
||||
CRITICAL_SECTION Lock;
|
||||
PCSRSS_CONSOLE Prev, Next; /* Next and Prev consoles in console wheel */
|
||||
HANDLE ActiveEvent;
|
||||
LIST_ENTRY InputEvents; /* List head for input event queue */
|
||||
PWCHAR LineBuffer; /* current line being input, in line buffered mode */
|
||||
WORD LineMaxSize; /* maximum size of line in characters (including CR+LF) */
|
||||
WORD LineSize; /* current size of line */
|
||||
WORD LinePos; /* current position within line */
|
||||
BOOLEAN LineComplete; /* user pressed enter, ready to send back to client */
|
||||
BOOLEAN LineUpPressed;
|
||||
BOOLEAN LineInsertToggle; /* replace character over cursor instead of inserting */
|
||||
ULONG LineWakeupMask; /* bitmap of which control characters will end line input */
|
||||
LIST_ENTRY HistoryBuffers;
|
||||
WORD HistoryBufferSize; /* size for newly created history buffers */
|
||||
WORD NumberOfHistoryBuffers; /* maximum number of history buffers allowed */
|
||||
BOOLEAN HistoryNoDup; /* remove old duplicate history entries */
|
||||
LIST_ENTRY BufferList; /* List of all screen buffers for this console */
|
||||
PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
|
||||
WORD Mode; /* Console mode flags */
|
||||
UNICODE_STRING Title; /* Title of console */
|
||||
DWORD HardwareState; /* _GDI_MANAGED, _DIRECT */
|
||||
HWND hWindow;
|
||||
COORD Size;
|
||||
PVOID PrivateData;
|
||||
UINT CodePage;
|
||||
UINT OutputCodePage;
|
||||
PCSRSS_CONSOLE_VTBL Vtbl;
|
||||
LIST_ENTRY ProcessList;
|
||||
struct tagALIAS_HEADER *Aliases;
|
||||
CONSOLE_SELECTION_INFO Selection;
|
||||
BYTE PauseFlags;
|
||||
HANDLE UnpauseEvent;
|
||||
} CSRSS_CONSOLE;
|
||||
|
||||
typedef struct ConsoleInput_t
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
INPUT_RECORD InputEvent;
|
||||
} ConsoleInput;
|
||||
|
||||
/* CONSOLE_SELECTION_INFO dwFlags values */
|
||||
#define CONSOLE_NO_SELECTION 0x0
|
||||
#define CONSOLE_SELECTION_IN_PROGRESS 0x1
|
||||
#define CONSOLE_SELECTION_NOT_EMPTY 0x2
|
||||
#define CONSOLE_MOUSE_SELECTION 0x4
|
||||
#define CONSOLE_MOUSE_DOWN 0x8
|
||||
/* HistoryFlags values */
|
||||
#define HISTORY_NO_DUP_FLAG 0x1
|
||||
|
||||
/* PauseFlags values (internal only) */
|
||||
#define PAUSED_FROM_KEYBOARD 0x1
|
||||
#define PAUSED_FROM_SCROLLBAR 0x2
|
||||
#define PAUSED_FROM_SELECTION 0x4
|
||||
|
||||
#define ConioInitScreenBuffer(Console, Buff) (Console)->Vtbl->InitScreenBuffer((Console), (Buff))
|
||||
#define ConioDrawRegion(Console, Region) (Console)->Vtbl->DrawRegion((Console), (Region))
|
||||
#define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \
|
||||
(Console)->Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \
|
||||
(ScrolledLines), (Buffer), (Length))
|
||||
#define ConioSetCursorInfo(Console, Buff) (Console)->Vtbl->SetCursorInfo((Console), (Buff))
|
||||
#define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \
|
||||
(Console)->Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY))
|
||||
#define ConioUpdateScreenInfo(Console, Buff) \
|
||||
(Console)->Vtbl->UpdateScreenInfo(Console, Buff)
|
||||
#define ConioChangeTitle(Console) (Console)->Vtbl->ChangeTitle(Console)
|
||||
#define ConioCleanupConsole(Console) (Console)->Vtbl->CleanupConsole(Console)
|
||||
#define ConioChangeIcon(Console, hWindowIcon) (Console)->Vtbl->ChangeIcon(Console, hWindowIcon)
|
||||
#define ConioResizeBuffer(Console, Buff, Size) (Console)->Vtbl->ResizeBuffer(Console, Buff, Size)
|
||||
|
||||
/* console.c */
|
||||
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCSR_PROCESS ProcessData, PCSRSS_CONSOLE *Console);
|
||||
VOID WINAPI ConioDeleteConsole(Object_t *Object);
|
||||
VOID WINAPI CsrInitConsoleSupport(VOID);
|
||||
VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioConsoleCtrlEvent(DWORD Event, PCSR_PROCESS ProcessData);
|
||||
VOID FASTCALL ConioConsoleCtrlEventTimeout(DWORD Event, PCSR_PROCESS ProcessData,
|
||||
DWORD Timeout);
|
||||
CSR_API(CsrAllocConsole);
|
||||
CSR_API(CsrFreeConsole);
|
||||
CSR_API(CsrSetConsoleMode);
|
||||
CSR_API(CsrGetConsoleMode);
|
||||
CSR_API(CsrSetTitle);
|
||||
CSR_API(CsrGetTitle);
|
||||
CSR_API(CsrHardwareStateProperty);
|
||||
CSR_API(CsrGetConsoleWindow);
|
||||
CSR_API(CsrSetConsoleIcon);
|
||||
CSR_API(CsrGetConsoleCodePage);
|
||||
CSR_API(CsrSetConsoleCodePage);
|
||||
CSR_API(CsrGetConsoleOutputCodePage);
|
||||
CSR_API(CsrSetConsoleOutputCodePage);
|
||||
CSR_API(CsrGetProcessList);
|
||||
CSR_API(CsrGenerateCtrlEvent);
|
||||
CSR_API(CsrGetConsoleSelectionInfo);
|
||||
|
||||
/* coninput.c */
|
||||
#define ConioLockConsole(ProcessData, Handle, Ptr, Access) \
|
||||
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), Access, CONIO_CONSOLE_MAGIC)
|
||||
#define ConioUnlockConsole(Console) \
|
||||
Win32CsrUnlockObject((Object_t *) Console)
|
||||
void WINAPI ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode);
|
||||
CSR_API(CsrReadConsole);
|
||||
CSR_API(CsrReadInputEvent);
|
||||
CSR_API(CsrFlushInputBuffer);
|
||||
CSR_API(CsrGetNumberOfConsoleInputEvents);
|
||||
CSR_API(CsrPeekConsoleInput);
|
||||
CSR_API(CsrWriteConsoleInput);
|
||||
|
||||
/* conoutput.c */
|
||||
#define ConioRectHeight(Rect) \
|
||||
(((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1)
|
||||
#define ConioRectWidth(Rect) \
|
||||
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
|
||||
#define ConioLockScreenBuffer(ProcessData, Handle, Ptr, Access) \
|
||||
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), Access, CONIO_SCREEN_BUFFER_MAGIC)
|
||||
#define ConioUnlockScreenBuffer(Buff) \
|
||||
Win32CsrUnlockObject((Object_t *) Buff)
|
||||
PBYTE FASTCALL ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buf, ULONG X, ULONG Y);
|
||||
VOID FASTCALL ConioDrawConsole(PCSRSS_CONSOLE Console);
|
||||
NTSTATUS FASTCALL ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
|
||||
CHAR *Buffer, DWORD Length, BOOL Attrib);
|
||||
NTSTATUS FASTCALL CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer);
|
||||
VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer);
|
||||
DWORD FASTCALL ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale);
|
||||
|
||||
CSR_API(CsrWriteConsole);
|
||||
CSR_API(CsrGetScreenBufferInfo);
|
||||
CSR_API(CsrSetCursor);
|
||||
CSR_API(CsrWriteConsoleOutputChar);
|
||||
CSR_API(CsrFillOutputChar);
|
||||
CSR_API(CsrWriteConsoleOutputAttrib);
|
||||
CSR_API(CsrFillOutputAttrib);
|
||||
CSR_API(CsrGetCursorInfo);
|
||||
CSR_API(CsrSetCursorInfo);
|
||||
CSR_API(CsrSetTextAttrib);
|
||||
CSR_API(CsrCreateScreenBuffer);
|
||||
CSR_API(CsrSetScreenBuffer);
|
||||
CSR_API(CsrWriteConsoleOutput);
|
||||
CSR_API(CsrScrollConsoleScreenBuffer);
|
||||
CSR_API(CsrReadConsoleOutputChar);
|
||||
CSR_API(CsrReadConsoleOutputAttrib);
|
||||
CSR_API(CsrReadConsoleOutput);
|
||||
CSR_API(CsrSetScreenBufferSize);
|
||||
|
||||
/* alias.c */
|
||||
VOID IntDeleteAllAliases(struct tagALIAS_HEADER *RootHeader);
|
||||
CSR_API(CsrAddConsoleAlias);
|
||||
CSR_API(CsrGetConsoleAlias);
|
||||
CSR_API(CsrGetAllConsoleAliases);
|
||||
CSR_API(CsrGetAllConsoleAliasesLength);
|
||||
CSR_API(CsrGetConsoleAliasesExes);
|
||||
CSR_API(CsrGetConsoleAliasesExesLength);
|
||||
|
||||
/* lineinput.c */
|
||||
struct tagHISTORY_BUFFER;
|
||||
VOID FASTCALL HistoryDeleteBuffer(struct tagHISTORY_BUFFER *Hist);
|
||||
CSR_API(CsrGetCommandHistoryLength);
|
||||
CSR_API(CsrGetCommandHistory);
|
||||
CSR_API(CsrExpungeCommandHistory);
|
||||
CSR_API(CsrSetHistoryNumberCommands);
|
||||
CSR_API(CsrGetHistoryInfo);
|
||||
CSR_API(CsrSetHistoryInfo);
|
||||
VOID FASTCALL LineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent);
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,832 @@
|
||||
/*
|
||||
* reactos/subsys/csrss/win32csr/conio.c
|
||||
*
|
||||
* Console I/O functions
|
||||
*
|
||||
* ReactOS Operating System
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
ConioConsoleFromProcessData(PCSR_PROCESS ProcessData, PCSRSS_CONSOLE *Console)
|
||||
{
|
||||
PCSRSS_CONSOLE ProcessConsole;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
ProcessConsole = ProcessData->Console;
|
||||
|
||||
if (!ProcessConsole)
|
||||
{
|
||||
*Console = NULL;
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
InterlockedIncrement(&ProcessConsole->ReferenceCount);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
EnterCriticalSection(&(ProcessConsole->Lock));
|
||||
*Console = ProcessConsole;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConioConsoleCtrlEventTimeout(DWORD Event, PCSR_PROCESS ProcessData, DWORD Timeout)
|
||||
{
|
||||
HANDLE Thread;
|
||||
|
||||
DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->ClientId.UniqueProcess);
|
||||
|
||||
if (ProcessData->CtrlDispatcher)
|
||||
{
|
||||
|
||||
Thread = CreateRemoteThread(ProcessData->ProcessHandle, NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
|
||||
UlongToPtr(Event), 0, NULL);
|
||||
if (NULL == Thread)
|
||||
{
|
||||
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
WaitForSingleObject(Thread, Timeout);
|
||||
CloseHandle(Thread);
|
||||
}
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConioConsoleCtrlEvent(DWORD Event, PCSR_PROCESS ProcessData)
|
||||
{
|
||||
ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI
|
||||
CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||
PCSRSS_SCREEN_BUFFER NewBuffer;
|
||||
BOOL GuiMode;
|
||||
WCHAR Title[255];
|
||||
HINSTANCE hInst;
|
||||
|
||||
Console->Title.MaximumLength = Console->Title.Length = 0;
|
||||
Console->Title.Buffer = NULL;
|
||||
|
||||
hInst = GetModuleHandleW(L"win32csr");
|
||||
if (LoadStringW(hInst,IDS_COMMAND_PROMPT,Title,sizeof(Title)/sizeof(Title[0])))
|
||||
{
|
||||
RtlCreateUnicodeString(&Console->Title, Title);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
|
||||
}
|
||||
|
||||
Console->ReferenceCount = 0;
|
||||
Console->LineBuffer = NULL;
|
||||
Console->Header.Type = CONIO_CONSOLE_MAGIC;
|
||||
Console->Header.Console = Console;
|
||||
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
|
||||
InitializeListHead(&Console->BufferList);
|
||||
Console->ActiveBuffer = NULL;
|
||||
InitializeListHead(&Console->InputEvents);
|
||||
InitializeListHead(&Console->HistoryBuffers);
|
||||
Console->CodePage = GetOEMCP();
|
||||
Console->OutputCodePage = GetOEMCP();
|
||||
|
||||
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
SecurityAttributes.lpSecurityDescriptor = NULL;
|
||||
SecurityAttributes.bInheritHandle = TRUE;
|
||||
|
||||
Console->ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
|
||||
if (NULL == Console->ActiveEvent)
|
||||
{
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
Console->PrivateData = NULL;
|
||||
InitializeCriticalSection(&Console->Lock);
|
||||
|
||||
GuiMode = DtbgIsDesktopVisible();
|
||||
|
||||
/* allocate console screen buffer */
|
||||
NewBuffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
|
||||
if (NULL == NewBuffer)
|
||||
{
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
CloseHandle(Console->ActiveEvent);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
/* init screen buffer with defaults */
|
||||
NewBuffer->CursorInfo.bVisible = TRUE;
|
||||
NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
|
||||
/* make console active, and insert into console list */
|
||||
Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
|
||||
|
||||
/*
|
||||
* If we are not in GUI-mode, start the text-mode console. If we fail,
|
||||
* try to start the GUI-mode console (win32k will automatically switch
|
||||
* to graphical mode, therefore no additional code is needed).
|
||||
*/
|
||||
if (!GuiMode)
|
||||
{
|
||||
DPRINT1("WIN32CSR: Opening text-mode console\n");
|
||||
Status = TuiInitConsole(Console);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to open text-mode console, switching to gui-mode, Status = 0x%08lx\n", Status);
|
||||
GuiMode = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to open the GUI-mode console. Two cases are possible:
|
||||
* - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
|
||||
* failed and we start GUI-mode console.
|
||||
* - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
|
||||
* succeeded BUT we failed at starting text-mode console. Then GuiMode
|
||||
* was switched to TRUE in order to try to open the console in GUI-mode.
|
||||
*/
|
||||
if (GuiMode)
|
||||
{
|
||||
DPRINT1("WIN32CSR: Opening GUI-mode console\n");
|
||||
Status = GuiInitConsole(Console, ShowCmd);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap,0, NewBuffer);
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
CloseHandle(Console->ActiveEvent);
|
||||
DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ConioCleanupConsole(Console);
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
CloseHandle(Console->ActiveEvent);
|
||||
HeapFree(Win32CsrApiHeap, 0, NewBuffer);
|
||||
DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* copy buffer contents to screen */
|
||||
ConioDrawConsole(Console);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrAllocConsole)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN NewConsole = FALSE;
|
||||
|
||||
DPRINT("CsrAllocConsole\n");
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
if (ProcessData->Console)
|
||||
{
|
||||
DPRINT1("Process already has a console\n");
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* If we don't need a console, then get out of here */
|
||||
if (!Request->Data.AllocConsoleRequest.ConsoleNeeded)
|
||||
{
|
||||
DPRINT("No console needed\n");
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* If we already have one, then don't create a new one... */
|
||||
if (!Request->Data.AllocConsoleRequest.Console ||
|
||||
Request->Data.AllocConsoleRequest.Console != ProcessData->ParentConsole)
|
||||
{
|
||||
/* Allocate a console structure */
|
||||
NewConsole = TRUE;
|
||||
Console = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
|
||||
if (NULL == Console)
|
||||
{
|
||||
DPRINT1("Not enough memory for console\n");
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
/* initialize list head */
|
||||
InitializeListHead(&Console->ProcessList);
|
||||
/* insert process data required for GUI initialization */
|
||||
InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
|
||||
/* Initialize the Console */
|
||||
Status = CsrInitConsole(Console, Request->Data.AllocConsoleRequest.ShowCmd);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Console init failed\n");
|
||||
HeapFree(Win32CsrApiHeap, 0, Console);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reuse our current console */
|
||||
Console = Request->Data.AllocConsoleRequest.Console;
|
||||
}
|
||||
|
||||
/* Set the Process Console */
|
||||
ProcessData->Console = Console;
|
||||
|
||||
/* Return it to the caller */
|
||||
Request->Data.AllocConsoleRequest.Console = Console;
|
||||
|
||||
/* Add a reference count because the process is tied to the console */
|
||||
_InterlockedIncrement(&Console->ReferenceCount);
|
||||
|
||||
if (NewConsole || !ProcessData->bInheritHandles)
|
||||
{
|
||||
/* Insert the Objects */
|
||||
Status = Win32CsrInsertObject(ProcessData,
|
||||
&Request->Data.AllocConsoleRequest.InputHandle,
|
||||
&Console->Header,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
TRUE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to insert object\n");
|
||||
ConioDeleteConsole((Object_t *) Console);
|
||||
ProcessData->Console = 0;
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Win32CsrInsertObject(ProcessData,
|
||||
&Request->Data.AllocConsoleRequest.OutputHandle,
|
||||
&Console->ActiveBuffer->Header,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
TRUE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to insert object\n");
|
||||
ConioDeleteConsole((Object_t *) Console);
|
||||
Win32CsrReleaseObject(ProcessData,
|
||||
Request->Data.AllocConsoleRequest.InputHandle);
|
||||
ProcessData->Console = 0;
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Duplicate the Event */
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
ProcessData->Console->ActiveEvent,
|
||||
ProcessData->ProcessHandle,
|
||||
&ProcessData->ConsoleEvent,
|
||||
EVENT_ALL_ACCESS,
|
||||
FALSE,
|
||||
0))
|
||||
{
|
||||
DPRINT1("DuplicateHandle() failed: %lu\n", GetLastError());
|
||||
ConioDeleteConsole((Object_t *) Console);
|
||||
if (NewConsole || !ProcessData->bInheritHandles)
|
||||
{
|
||||
Win32CsrReleaseObject(ProcessData,
|
||||
Request->Data.AllocConsoleRequest.OutputHandle);
|
||||
Win32CsrReleaseObject(ProcessData,
|
||||
Request->Data.AllocConsoleRequest.InputHandle);
|
||||
}
|
||||
ProcessData->Console = 0;
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set the Ctrl Dispatcher */
|
||||
ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher;
|
||||
DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
|
||||
|
||||
if (!NewConsole)
|
||||
{
|
||||
/* Insert into the list if it has not been added */
|
||||
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrFreeConsole)
|
||||
{
|
||||
Win32CsrReleaseConsole(ProcessData);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConioDeleteConsole(Object_t *Object)
|
||||
{
|
||||
PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
|
||||
ConsoleInput *Event;
|
||||
|
||||
DPRINT("ConioDeleteConsole\n");
|
||||
|
||||
/* Drain input event queue */
|
||||
while (Console->InputEvents.Flink != &Console->InputEvents)
|
||||
{
|
||||
Event = (ConsoleInput *) Console->InputEvents.Flink;
|
||||
Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
|
||||
Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
|
||||
HeapFree(Win32CsrApiHeap, 0, Event);
|
||||
}
|
||||
|
||||
ConioCleanupConsole(Console);
|
||||
if (Console->LineBuffer)
|
||||
RtlFreeHeap(Win32CsrApiHeap, 0, Console->LineBuffer);
|
||||
while (!IsListEmpty(&Console->HistoryBuffers))
|
||||
HistoryDeleteBuffer((struct tagHISTORY_BUFFER *)Console->HistoryBuffers.Flink);
|
||||
|
||||
ConioDeleteScreenBuffer(Console->ActiveBuffer);
|
||||
if (!IsListEmpty(&Console->BufferList))
|
||||
{
|
||||
DPRINT1("BUG: screen buffer list not empty\n");
|
||||
}
|
||||
|
||||
CloseHandle(Console->ActiveEvent);
|
||||
if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
IntDeleteAllAliases(Console->Aliases);
|
||||
HeapFree(Win32CsrApiHeap, 0, Console);
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
CsrInitConsoleSupport(VOID)
|
||||
{
|
||||
DPRINT("CSR: CsrInitConsoleSupport()\n");
|
||||
|
||||
/* Should call LoadKeyboardLayout */
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConioPause(PCSRSS_CONSOLE Console, UINT Flags)
|
||||
{
|
||||
Console->PauseFlags |= Flags;
|
||||
if (!Console->UnpauseEvent)
|
||||
Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags)
|
||||
{
|
||||
Console->PauseFlags &= ~Flags;
|
||||
if (Console->PauseFlags == 0 && Console->UnpauseEvent)
|
||||
{
|
||||
SetEvent(Console->UnpauseEvent);
|
||||
CloseHandle(Console->UnpauseEvent);
|
||||
Console->UnpauseEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CSR_API(CsrSetConsoleMode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PCSRSS_SCREEN_BUFFER Buff;
|
||||
|
||||
DPRINT("CsrSetConsoleMode\n");
|
||||
|
||||
Status = Win32CsrLockObject(ProcessData,
|
||||
Request->Data.SetConsoleModeRequest.ConsoleHandle,
|
||||
(Object_t **) &Console, GENERIC_WRITE, 0);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Buff = (PCSRSS_SCREEN_BUFFER)Console;
|
||||
if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
|
||||
{
|
||||
Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
|
||||
}
|
||||
else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
|
||||
{
|
||||
Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
Win32CsrUnlockObject((Object_t *)Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleMode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */
|
||||
|
||||
DPRINT("CsrGetConsoleMode\n");
|
||||
|
||||
Status = Win32CsrLockObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
|
||||
(Object_t **) &Console, GENERIC_READ, 0);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
Status = STATUS_SUCCESS;
|
||||
Buff = (PCSRSS_SCREEN_BUFFER) Console;
|
||||
if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
|
||||
{
|
||||
Request->Data.GetConsoleModeRequest.ConsoleMode = Console->Mode;
|
||||
}
|
||||
else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
|
||||
{
|
||||
Request->Data.GetConsoleModeRequest.ConsoleMode = Buff->Mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
Win32CsrUnlockObject((Object_t *)Console);
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetTitle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PWCHAR Buffer;
|
||||
|
||||
DPRINT("CsrSetTitle\n");
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, Request->Data.SetTitleRequest.Title,
|
||||
Request->Data.SetTitleRequest.Length, 1))
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Request->Data.SetTitleRequest.Length);
|
||||
if (Buffer)
|
||||
{
|
||||
/* copy title to console */
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
Console->Title.Buffer = Buffer;
|
||||
Console->Title.Length = Console->Title.MaximumLength = Request->Data.SetTitleRequest.Length;
|
||||
memcpy(Console->Title.Buffer, Request->Data.SetTitleRequest.Title, Console->Title.Length);
|
||||
if (! ConioChangeTitle(Console))
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetTitle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
DWORD Length;
|
||||
|
||||
DPRINT("CsrGetTitle\n");
|
||||
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, Request->Data.GetTitleRequest.Title,
|
||||
Request->Data.GetTitleRequest.Length, 1))
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Copy title of the console to the user title buffer */
|
||||
if (Request->Data.GetTitleRequest.Length >= sizeof(WCHAR))
|
||||
{
|
||||
Length = min(Request->Data.GetTitleRequest.Length - sizeof(WCHAR), Console->Title.Length);
|
||||
memcpy(Request->Data.GetTitleRequest.Title, Console->Title.Buffer, Length);
|
||||
Request->Data.GetTitleRequest.Title[Length / sizeof(WCHAR)] = L'\0';
|
||||
}
|
||||
|
||||
Request->Data.GetTitleRequest.Length = Console->Title.Length;
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* HardwareStateProperty
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Set/Get the value of the HardwareState and switch
|
||||
* between direct video buffer ouput and GDI windowed
|
||||
* output.
|
||||
* ARGUMENTS
|
||||
* Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
|
||||
* object. We use the same object to Request.
|
||||
* NOTE
|
||||
* ConsoleHwState has the correct size to be compatible
|
||||
* with NT's, but values are not.
|
||||
*/
|
||||
static NTSTATUS FASTCALL
|
||||
SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
|
||||
{
|
||||
DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
|
||||
|
||||
if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
|
||||
||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
|
||||
{
|
||||
if (Console->HardwareState != ConsoleHwState)
|
||||
{
|
||||
/* TODO: implement switching from full screen to windowed mode */
|
||||
/* TODO: or back; now simply store the hardware state */
|
||||
Console->HardwareState = ConsoleHwState;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
|
||||
}
|
||||
|
||||
CSR_API(CsrHardwareStateProperty)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrHardwareStateProperty\n");
|
||||
|
||||
Status = ConioLockConsole(ProcessData,
|
||||
Request->Data.ConsoleHardwareStateRequest.ConsoleHandle,
|
||||
&Console,
|
||||
GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
switch (Request->Data.ConsoleHardwareStateRequest.SetGet)
|
||||
{
|
||||
case CONSOLE_HARDWARE_STATE_GET:
|
||||
Request->Data.ConsoleHardwareStateRequest.State = Console->HardwareState;
|
||||
break;
|
||||
|
||||
case CONSOLE_HARDWARE_STATE_SET:
|
||||
DPRINT("Setting console hardware state.\n");
|
||||
Status = SetConsoleHardwareState(Console, Request->Data.ConsoleHardwareStateRequest.State);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
|
||||
break;
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleWindow)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrGetConsoleWindow\n");
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Request->Data.GetConsoleWindowRequest.WindowHandle = Console->hWindow;
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetConsoleIcon)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrSetConsoleIcon\n");
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = (ConioChangeIcon(Console, Request->Data.SetConsoleIconRequest.WindowIcon)
|
||||
? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleCodePage)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrGetConsoleCodePage\n");
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Request->Data.GetConsoleCodePage.CodePage = Console->CodePage;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetConsoleCodePage)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrSetConsoleCodePage\n");
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (IsValidCodePage(Request->Data.SetConsoleCodePage.CodePage))
|
||||
{
|
||||
Console->CodePage = Request->Data.SetConsoleCodePage.CodePage;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleOutputCodePage)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrGetConsoleOutputCodePage\n");
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Request->Data.GetConsoleOutputCodePage.CodePage = Console->OutputCodePage;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetConsoleOutputCodePage)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrSetConsoleOutputCodePage\n");
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (IsValidCodePage(Request->Data.SetConsoleOutputCodePage.CodePage))
|
||||
{
|
||||
Console->OutputCodePage = Request->Data.SetConsoleOutputCodePage.CodePage;
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetProcessList)
|
||||
{
|
||||
PDWORD Buffer;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PCSR_PROCESS current;
|
||||
PLIST_ENTRY current_entry;
|
||||
ULONG nItems = 0;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrGetProcessList\n");
|
||||
|
||||
Buffer = Request->Data.GetProcessListRequest.ProcessId;
|
||||
if (!Win32CsrValidateBuffer(ProcessData, Buffer, Request->Data.GetProcessListRequest.nMaxIds, sizeof(DWORD)))
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (current_entry = Console->ProcessList.Flink;
|
||||
current_entry != &Console->ProcessList;
|
||||
current_entry = current_entry->Flink)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
|
||||
if (++nItems <= Request->Data.GetProcessListRequest.nMaxIds)
|
||||
{
|
||||
*Buffer++ = HandleToUlong(current->ClientId.UniqueProcess);
|
||||
}
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.GetProcessListRequest.nProcessIdsTotal = nItems;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGenerateCtrlEvent)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
PCSR_PROCESS current;
|
||||
PLIST_ENTRY current_entry;
|
||||
DWORD Group;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Group = Request->Data.GenerateCtrlEvent.ProcessGroup;
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
for (current_entry = Console->ProcessList.Flink;
|
||||
current_entry != &Console->ProcessList;
|
||||
current_entry = current_entry->Flink)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
|
||||
if (Group == 0 || current->ProcessGroupId == Group)
|
||||
{
|
||||
ConioConsoleCtrlEvent(Request->Data.GenerateCtrlEvent.Event, current);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetConsoleSelectionInfo)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
memset(&Request->Data.GetConsoleSelectionInfo.Info, 0, sizeof(CONSOLE_SELECTION_INFO));
|
||||
if (Console->Selection.dwFlags != 0)
|
||||
Request->Data.GetConsoleSelectionInfo.Info = Console->Selection;
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,27 @@
|
||||
#define NDEBUG
|
||||
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
CSR_API(CsrCreateDesktop)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrShowDesktop)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrHideDesktop)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL DtbgIsDesktopVisible(VOID)
|
||||
{
|
||||
return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/include/destkopbg.h
|
||||
* PURPOSE: CSRSS internal desktop background window interface
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api.h"
|
||||
|
||||
/* Api functions */
|
||||
CSR_API(CsrCreateDesktop);
|
||||
CSR_API(CsrShowDesktop);
|
||||
CSR_API(CsrHideDesktop);
|
||||
CSR_API(CsrRegisterSystemClasses);
|
||||
|
||||
BOOL FASTCALL DtbgIsDesktopVisible(VOID);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/dllmain.c
|
||||
* PURPOSE: Initialization
|
||||
* PROGRAMMERS: Dmitry Philippov (shedon@mail.ru)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include "file.h"
|
||||
#include <debug.h>
|
||||
|
||||
/* Not defined in any header file */
|
||||
extern VOID WINAPI PrivateCsrssManualGuiCheck(LONG Check);
|
||||
extern LIST_ENTRY DosDeviceHistory;
|
||||
extern RTL_CRITICAL_SECTION Win32CsrDefineDosDeviceCritSec;
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
HANDLE Win32CsrApiHeap;
|
||||
HINSTANCE Win32CsrDllHandle = NULL;
|
||||
|
||||
static CSRSS_API_DEFINITION Win32CsrApiDefinitions[] =
|
||||
{
|
||||
CSRSS_DEFINE_API(GET_INPUT_HANDLE, CsrGetHandle),
|
||||
CSRSS_DEFINE_API(GET_OUTPUT_HANDLE, CsrGetHandle),
|
||||
CSRSS_DEFINE_API(CLOSE_HANDLE, CsrCloseHandle),
|
||||
CSRSS_DEFINE_API(VERIFY_HANDLE, CsrVerifyHandle),
|
||||
CSRSS_DEFINE_API(DUPLICATE_HANDLE, CsrDuplicateHandle),
|
||||
CSRSS_DEFINE_API(GET_INPUT_WAIT_HANDLE, CsrGetInputWaitHandle),
|
||||
CSRSS_DEFINE_API(WRITE_CONSOLE, CsrWriteConsole),
|
||||
CSRSS_DEFINE_API(READ_CONSOLE, CsrReadConsole),
|
||||
CSRSS_DEFINE_API(ALLOC_CONSOLE, CsrAllocConsole),
|
||||
CSRSS_DEFINE_API(FREE_CONSOLE, CsrFreeConsole),
|
||||
CSRSS_DEFINE_API(SCREEN_BUFFER_INFO, CsrGetScreenBufferInfo),
|
||||
CSRSS_DEFINE_API(SET_CURSOR, CsrSetCursor),
|
||||
CSRSS_DEFINE_API(FILL_OUTPUT, CsrFillOutputChar),
|
||||
CSRSS_DEFINE_API(READ_INPUT, CsrReadInputEvent),
|
||||
CSRSS_DEFINE_API(WRITE_CONSOLE_OUTPUT_CHAR, CsrWriteConsoleOutputChar),
|
||||
CSRSS_DEFINE_API(WRITE_CONSOLE_OUTPUT_ATTRIB, CsrWriteConsoleOutputAttrib),
|
||||
CSRSS_DEFINE_API(FILL_OUTPUT_ATTRIB, CsrFillOutputAttrib),
|
||||
CSRSS_DEFINE_API(GET_CURSOR_INFO, CsrGetCursorInfo),
|
||||
CSRSS_DEFINE_API(SET_CURSOR_INFO, CsrSetCursorInfo),
|
||||
CSRSS_DEFINE_API(SET_ATTRIB, CsrSetTextAttrib),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_MODE, CsrGetConsoleMode),
|
||||
CSRSS_DEFINE_API(SET_CONSOLE_MODE, CsrSetConsoleMode),
|
||||
CSRSS_DEFINE_API(CREATE_SCREEN_BUFFER, CsrCreateScreenBuffer),
|
||||
CSRSS_DEFINE_API(SET_SCREEN_BUFFER, CsrSetScreenBuffer),
|
||||
CSRSS_DEFINE_API(SET_TITLE, CsrSetTitle),
|
||||
CSRSS_DEFINE_API(GET_TITLE, CsrGetTitle),
|
||||
CSRSS_DEFINE_API(WRITE_CONSOLE_OUTPUT, CsrWriteConsoleOutput),
|
||||
CSRSS_DEFINE_API(FLUSH_INPUT_BUFFER, CsrFlushInputBuffer),
|
||||
CSRSS_DEFINE_API(SCROLL_CONSOLE_SCREEN_BUFFER, CsrScrollConsoleScreenBuffer),
|
||||
CSRSS_DEFINE_API(READ_CONSOLE_OUTPUT_CHAR, CsrReadConsoleOutputChar),
|
||||
CSRSS_DEFINE_API(READ_CONSOLE_OUTPUT_ATTRIB, CsrReadConsoleOutputAttrib),
|
||||
CSRSS_DEFINE_API(GET_NUM_INPUT_EVENTS, CsrGetNumberOfConsoleInputEvents),
|
||||
CSRSS_DEFINE_API(EXIT_REACTOS, CsrExitReactos),
|
||||
CSRSS_DEFINE_API(PEEK_CONSOLE_INPUT, CsrPeekConsoleInput),
|
||||
CSRSS_DEFINE_API(READ_CONSOLE_OUTPUT, CsrReadConsoleOutput),
|
||||
CSRSS_DEFINE_API(WRITE_CONSOLE_INPUT, CsrWriteConsoleInput),
|
||||
CSRSS_DEFINE_API(SETGET_CONSOLE_HW_STATE, CsrHardwareStateProperty),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_WINDOW, CsrGetConsoleWindow),
|
||||
CSRSS_DEFINE_API(CREATE_DESKTOP, CsrCreateDesktop),
|
||||
CSRSS_DEFINE_API(SHOW_DESKTOP, CsrShowDesktop),
|
||||
CSRSS_DEFINE_API(HIDE_DESKTOP, CsrHideDesktop),
|
||||
CSRSS_DEFINE_API(SET_CONSOLE_ICON, CsrSetConsoleIcon),
|
||||
CSRSS_DEFINE_API(SET_LOGON_NOTIFY_WINDOW, CsrSetLogonNotifyWindow),
|
||||
CSRSS_DEFINE_API(REGISTER_LOGON_PROCESS, CsrRegisterLogonProcess),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_CP, CsrGetConsoleCodePage),
|
||||
CSRSS_DEFINE_API(SET_CONSOLE_CP, CsrSetConsoleCodePage),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_OUTPUT_CP, CsrGetConsoleOutputCodePage),
|
||||
CSRSS_DEFINE_API(SET_CONSOLE_OUTPUT_CP, CsrSetConsoleOutputCodePage),
|
||||
CSRSS_DEFINE_API(GET_PROCESS_LIST, CsrGetProcessList),
|
||||
CSRSS_DEFINE_API(ADD_CONSOLE_ALIAS, CsrAddConsoleAlias),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_ALIAS, CsrGetConsoleAlias),
|
||||
CSRSS_DEFINE_API(GET_ALL_CONSOLE_ALIASES, CsrGetAllConsoleAliases),
|
||||
CSRSS_DEFINE_API(GET_ALL_CONSOLE_ALIASES_LENGTH, CsrGetAllConsoleAliasesLength),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_ALIASES_EXES, CsrGetConsoleAliasesExes),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_ALIASES_EXES_LENGTH, CsrGetConsoleAliasesExesLength),
|
||||
CSRSS_DEFINE_API(GENERATE_CTRL_EVENT, CsrGenerateCtrlEvent),
|
||||
CSRSS_DEFINE_API(SET_SCREEN_BUFFER_SIZE, CsrSetScreenBufferSize),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_SELECTION_INFO, CsrGetConsoleSelectionInfo),
|
||||
CSRSS_DEFINE_API(GET_COMMAND_HISTORY_LENGTH, CsrGetCommandHistoryLength),
|
||||
CSRSS_DEFINE_API(GET_COMMAND_HISTORY, CsrGetCommandHistory),
|
||||
CSRSS_DEFINE_API(EXPUNGE_COMMAND_HISTORY, CsrExpungeCommandHistory),
|
||||
CSRSS_DEFINE_API(SET_HISTORY_NUMBER_COMMANDS, CsrSetHistoryNumberCommands),
|
||||
CSRSS_DEFINE_API(GET_HISTORY_INFO, CsrGetHistoryInfo),
|
||||
CSRSS_DEFINE_API(SET_HISTORY_INFO, CsrSetHistoryInfo),
|
||||
CSRSS_DEFINE_API(GET_TEMP_FILE, CsrGetTempFile),
|
||||
CSRSS_DEFINE_API(DEFINE_DOS_DEVICE, CsrDefineDosDevice),
|
||||
CSRSS_DEFINE_API(SOUND_SENTRY, CsrSoundSentry),
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static HHOOK hhk = NULL;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
LRESULT
|
||||
CALLBACK
|
||||
KeyboardHookProc(
|
||||
int nCode,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
return CallNextHookEx(hhk, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
ULONG
|
||||
InitializeVideoAddressSpace(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
|
||||
NTSTATUS Status;
|
||||
HANDLE PhysMemHandle;
|
||||
PVOID BaseAddress;
|
||||
LARGE_INTEGER Offset;
|
||||
SIZE_T ViewSize;
|
||||
CHAR IVTAndBda[1024+256];
|
||||
|
||||
/* Free the 1MB pre-reserved region. In reality, ReactOS should simply support us mapping the view into the reserved area, but it doesn't. */
|
||||
BaseAddress = 0;
|
||||
ViewSize = 1024 * 1024;
|
||||
Status = ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
&ViewSize,
|
||||
MEM_RELEASE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Couldn't unmap reserved memory (%x)\n", Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the physical memory section */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&PhysMemName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenSection(&PhysMemHandle,
|
||||
SECTION_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Map the BIOS and device registers into the address space */
|
||||
Offset.QuadPart = 0xa0000;
|
||||
ViewSize = 0x100000 - 0xa0000;
|
||||
BaseAddress = (PVOID)0xa0000;
|
||||
Status = ZwMapViewOfSection(PhysMemHandle,
|
||||
NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
0,
|
||||
ViewSize,
|
||||
&Offset,
|
||||
&ViewSize,
|
||||
ViewUnmap,
|
||||
0,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Couldn't map physical memory (%x)\n", Status);
|
||||
ZwClose(PhysMemHandle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Close physical memory section handle */
|
||||
ZwClose(PhysMemHandle);
|
||||
|
||||
if (BaseAddress != (PVOID)0xa0000)
|
||||
{
|
||||
DPRINT1("Couldn't map physical memory at the right address (was %x)\n",
|
||||
BaseAddress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate some low memory to use for the non-BIOS
|
||||
* parts of the v86 mode address space
|
||||
*/
|
||||
BaseAddress = (PVOID)0x1;
|
||||
ViewSize = 0xa0000 - 0x1000;
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
0,
|
||||
&ViewSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status);
|
||||
return 0;
|
||||
}
|
||||
if (BaseAddress != (PVOID)0x0)
|
||||
{
|
||||
DPRINT1("Failed to allocate virtual memory at right address (was %x)\n",
|
||||
BaseAddress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the real mode IVT and BDA from the kernel */
|
||||
Status = NtVdmControl(VdmInitialize, IVTAndBda);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtVdmControl failed (status %x)\n", Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* CsrpInitVideo/3
|
||||
*
|
||||
* TODO: we need a virtual device for sessions other than
|
||||
* TODO: the console one
|
||||
*/
|
||||
NTSTATUS
|
||||
CsrpInitVideo (VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\??\\DISPLAY1");
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
HANDLE VideoHandle = (HANDLE) 0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("CSR: %s called\n", __FUNCTION__);
|
||||
|
||||
InitializeVideoAddressSpace();
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenFile(&VideoHandle,
|
||||
FILE_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
0,
|
||||
0);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(VideoHandle);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain(HANDLE hDll,
|
||||
DWORD dwReason,
|
||||
LPVOID lpReserved)
|
||||
{
|
||||
if (DLL_PROCESS_ATTACH == dwReason)
|
||||
{
|
||||
Win32CsrDllHandle = hDll;
|
||||
//
|
||||
// HACK HACK HACK ReactOS to BOOT! Initialization BUG ALERT! See bug 5655.
|
||||
//
|
||||
hhk = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, NULL, 0);
|
||||
// BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
|
||||
// BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
|
||||
// BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
|
||||
}
|
||||
|
||||
if (DLL_PROCESS_DETACH == dwReason)
|
||||
{
|
||||
CsrCleanupDefineDosDevice();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Ensure that a captured buffer is safe to access */
|
||||
BOOL FASTCALL
|
||||
Win32CsrValidateBuffer(PCSR_PROCESS ProcessData, PVOID Buffer,
|
||||
SIZE_T NumElements, SIZE_T ElementSize)
|
||||
{
|
||||
/* Check that the following conditions are true:
|
||||
* 1. The start of the buffer is somewhere within the process's
|
||||
* shared memory section view.
|
||||
* 2. The remaining space in the view is at least as large as the buffer.
|
||||
* (NB: Please don't try to "optimize" this by using multiplication
|
||||
* instead of division; remember that 2147483648 * 2 = 0.)
|
||||
* 3. The buffer is DWORD-aligned.
|
||||
*/
|
||||
ULONG_PTR Offset = (BYTE *)Buffer - (BYTE *)ProcessData->ClientViewBase;
|
||||
if (Offset >= ProcessData->ClientViewBounds
|
||||
|| NumElements > (ProcessData->ClientViewBounds - Offset) / ElementSize
|
||||
|| (Offset & (sizeof(DWORD) - 1)) != 0)
|
||||
{
|
||||
DPRINT1("Invalid buffer %p(%u*%u); section view is %p(%u)\n",
|
||||
Buffer, NumElements, ElementSize,
|
||||
ProcessData->ClientViewBase, ProcessData->ClientViewBounds);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
Win32CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc,
|
||||
PVOID Context)
|
||||
{
|
||||
return CsrEnumProcesses(EnumProc, Context);
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
PrivateCsrssManualGuiCheck(LONG Check)
|
||||
{
|
||||
NtUserCallOneParam(Check, ONEPARAM_ROUTINE_CSRSS_GUICHECK);
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
CreateSystemThreads(PVOID pParam)
|
||||
{
|
||||
NtUserCallOneParam((DWORD)pParam, ONEPARAM_ROUTINE_CREATESYSTEMTHREADS);
|
||||
DPRINT1("This thread should not terminate!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
WINAPI
|
||||
Win32CsrInitialization(IN PCSR_SERVER_DLL ServerDll)
|
||||
{
|
||||
HANDLE ServerThread;
|
||||
CLIENT_ID ClientId;
|
||||
NTSTATUS Status;
|
||||
UINT i;
|
||||
|
||||
Win32CsrApiHeap = RtlGetProcessHeap();
|
||||
|
||||
CsrpInitVideo();
|
||||
|
||||
NtUserInitialize(0, NULL, NULL);
|
||||
|
||||
PrivateCsrssManualGuiCheck(0);
|
||||
CsrInitConsoleSupport();
|
||||
|
||||
/* HACK */
|
||||
ServerDll->DispatchTable = (PVOID)Win32CsrApiDefinitions;
|
||||
ServerDll->HighestApiSupported = 0xDEADBABE;
|
||||
|
||||
ServerDll->HardErrorCallback = Win32CsrHardError;
|
||||
ServerDll->NewProcessCallback = Win32CsrDuplicateHandleTable;
|
||||
ServerDll->DisconnectCallback = Win32CsrReleaseConsole;
|
||||
|
||||
RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
InitializeListHead(&DosDeviceHistory);
|
||||
|
||||
/* Start the Raw Input Thread and the Desktop Thread */
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)i, &ServerThread, &ClientId);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
NtResumeThread(ServerThread, NULL);
|
||||
NtClose(ServerThread);
|
||||
}
|
||||
else
|
||||
DPRINT1("Cannot start Raw Input Thread!\n");
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,912 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* FILE: subsys/csrss/win32csr/exitros.c
|
||||
* PURPOSE: Logout/shutdown
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <sddl.h>
|
||||
#include "resource.h"
|
||||
#include <debug.h>
|
||||
|
||||
static HANDLE LogonProcess = NULL;
|
||||
|
||||
CSR_API(CsrRegisterLogonProcess)
|
||||
{
|
||||
if (Request->Data.RegisterLogonProcessRequest.Register)
|
||||
{
|
||||
if (0 != LogonProcess)
|
||||
{
|
||||
return STATUS_LOGON_SESSION_EXISTS;
|
||||
}
|
||||
LogonProcess = Request->Data.RegisterLogonProcessRequest.ProcessId;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Request->Header.ClientId.UniqueProcess != LogonProcess)
|
||||
{
|
||||
DPRINT1("Current logon process 0x%x, can't deregister from process 0x%x\n",
|
||||
LogonProcess, Request->Header.ClientId.UniqueProcess);
|
||||
return STATUS_NOT_LOGON_PROCESS;
|
||||
}
|
||||
LogonProcess = 0;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetLogonNotifyWindow)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct tagSHUTDOWN_SETTINGS
|
||||
{
|
||||
BOOL AutoEndTasks;
|
||||
DWORD HungAppTimeout;
|
||||
DWORD WaitToKillAppTimeout;
|
||||
} SHUTDOWN_SETTINGS, *PSHUTDOWN_SETTINGS;
|
||||
|
||||
#define DEFAULT_AUTO_END_TASKS FALSE
|
||||
#define DEFAULT_HUNG_APP_TIMEOUT 5000
|
||||
#define DEFAULT_WAIT_TO_KILL_APP_TIMEOUT 20000
|
||||
|
||||
typedef struct tagNOTIFY_CONTEXT
|
||||
{
|
||||
DWORD ProcessId;
|
||||
UINT Msg;
|
||||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
HDESK Desktop;
|
||||
HDESK OldDesktop;
|
||||
DWORD StartTime;
|
||||
DWORD QueryResult;
|
||||
HWND Dlg;
|
||||
DWORD EndNowResult;
|
||||
BOOL ShowUI;
|
||||
HANDLE UIThread;
|
||||
HWND WndClient;
|
||||
PSHUTDOWN_SETTINGS ShutdownSettings;
|
||||
LPTHREAD_START_ROUTINE SendMessageProc;
|
||||
} NOTIFY_CONTEXT, *PNOTIFY_CONTEXT;
|
||||
|
||||
#define QUERY_RESULT_ABORT 0
|
||||
#define QUERY_RESULT_CONTINUE 1
|
||||
#define QUERY_RESULT_TIMEOUT 2
|
||||
#define QUERY_RESULT_ERROR 3
|
||||
#define QUERY_RESULT_FORCE 4
|
||||
|
||||
static void FASTCALL
|
||||
UpdateProgressBar(HWND ProgressBar, PNOTIFY_CONTEXT NotifyContext)
|
||||
{
|
||||
DWORD Passed;
|
||||
|
||||
Passed = GetTickCount() - NotifyContext->StartTime;
|
||||
Passed -= NotifyContext->ShutdownSettings->HungAppTimeout;
|
||||
if (NotifyContext->ShutdownSettings->WaitToKillAppTimeout < Passed)
|
||||
{
|
||||
Passed = NotifyContext->ShutdownSettings->WaitToKillAppTimeout;
|
||||
}
|
||||
SendMessageW(ProgressBar, PBM_SETPOS, Passed / 2, 0);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK
|
||||
EndNowDlgProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
INT_PTR Result;
|
||||
PNOTIFY_CONTEXT NotifyContext;
|
||||
HWND ProgressBar;
|
||||
DWORD TitleLength;
|
||||
int Len;
|
||||
LPWSTR Title;
|
||||
|
||||
switch(Msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
NotifyContext = (PNOTIFY_CONTEXT) lParam;
|
||||
NotifyContext->EndNowResult = QUERY_RESULT_ABORT;
|
||||
SetWindowLongPtrW(Dlg, DWLP_USER, (LONG_PTR) lParam);
|
||||
TitleLength = SendMessageW(NotifyContext->WndClient, WM_GETTEXTLENGTH,
|
||||
0, 0) +
|
||||
GetWindowTextLengthW(Dlg);
|
||||
Title = HeapAlloc(Win32CsrApiHeap, 0, (TitleLength + 1) * sizeof(WCHAR));
|
||||
if (NULL != Title)
|
||||
{
|
||||
Len = GetWindowTextW(Dlg, Title, TitleLength + 1);
|
||||
SendMessageW(NotifyContext->WndClient, WM_GETTEXT,
|
||||
TitleLength + 1 - Len, (LPARAM) (Title + Len));
|
||||
SetWindowTextW(Dlg, Title);
|
||||
HeapFree(Win32CsrApiHeap, 0, Title);
|
||||
}
|
||||
ProgressBar = GetDlgItem(Dlg, IDC_PROGRESS);
|
||||
SendMessageW(ProgressBar, PBM_SETRANGE32, 0,
|
||||
NotifyContext->ShutdownSettings->WaitToKillAppTimeout / 2);
|
||||
UpdateProgressBar(ProgressBar, NotifyContext);
|
||||
SetTimer(Dlg, 0, 200, NULL);
|
||||
Result = FALSE;
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
NotifyContext = (PNOTIFY_CONTEXT) GetWindowLongPtrW(Dlg, DWLP_USER);
|
||||
ProgressBar = GetDlgItem(Dlg, IDC_PROGRESS);
|
||||
UpdateProgressBar(ProgressBar, NotifyContext);
|
||||
Result = TRUE;
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (BN_CLICKED == HIWORD(wParam) && IDC_END_NOW == LOWORD(wParam))
|
||||
{
|
||||
NotifyContext = (PNOTIFY_CONTEXT) GetWindowLongPtrW(Dlg, DWLP_USER);
|
||||
NotifyContext->EndNowResult = QUERY_RESULT_FORCE;
|
||||
SendMessageW(Dlg, WM_CLOSE, 0, 0);
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
DestroyWindow(Dlg);
|
||||
Result = TRUE;
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
NotifyContext = (PNOTIFY_CONTEXT) GetWindowLongPtrW(Dlg, DWLP_USER);
|
||||
NotifyContext->Dlg = NULL;
|
||||
KillTimer(Dlg, 0);
|
||||
PostQuitMessage(NotifyContext->EndNowResult);
|
||||
Result = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
Result = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
typedef void (WINAPI *INITCOMMONCONTROLS_PROC)(void);
|
||||
|
||||
static void
|
||||
CallInitCommonControls()
|
||||
{
|
||||
static BOOL Initialized = FALSE;
|
||||
HMODULE Lib;
|
||||
INITCOMMONCONTROLS_PROC InitProc;
|
||||
|
||||
if (Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Lib = LoadLibraryW(L"COMCTL32.DLL");
|
||||
if (NULL == Lib)
|
||||
{
|
||||
return;
|
||||
}
|
||||
InitProc = (INITCOMMONCONTROLS_PROC) GetProcAddress(Lib, "InitCommonControls");
|
||||
if (NULL == InitProc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
(*InitProc)();
|
||||
|
||||
Initialized = TRUE;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
EndNowThreadProc(LPVOID Parameter)
|
||||
{
|
||||
PNOTIFY_CONTEXT NotifyContext = (PNOTIFY_CONTEXT) Parameter;
|
||||
MSG Msg;
|
||||
|
||||
SetThreadDesktop(NotifyContext->Desktop);
|
||||
SwitchDesktop(NotifyContext->Desktop);
|
||||
CallInitCommonControls();
|
||||
NotifyContext->Dlg = CreateDialogParam(GetModuleHandleW(L"win32csr"),
|
||||
MAKEINTRESOURCE(IDD_END_NOW), NULL,
|
||||
EndNowDlgProc, (LPARAM) NotifyContext);
|
||||
if (NULL == NotifyContext->Dlg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ShowWindow(NotifyContext->Dlg, SW_SHOWNORMAL);
|
||||
|
||||
while (GetMessageW(&Msg, NULL, 0, 0))
|
||||
{
|
||||
if (! IsDialogMessage(NotifyContext->Dlg, &Msg))
|
||||
{
|
||||
TranslateMessage(&Msg);
|
||||
DispatchMessageW(&Msg);
|
||||
}
|
||||
}
|
||||
|
||||
return Msg.wParam;
|
||||
}
|
||||
|
||||
typedef struct tagMESSAGE_CONTEXT
|
||||
{
|
||||
HWND Wnd;
|
||||
UINT Msg;
|
||||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
DWORD Timeout;
|
||||
} MESSAGE_CONTEXT, *PMESSAGE_CONTEXT;
|
||||
|
||||
static DWORD WINAPI
|
||||
SendQueryEndSession(LPVOID Parameter)
|
||||
{
|
||||
PMESSAGE_CONTEXT Context = (PMESSAGE_CONTEXT) Parameter;
|
||||
DWORD_PTR Result;
|
||||
|
||||
if (SendMessageTimeoutW(Context->Wnd, WM_QUERYENDSESSION, Context->wParam,
|
||||
Context->lParam, SMTO_NORMAL, Context->Timeout,
|
||||
&Result))
|
||||
{
|
||||
return Result ? QUERY_RESULT_CONTINUE : QUERY_RESULT_ABORT;
|
||||
}
|
||||
|
||||
return 0 == GetLastError() ? QUERY_RESULT_TIMEOUT : QUERY_RESULT_ERROR;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
SendEndSession(LPVOID Parameter)
|
||||
{
|
||||
PMESSAGE_CONTEXT Context = (PMESSAGE_CONTEXT) Parameter;
|
||||
DWORD_PTR Result;
|
||||
|
||||
if (Context->wParam)
|
||||
{
|
||||
if (SendMessageTimeoutW(Context->Wnd, WM_ENDSESSION, Context->wParam,
|
||||
Context->lParam, SMTO_NORMAL, Context->Timeout,
|
||||
&Result))
|
||||
{
|
||||
return QUERY_RESULT_CONTINUE;
|
||||
}
|
||||
return 0 == GetLastError() ? QUERY_RESULT_TIMEOUT : QUERY_RESULT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(Context->Wnd, WM_ENDSESSION, Context->wParam,
|
||||
Context->lParam);
|
||||
return QUERY_RESULT_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL CALLBACK
|
||||
NotifyTopLevelEnum(HWND Wnd, LPARAM lParam)
|
||||
{
|
||||
PNOTIFY_CONTEXT NotifyContext = (PNOTIFY_CONTEXT) lParam;
|
||||
MESSAGE_CONTEXT MessageContext;
|
||||
DWORD Now, Passed;
|
||||
DWORD Timeout, WaitStatus;
|
||||
DWORD ProcessId;
|
||||
HANDLE MessageThread;
|
||||
HANDLE Threads[2];
|
||||
|
||||
if (0 == GetWindowThreadProcessId(Wnd, &ProcessId))
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ProcessId == NotifyContext->ProcessId)
|
||||
{
|
||||
Now = GetTickCount();
|
||||
if (0 == NotifyContext->StartTime)
|
||||
{
|
||||
NotifyContext->StartTime = Now;
|
||||
}
|
||||
/* Note: Passed is computed correctly even when GetTickCount() wraps due
|
||||
to unsigned arithmetic */
|
||||
Passed = Now - NotifyContext->StartTime;
|
||||
MessageContext.Wnd = Wnd;
|
||||
MessageContext.Msg = NotifyContext->Msg;
|
||||
MessageContext.wParam = NotifyContext->wParam;
|
||||
MessageContext.lParam = NotifyContext->lParam;
|
||||
MessageContext.Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
|
||||
if (! NotifyContext->ShutdownSettings->AutoEndTasks)
|
||||
{
|
||||
MessageContext.Timeout += NotifyContext->ShutdownSettings->WaitToKillAppTimeout;
|
||||
}
|
||||
if (Passed < MessageContext.Timeout)
|
||||
{
|
||||
MessageContext.Timeout -= Passed;
|
||||
MessageThread = CreateThread(NULL, 0, NotifyContext->SendMessageProc,
|
||||
(LPVOID) &MessageContext, 0, NULL);
|
||||
if (NULL == MessageThread)
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
Timeout = NotifyContext->ShutdownSettings->HungAppTimeout;
|
||||
if (Passed < Timeout)
|
||||
{
|
||||
Timeout -= Passed;
|
||||
WaitStatus = WaitForSingleObjectEx(MessageThread, Timeout, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitStatus = WAIT_TIMEOUT;
|
||||
}
|
||||
if (WAIT_TIMEOUT == WaitStatus)
|
||||
{
|
||||
NotifyContext->WndClient = Wnd;
|
||||
if (NULL == NotifyContext->UIThread && NotifyContext->ShowUI)
|
||||
{
|
||||
NotifyContext->UIThread = CreateThread(NULL, 0,
|
||||
EndNowThreadProc,
|
||||
(LPVOID) NotifyContext,
|
||||
0, NULL);
|
||||
}
|
||||
Threads[0] = MessageThread;
|
||||
Threads[1] = NotifyContext->UIThread;
|
||||
WaitStatus = WaitForMultipleObjectsEx(NULL == NotifyContext->UIThread ?
|
||||
1 : 2,
|
||||
Threads, FALSE, INFINITE,
|
||||
FALSE);
|
||||
if (WAIT_OBJECT_0 == WaitStatus)
|
||||
{
|
||||
if (! GetExitCodeThread(MessageThread, &NotifyContext->QueryResult))
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
else if (WAIT_OBJECT_0 + 1 == WaitStatus)
|
||||
{
|
||||
if (! GetExitCodeThread(NotifyContext->UIThread,
|
||||
&NotifyContext->QueryResult))
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
}
|
||||
if (WAIT_OBJECT_0 != WaitStatus)
|
||||
{
|
||||
TerminateThread(MessageThread, QUERY_RESULT_TIMEOUT);
|
||||
}
|
||||
}
|
||||
else if (WAIT_OBJECT_0 == WaitStatus)
|
||||
{
|
||||
if (! GetExitCodeThread(MessageThread,
|
||||
&NotifyContext->QueryResult))
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_ERROR;
|
||||
}
|
||||
CloseHandle(MessageThread);
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyContext->QueryResult = QUERY_RESULT_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return QUERY_RESULT_CONTINUE == NotifyContext->QueryResult;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK
|
||||
NotifyDesktopEnum(LPWSTR DesktopName, LPARAM lParam)
|
||||
{
|
||||
PNOTIFY_CONTEXT Context = (PNOTIFY_CONTEXT) lParam;
|
||||
|
||||
Context->Desktop = OpenDesktopW(DesktopName, 0, FALSE,
|
||||
DESKTOP_ENUMERATE | DESKTOP_SWITCHDESKTOP);
|
||||
if (NULL == Context->Desktop)
|
||||
{
|
||||
DPRINT1("OpenDesktop failed with error %d\n", GetLastError());
|
||||
Context->QueryResult = QUERY_RESULT_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Context->OldDesktop = GetThreadDesktop(GetCurrentThreadId());
|
||||
SwitchDesktop(Context->Desktop);
|
||||
|
||||
EnumDesktopWindows(Context->Desktop, NotifyTopLevelEnum, lParam);
|
||||
|
||||
SwitchDesktop(Context->OldDesktop);
|
||||
|
||||
CloseDesktop(Context->Desktop);
|
||||
|
||||
return QUERY_RESULT_CONTINUE == Context->QueryResult;
|
||||
}
|
||||
|
||||
static BOOL FASTCALL
|
||||
NotifyTopLevelWindows(PNOTIFY_CONTEXT Context)
|
||||
{
|
||||
HWINSTA WindowStation;
|
||||
|
||||
WindowStation = GetProcessWindowStation();
|
||||
if (NULL == WindowStation)
|
||||
{
|
||||
DPRINT1("GetProcessWindowStation failed with error %d\n", GetLastError());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EnumDesktopsW(WindowStation, NotifyDesktopEnum, (LPARAM) Context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL FASTCALL
|
||||
NotifyAndTerminateProcess(PCSR_PROCESS ProcessData,
|
||||
PSHUTDOWN_SETTINGS ShutdownSettings,
|
||||
UINT Flags)
|
||||
{
|
||||
NOTIFY_CONTEXT Context;
|
||||
HANDLE Process;
|
||||
DWORD QueryResult = QUERY_RESULT_CONTINUE;
|
||||
|
||||
Context.QueryResult = QUERY_RESULT_CONTINUE;
|
||||
|
||||
if (0 == (Flags & EWX_FORCE))
|
||||
{
|
||||
if (NULL != ProcessData->Console)
|
||||
{
|
||||
ConioConsoleCtrlEventTimeout(CTRL_LOGOFF_EVENT, ProcessData,
|
||||
ShutdownSettings->WaitToKillAppTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context.ProcessId = (DWORD_PTR) ProcessData->ClientId.UniqueProcess;
|
||||
Context.wParam = 0;
|
||||
Context.lParam = (0 != (Flags & EWX_INTERNAL_FLAG_LOGOFF) ?
|
||||
ENDSESSION_LOGOFF : 0);
|
||||
Context.StartTime = 0;
|
||||
Context.UIThread = NULL;
|
||||
Context.ShowUI = DtbgIsDesktopVisible();
|
||||
Context.Dlg = NULL;
|
||||
Context.ShutdownSettings = ShutdownSettings;
|
||||
Context.SendMessageProc = SendQueryEndSession;
|
||||
|
||||
NotifyTopLevelWindows(&Context);
|
||||
|
||||
Context.wParam = (QUERY_RESULT_ABORT != Context.QueryResult);
|
||||
Context.lParam = (0 != (Flags & EWX_INTERNAL_FLAG_LOGOFF) ?
|
||||
ENDSESSION_LOGOFF : 0);
|
||||
Context.SendMessageProc = SendEndSession;
|
||||
Context.ShowUI = DtbgIsDesktopVisible() &&
|
||||
(QUERY_RESULT_ABORT != Context.QueryResult);
|
||||
QueryResult = Context.QueryResult;
|
||||
Context.QueryResult = QUERY_RESULT_CONTINUE;
|
||||
|
||||
NotifyTopLevelWindows(&Context);
|
||||
|
||||
if (NULL != Context.UIThread)
|
||||
{
|
||||
if (NULL != Context.Dlg)
|
||||
{
|
||||
SendMessageW(Context.Dlg, WM_CLOSE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TerminateThread(Context.UIThread, QUERY_RESULT_ERROR);
|
||||
}
|
||||
CloseHandle(Context.UIThread);
|
||||
}
|
||||
}
|
||||
|
||||
if (QUERY_RESULT_ABORT == QueryResult)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate this process */
|
||||
Process = OpenProcess(PROCESS_TERMINATE, FALSE,
|
||||
(DWORD_PTR) ProcessData->ClientId.UniqueProcess);
|
||||
if (NULL == Process)
|
||||
{
|
||||
DPRINT1("Unable to open process %d, error %d\n", ProcessData->ClientId.UniqueProcess,
|
||||
GetLastError());
|
||||
return TRUE;
|
||||
}
|
||||
TerminateProcess(Process, 0);
|
||||
CloseHandle(Process);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct tagPROCESS_ENUM_CONTEXT
|
||||
{
|
||||
UINT ProcessCount;
|
||||
PCSR_PROCESS *ProcessData;
|
||||
TOKEN_ORIGIN TokenOrigin;
|
||||
DWORD ShellProcess;
|
||||
DWORD CsrssProcess;
|
||||
} PROCESS_ENUM_CONTEXT, *PPROCESS_ENUM_CONTEXT;
|
||||
|
||||
static NTSTATUS WINAPI
|
||||
ExitReactosProcessEnum(PCSR_PROCESS ProcessData, PVOID Data)
|
||||
{
|
||||
HANDLE Process;
|
||||
HANDLE Token;
|
||||
TOKEN_ORIGIN Origin;
|
||||
DWORD ReturnLength;
|
||||
PPROCESS_ENUM_CONTEXT Context = (PPROCESS_ENUM_CONTEXT) Data;
|
||||
PCSR_PROCESS *NewData;
|
||||
|
||||
/* Do not kill winlogon or csrss */
|
||||
if ((DWORD_PTR) ProcessData->ClientId.UniqueProcess == Context->CsrssProcess ||
|
||||
ProcessData->ClientId.UniqueProcess == LogonProcess)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get the login session of this process */
|
||||
Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
|
||||
(DWORD_PTR) ProcessData->ClientId.UniqueProcess);
|
||||
if (NULL == Process)
|
||||
{
|
||||
DPRINT1("Unable to open process %d, error %d\n", ProcessData->ClientId.UniqueProcess,
|
||||
GetLastError());
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (! OpenProcessToken(Process, TOKEN_QUERY, &Token))
|
||||
{
|
||||
DPRINT1("Unable to open token for process %d, error %d\n",
|
||||
ProcessData->ClientId.UniqueProcess, GetLastError());
|
||||
CloseHandle(Process);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CloseHandle(Process);
|
||||
|
||||
if (! GetTokenInformation(Token, TokenOrigin, &Origin,
|
||||
sizeof(TOKEN_ORIGIN), &ReturnLength))
|
||||
{
|
||||
DPRINT1("GetTokenInformation failed for process %d with error %d\n",
|
||||
ProcessData->ClientId.UniqueProcess, GetLastError());
|
||||
CloseHandle(Token);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CloseHandle(Token);
|
||||
|
||||
/* This process will be killed if it's in the correct logon session */
|
||||
if (RtlEqualLuid(&(Context->TokenOrigin.OriginatingLogonSession),
|
||||
&(Origin.OriginatingLogonSession)))
|
||||
{
|
||||
/* Kill the shell process last */
|
||||
if ((DWORD_PTR) ProcessData->ClientId.UniqueProcess == Context->ShellProcess)
|
||||
{
|
||||
ProcessData->ShutdownLevel = 0;
|
||||
}
|
||||
NewData = HeapAlloc(Win32CsrApiHeap, 0, (Context->ProcessCount + 1)
|
||||
* sizeof(PCSR_PROCESS));
|
||||
if (NULL == NewData)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
if (0 != Context->ProcessCount)
|
||||
{
|
||||
memcpy(NewData, Context->ProcessData,
|
||||
Context->ProcessCount * sizeof(PCSR_PROCESS));
|
||||
HeapFree(Win32CsrApiHeap, 0, Context->ProcessData);
|
||||
}
|
||||
Context->ProcessData = NewData;
|
||||
Context->ProcessData[Context->ProcessCount] = ProcessData;
|
||||
Context->ProcessCount++;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ProcessDataCompare(const void *Elem1, const void *Elem2)
|
||||
{
|
||||
const PCSR_PROCESS *ProcessData1 = (PCSR_PROCESS *) Elem1;
|
||||
const PCSR_PROCESS *ProcessData2 = (PCSR_PROCESS *) Elem2;
|
||||
|
||||
if ((*ProcessData1)->ShutdownLevel < (*ProcessData2)->ShutdownLevel)
|
||||
{
|
||||
return +1;
|
||||
}
|
||||
else if ((*ProcessData2)->ShutdownLevel < (*ProcessData1)->ShutdownLevel)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if ((*ProcessData1)->ClientId.UniqueProcess < (*ProcessData2)->ClientId.UniqueProcess)
|
||||
{
|
||||
return +1;
|
||||
}
|
||||
else if ((*ProcessData2)->ClientId.UniqueProcess < (*ProcessData1)->ClientId.UniqueProcess)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD FASTCALL
|
||||
GetShutdownSetting(HKEY DesktopKey, LPCWSTR ValueName, DWORD DefaultValue)
|
||||
{
|
||||
BYTE ValueBuffer[16];
|
||||
LONG ErrCode;
|
||||
DWORD Type;
|
||||
DWORD ValueSize;
|
||||
UNICODE_STRING StringValue;
|
||||
ULONG Value;
|
||||
|
||||
ValueSize = sizeof(ValueBuffer);
|
||||
ErrCode = RegQueryValueExW(DesktopKey, ValueName, NULL, &Type, ValueBuffer,
|
||||
&ValueSize);
|
||||
if (ERROR_SUCCESS != ErrCode)
|
||||
{
|
||||
DPRINT("GetShutdownSetting for %S failed with error code %ld\n",
|
||||
ValueName, ErrCode);
|
||||
return DefaultValue;
|
||||
}
|
||||
|
||||
if (REG_SZ == Type)
|
||||
{
|
||||
RtlInitUnicodeString(&StringValue, (LPCWSTR) ValueBuffer);
|
||||
if (! NT_SUCCESS(RtlUnicodeStringToInteger(&StringValue, 10, &Value)))
|
||||
{
|
||||
DPRINT1("Unable to convert value %S for setting %S\n",
|
||||
StringValue.Buffer, ValueName);
|
||||
return DefaultValue;
|
||||
}
|
||||
return (DWORD) Value;
|
||||
}
|
||||
else if (REG_DWORD == Type)
|
||||
{
|
||||
return *((DWORD *) ValueBuffer);
|
||||
}
|
||||
|
||||
DPRINT1("Unexpected registry type %d for setting %S\n", Type, ValueName);
|
||||
return DefaultValue;
|
||||
}
|
||||
|
||||
static void FASTCALL
|
||||
LoadShutdownSettings(PSID Sid, PSHUTDOWN_SETTINGS ShutdownSettings)
|
||||
{
|
||||
static WCHAR Subkey[] = L"\\Control Panel\\Desktop";
|
||||
LPWSTR StringSid;
|
||||
WCHAR InitialKeyName[128];
|
||||
LPWSTR KeyName;
|
||||
HKEY DesktopKey;
|
||||
LONG ErrCode;
|
||||
|
||||
ShutdownSettings->AutoEndTasks = DEFAULT_AUTO_END_TASKS;
|
||||
ShutdownSettings->HungAppTimeout = DEFAULT_HUNG_APP_TIMEOUT;
|
||||
ShutdownSettings->WaitToKillAppTimeout = DEFAULT_WAIT_TO_KILL_APP_TIMEOUT;
|
||||
|
||||
if (! ConvertSidToStringSidW(Sid, &StringSid))
|
||||
{
|
||||
DPRINT1("ConvertSidToStringSid failed with error %d, using default shutdown settings\n",
|
||||
GetLastError());
|
||||
return;
|
||||
}
|
||||
if (wcslen(StringSid) + wcslen(Subkey) + 1 <=
|
||||
sizeof(InitialKeyName) / sizeof(WCHAR))
|
||||
{
|
||||
KeyName = InitialKeyName;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyName = HeapAlloc(Win32CsrApiHeap, 0,
|
||||
(wcslen(StringSid) + wcslen(Subkey) + 1) *
|
||||
sizeof(WCHAR));
|
||||
if (NULL == KeyName)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory, using default shutdown settings\n");
|
||||
LocalFree(StringSid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
wcscat(wcscpy(KeyName, StringSid), Subkey);
|
||||
LocalFree(StringSid);
|
||||
|
||||
ErrCode = RegOpenKeyExW(HKEY_USERS, KeyName, 0, KEY_QUERY_VALUE, &DesktopKey);
|
||||
if (KeyName != InitialKeyName)
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap, 0, KeyName);
|
||||
}
|
||||
if (ERROR_SUCCESS != ErrCode)
|
||||
{
|
||||
DPRINT1("RegOpenKeyEx failed with error %ld, using default shutdown settings\n", ErrCode);
|
||||
return;
|
||||
}
|
||||
|
||||
ShutdownSettings->AutoEndTasks = (BOOL) GetShutdownSetting(DesktopKey, L"AutoEndTasks",
|
||||
(DWORD) DEFAULT_AUTO_END_TASKS);
|
||||
ShutdownSettings->HungAppTimeout = GetShutdownSetting(DesktopKey,
|
||||
L"HungAppTimeout",
|
||||
DEFAULT_HUNG_APP_TIMEOUT);
|
||||
ShutdownSettings->WaitToKillAppTimeout = GetShutdownSetting(DesktopKey,
|
||||
L"WaitToKillAppTimeout",
|
||||
DEFAULT_WAIT_TO_KILL_APP_TIMEOUT);
|
||||
|
||||
RegCloseKey(DesktopKey);
|
||||
}
|
||||
|
||||
static NTSTATUS FASTCALL
|
||||
InternalExitReactos(DWORD ProcessId, DWORD ThreadId, UINT Flags)
|
||||
{
|
||||
HANDLE CallerThread;
|
||||
HANDLE CallerToken;
|
||||
NTSTATUS Status;
|
||||
PROCESS_ENUM_CONTEXT Context;
|
||||
DWORD ReturnLength;
|
||||
HWND ShellWnd;
|
||||
UINT ProcessIndex;
|
||||
char FixedUserInfo[64];
|
||||
TOKEN_USER *UserInfo;
|
||||
SHUTDOWN_SETTINGS ShutdownSettings;
|
||||
|
||||
if (ProcessId != (DWORD_PTR) LogonProcess)
|
||||
{
|
||||
DPRINT1("Internal ExitWindowsEx call not from winlogon\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
DPRINT1("FIXME: Need to close all user processes!\n");
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
CallerThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, ThreadId);
|
||||
if (NULL == CallerThread)
|
||||
{
|
||||
DPRINT1("OpenThread failed with error %d\n", GetLastError());
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
if (! OpenThreadToken(CallerThread, TOKEN_QUERY, FALSE, &CallerToken))
|
||||
{
|
||||
DPRINT1("OpenThreadToken failed with error %d\n", GetLastError());
|
||||
CloseHandle(CallerThread);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CloseHandle(CallerThread);
|
||||
|
||||
Context.ProcessCount = 0;
|
||||
Context.ProcessData = NULL;
|
||||
if (! GetTokenInformation(CallerToken, TokenOrigin, &Context.TokenOrigin,
|
||||
sizeof(TOKEN_ORIGIN), &ReturnLength))
|
||||
{
|
||||
DPRINT1("GetTokenInformation failed with error %d\n", GetLastError());
|
||||
CloseHandle(CallerToken);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
if (! GetTokenInformation(CallerToken, TokenUser, FixedUserInfo,
|
||||
sizeof(FixedUserInfo), &ReturnLength))
|
||||
{
|
||||
if (sizeof(FixedUserInfo) < ReturnLength)
|
||||
{
|
||||
UserInfo = HeapAlloc(Win32CsrApiHeap, 0, ReturnLength);
|
||||
if (NULL == UserInfo)
|
||||
{
|
||||
DPRINT1("Unable to allocate %u bytes for user info\n",
|
||||
(unsigned) ReturnLength);
|
||||
CloseHandle(CallerToken);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
if (! GetTokenInformation(CallerToken, TokenUser, UserInfo,
|
||||
ReturnLength, &ReturnLength))
|
||||
{
|
||||
DPRINT1("GetTokenInformation failed with error %d\n",
|
||||
GetLastError());
|
||||
HeapFree(Win32CsrApiHeap, 0, UserInfo);
|
||||
CloseHandle(CallerToken);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("GetTokenInformation failed with error %d\n", GetLastError());
|
||||
CloseHandle(CallerToken);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UserInfo = (TOKEN_USER *) FixedUserInfo;
|
||||
}
|
||||
CloseHandle(CallerToken);
|
||||
LoadShutdownSettings(UserInfo->User.Sid, &ShutdownSettings);
|
||||
if (UserInfo != (TOKEN_USER *) FixedUserInfo)
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap, 0, UserInfo);
|
||||
}
|
||||
Context.CsrssProcess = GetCurrentProcessId();
|
||||
ShellWnd = GetShellWindow();
|
||||
if (NULL == ShellWnd)
|
||||
{
|
||||
DPRINT("No shell present\n");
|
||||
Context.ShellProcess = 0;
|
||||
}
|
||||
else if (0 == GetWindowThreadProcessId(ShellWnd, &Context.ShellProcess))
|
||||
{
|
||||
DPRINT1("Can't get process id of shell window\n");
|
||||
Context.ShellProcess = 0;
|
||||
}
|
||||
|
||||
Status = Win32CsrEnumProcesses(ExitReactosProcessEnum, &Context);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to enumerate registered processes, status 0x%x\n",
|
||||
Status);
|
||||
if (NULL != Context.ProcessData)
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap, 0, Context.ProcessData);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
qsort(Context.ProcessData, Context.ProcessCount, sizeof(PCSR_PROCESS),
|
||||
ProcessDataCompare);
|
||||
|
||||
/* Terminate processes, stop if we find one kicking and screaming it doesn't
|
||||
want to die */
|
||||
Status = STATUS_SUCCESS;
|
||||
for (ProcessIndex = 0;
|
||||
ProcessIndex < Context.ProcessCount && NT_SUCCESS(Status);
|
||||
ProcessIndex++)
|
||||
{
|
||||
if (! NotifyAndTerminateProcess(Context.ProcessData[ProcessIndex],
|
||||
&ShutdownSettings, Flags))
|
||||
{
|
||||
Status = STATUS_REQUEST_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
if (NULL != Context.ProcessData)
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap, 0, Context.ProcessData);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS FASTCALL
|
||||
UserExitReactos(DWORD UserProcessId, UINT Flags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* FIXME Inside 2000 says we should impersonate the caller here */
|
||||
Status = NtUserCallTwoParam (UserProcessId, Flags, TWOPARAM_ROUTINE_EXITREACTOS);
|
||||
|
||||
/* If the message isn't handled, the return value is 0, so 0 doesn't indicate
|
||||
success. Success is indicated by a 1 return value, if anything besides 0
|
||||
or 1 it's a NTSTATUS value */
|
||||
if (1 == Status)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (0 == Status)
|
||||
{
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrExitReactos)
|
||||
{
|
||||
if (0 == (Request->Data.ExitReactosRequest.Flags & EWX_INTERNAL_FLAG))
|
||||
{
|
||||
return UserExitReactos((DWORD_PTR) Request->Header.ClientId.UniqueProcess,
|
||||
Request->Data.ExitReactosRequest.Flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return InternalExitReactos((DWORD_PTR) Request->Header.ClientId.UniqueProcess,
|
||||
(DWORD_PTR) Request->Header.ClientId.UniqueThread,
|
||||
Request->Data.ExitReactosRequest.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/file.c
|
||||
* PURPOSE: File handling
|
||||
* PROGRAMMERS: Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
* NOTE: Belongs to basesrv.dll
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <w32csr.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include "file.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
typedef BOOL (WINAPI *PUSER_SOUND_SENTRY)(VOID);
|
||||
BOOL
|
||||
WINAPI
|
||||
FirstSoundSentry(VOID);
|
||||
|
||||
UINT CsrGetTempFileUnique;
|
||||
LIST_ENTRY DosDeviceHistory;
|
||||
RTL_CRITICAL_SECTION Win32CsrDefineDosDeviceCritSec;
|
||||
PUSER_SOUND_SENTRY _UserSoundSentry = FirstSoundSentry;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
FailSoundSentry(VOID)
|
||||
{
|
||||
/* In case the function can't be found/is unimplemented */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
FirstSoundSentry(VOID)
|
||||
{
|
||||
UNICODE_STRING DllString = RTL_CONSTANT_STRING(L"winsrv");
|
||||
STRING FuncString = RTL_CONSTANT_STRING("_UserSoundSentry");
|
||||
HANDLE DllHandle;
|
||||
NTSTATUS Status;
|
||||
PUSER_SOUND_SENTRY NewSoundSentry = FailSoundSentry;
|
||||
|
||||
/* Load winsrv manually */
|
||||
Status = LdrGetDllHandle(NULL, NULL, &DllString, &DllHandle);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* If it was found, get SoundSentry export */
|
||||
Status = LdrGetProcedureAddress(DllHandle,
|
||||
&FuncString,
|
||||
0,
|
||||
(PVOID*)&NewSoundSentry);
|
||||
}
|
||||
|
||||
/* Set it as the callback for the future, and call it */
|
||||
_UserSoundSentry = NewSoundSentry;
|
||||
return _UserSoundSentry();
|
||||
}
|
||||
|
||||
CSR_API(CsrSoundSentry)
|
||||
{
|
||||
/* Call the API and see if it suceeds */
|
||||
return _UserSoundSentry() ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetTempFile)
|
||||
{
|
||||
DPRINT("CsrGetTempFile entered\n");
|
||||
|
||||
/* Return 16-bits ID */
|
||||
Request->Data.GetTempFile.UniqueID = (++CsrGetTempFileUnique & 0xFFFF);
|
||||
|
||||
DPRINT("Returning: %u\n", Request->Data.GetTempFile.UniqueID);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrDefineDosDevice)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE LinkHandle = NULL;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING DeviceName = {0};
|
||||
UNICODE_STRING RequestDeviceName = {0};
|
||||
UNICODE_STRING LinkTarget = {0};
|
||||
PUNICODE_STRING RequestLinkTarget;
|
||||
ULONG Length;
|
||||
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
||||
SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
PACL Dacl;
|
||||
PSID AdminSid;
|
||||
PSID SystemSid;
|
||||
PSID WorldSid;
|
||||
ULONG SidLength;
|
||||
PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
|
||||
PLIST_ENTRY Entry;
|
||||
PLIST_ENTRY ListHead;
|
||||
BOOLEAN Matched, AddHistory;
|
||||
DWORD dwFlags;
|
||||
PWSTR lpBuffer;
|
||||
|
||||
DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
|
||||
Request->Data.DefineDosDeviceRequest.dwFlags,
|
||||
&Request->Data.DefineDosDeviceRequest.DeviceName,
|
||||
&Request->Data.DefineDosDeviceRequest.TargetName);
|
||||
|
||||
Matched = AddHistory = FALSE;
|
||||
HistoryEntry = NULL;
|
||||
AdminSid = SystemSid = WorldSid = NULL;
|
||||
SecurityDescriptor = NULL;
|
||||
ListHead = &DosDeviceHistory;
|
||||
dwFlags = Request->Data.DefineDosDeviceRequest.dwFlags;
|
||||
|
||||
/* Validate the flags */
|
||||
if ( (dwFlags & 0xFFFFFFF0) ||
|
||||
((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
|
||||
! (dwFlags & DDD_REMOVE_DEFINITION)) )
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = RtlEnterCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
|
||||
Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
Status =
|
||||
RtlUpcaseUnicodeString(&RequestDeviceName,
|
||||
&Request->Data.DefineDosDeviceRequest.DeviceName,
|
||||
TRUE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
_SEH2_LEAVE;
|
||||
|
||||
RequestLinkTarget =
|
||||
&Request->Data.DefineDosDeviceRequest.TargetName;
|
||||
lpBuffer = (PWSTR) RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
RequestDeviceName.MaximumLength + 5 * sizeof(WCHAR));
|
||||
if (! lpBuffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
swprintf(lpBuffer,
|
||||
L"\\??\\%wZ",
|
||||
&RequestDeviceName);
|
||||
RtlInitUnicodeString(&DeviceName,
|
||||
lpBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenSymbolicLinkObject(&LinkHandle,
|
||||
DELETE | 0x1,
|
||||
&ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = NtQuerySymbolicLinkObject(LinkHandle,
|
||||
&LinkTarget,
|
||||
&Length);
|
||||
if (! NT_SUCCESS(Status) &&
|
||||
Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
LinkTarget.Length = 0;
|
||||
LinkTarget.MaximumLength = Length;
|
||||
LinkTarget.Buffer = (PWSTR)
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
Length);
|
||||
if (! LinkTarget.Buffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Status = NtQuerySymbolicLinkObject(LinkHandle,
|
||||
&LinkTarget,
|
||||
&Length);
|
||||
}
|
||||
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
|
||||
&DeviceName, Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
if ((dwFlags & DDD_REMOVE_DEFINITION))
|
||||
{
|
||||
/* If no target name specified we remove the current symlink target */
|
||||
if (RequestLinkTarget->Length == 0)
|
||||
Matched = TRUE;
|
||||
else
|
||||
{
|
||||
if (dwFlags & DDD_EXACT_MATCH_ON_REMOVE)
|
||||
Matched = ! RtlCompareUnicodeString(RequestLinkTarget,
|
||||
&LinkTarget,
|
||||
TRUE);
|
||||
else
|
||||
Matched = RtlPrefixUnicodeString(RequestLinkTarget,
|
||||
&LinkTarget,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
if (Matched && IsListEmpty(ListHead))
|
||||
{
|
||||
/* Current symlink target macthed and there is nothing to revert to */
|
||||
RequestLinkTarget = NULL;
|
||||
}
|
||||
else if (Matched && ! IsListEmpty(ListHead))
|
||||
{
|
||||
/* Fetch the first history entry we come across for the device name */
|
||||
/* This will become the current symlink target for the device name */
|
||||
Matched = FALSE;
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Matched =
|
||||
! RtlCompareUnicodeString(&RequestDeviceName,
|
||||
&HistoryEntry->Device,
|
||||
FALSE);
|
||||
if (Matched)
|
||||
{
|
||||
RemoveEntryList(&HistoryEntry->Entry);
|
||||
RequestLinkTarget = &HistoryEntry->Target;
|
||||
break;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
HistoryEntry = NULL;
|
||||
}
|
||||
|
||||
/* Nothing to revert to so delete the symlink */
|
||||
if (! Matched)
|
||||
RequestLinkTarget = NULL;
|
||||
}
|
||||
else if (! Matched)
|
||||
{
|
||||
/* Locate a previous symlink target as we did not get a hit earlier */
|
||||
/* If we find one we need to remove it */
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Matched =
|
||||
! RtlCompareUnicodeString(&RequestDeviceName,
|
||||
&HistoryEntry->Device,
|
||||
FALSE);
|
||||
if (! Matched)
|
||||
{
|
||||
HistoryEntry = NULL;
|
||||
Entry = Entry->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
Matched = FALSE;
|
||||
if (dwFlags & DDD_EXACT_MATCH_ON_REMOVE)
|
||||
{
|
||||
if (! RtlCompareUnicodeString(RequestLinkTarget,
|
||||
&HistoryEntry->Target,
|
||||
TRUE))
|
||||
{
|
||||
Matched = TRUE;
|
||||
}
|
||||
}
|
||||
else if (RtlPrefixUnicodeString(RequestLinkTarget,
|
||||
&HistoryEntry->Target,
|
||||
TRUE))
|
||||
{
|
||||
Matched = TRUE;
|
||||
}
|
||||
|
||||
if (Matched)
|
||||
{
|
||||
RemoveEntryList(&HistoryEntry->Entry);
|
||||
break;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
HistoryEntry = NULL;
|
||||
}
|
||||
|
||||
/* Leave existing symlink as is */
|
||||
if (! Matched)
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
else
|
||||
Status = STATUS_SUCCESS;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddHistory = TRUE;
|
||||
}
|
||||
|
||||
Status = NtMakeTemporaryObject(LinkHandle);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
|
||||
&DeviceName, Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Status = NtClose(LinkHandle);
|
||||
LinkHandle = NULL;
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
|
||||
&DeviceName, Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't create symlink if we don't have a target */
|
||||
if (! RequestLinkTarget || RequestLinkTarget->Length == 0)
|
||||
_SEH2_LEAVE;
|
||||
|
||||
if (AddHistory)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(CSRSS_DOS_DEVICE_HISTORY_ENTRY));
|
||||
if (! HistoryEntry)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
HistoryEntry->Target.Buffer =
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
LinkTarget.Length);
|
||||
if (! HistoryEntry->Target.Buffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
HistoryEntry->Target.Length =
|
||||
HistoryEntry->Target.MaximumLength =
|
||||
LinkTarget.Length;
|
||||
RtlCopyUnicodeString(&HistoryEntry->Target,
|
||||
&LinkTarget);
|
||||
|
||||
HistoryEntry->Device.Buffer =
|
||||
RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
RequestDeviceName.Length);
|
||||
if (! HistoryEntry->Device.Buffer)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
HistoryEntry->Device.Length =
|
||||
HistoryEntry->Device.MaximumLength =
|
||||
RequestDeviceName.Length;
|
||||
RtlCopyUnicodeString(&HistoryEntry->Device,
|
||||
&RequestDeviceName);
|
||||
|
||||
/* Remember previous symlink target for this device */
|
||||
InsertHeadList(ListHead,
|
||||
&HistoryEntry->Entry);
|
||||
HistoryEntry = NULL;
|
||||
}
|
||||
|
||||
RtlAllocateAndInitializeSid(&WorldAuthority,
|
||||
1,
|
||||
SECURITY_WORLD_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
&WorldSid);
|
||||
|
||||
RtlAllocateAndInitializeSid(&SystemAuthority,
|
||||
1,
|
||||
SECURITY_LOCAL_SYSTEM_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
&SystemSid);
|
||||
|
||||
RtlAllocateAndInitializeSid(&SystemAuthority,
|
||||
2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
SECURITY_NULL_RID,
|
||||
&AdminSid);
|
||||
|
||||
SidLength = RtlLengthSid(SystemSid) +
|
||||
RtlLengthSid(AdminSid) +
|
||||
RtlLengthSid(WorldSid);
|
||||
Length = sizeof(ACL) + SidLength + 3 * sizeof(ACCESS_ALLOWED_ACE);
|
||||
|
||||
SecurityDescriptor = RtlAllocateHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
|
||||
if (! SecurityDescriptor)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory\n");
|
||||
Status = STATUS_NO_MEMORY;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Dacl = (PACL)((ULONG_PTR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
|
||||
Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
Status = RtlCreateAcl(Dacl,
|
||||
Length,
|
||||
ACL_REVISION);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
|
||||
Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
(void) RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
GENERIC_ALL,
|
||||
SystemSid);
|
||||
(void) RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
GENERIC_ALL,
|
||||
AdminSid);
|
||||
(void) RtlAddAccessAllowedAce(Dacl,
|
||||
ACL_REVISION,
|
||||
STANDARD_RIGHTS_READ,
|
||||
WorldSid);
|
||||
|
||||
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
|
||||
TRUE,
|
||||
Dacl,
|
||||
FALSE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
|
||||
Status);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
SecurityDescriptor);
|
||||
Status = NtCreateSymbolicLinkObject(&LinkHandle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
RequestLinkTarget);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = NtMakePermanentObject(LinkHandle);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
|
||||
&DeviceName, Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
|
||||
&DeviceName, Status);
|
||||
}
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
(void) RtlLeaveCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
if (DeviceName.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
DeviceName.Buffer);
|
||||
if (LinkTarget.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
LinkTarget.Buffer);
|
||||
if (SecurityDescriptor)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
SecurityDescriptor);
|
||||
if (LinkHandle)
|
||||
(void) NtClose(LinkHandle);
|
||||
if (SystemSid)
|
||||
(void) RtlFreeSid(SystemSid);
|
||||
if (AdminSid)
|
||||
(void) RtlFreeSid(AdminSid);
|
||||
if (WorldSid)
|
||||
(void) RtlFreeSid(WorldSid);
|
||||
RtlFreeUnicodeString(&RequestDeviceName);
|
||||
if (HistoryEntry)
|
||||
{
|
||||
if (HistoryEntry->Target.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Target.Buffer);
|
||||
if (HistoryEntry->Device.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Device.Buffer);
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry);
|
||||
}
|
||||
}
|
||||
_SEH2_END
|
||||
|
||||
DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
void CsrCleanupDefineDosDevice(void)
|
||||
{
|
||||
PLIST_ENTRY Entry, ListHead;
|
||||
PCSRSS_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
|
||||
|
||||
(void) RtlDeleteCriticalSection(&Win32CsrDefineDosDeviceCritSec);
|
||||
|
||||
ListHead = &DosDeviceHistory;
|
||||
Entry = ListHead->Flink;
|
||||
while (Entry != ListHead)
|
||||
{
|
||||
HistoryEntry = (PCSRSS_DOS_DEVICE_HISTORY_ENTRY)
|
||||
CONTAINING_RECORD(Entry,
|
||||
CSRSS_DOS_DEVICE_HISTORY_ENTRY,
|
||||
Entry);
|
||||
Entry = Entry->Flink;
|
||||
|
||||
if (HistoryEntry)
|
||||
{
|
||||
if (HistoryEntry->Target.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Target.Buffer);
|
||||
if (HistoryEntry->Device.Buffer)
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry->Device.Buffer);
|
||||
(void) RtlFreeHeap(Win32CsrApiHeap,
|
||||
0,
|
||||
HistoryEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* EOF */
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsystem/win32/csrss/win32csr/file.h
|
||||
* PURPOSE: File handling
|
||||
* PROGRAMMERS: Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
* NOTE: Belongs to basesrv.dll
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api.h"
|
||||
|
||||
typedef struct tagCSRSS_DOS_DEVICE_HISTORY_ENTRY
|
||||
{
|
||||
UNICODE_STRING Device;
|
||||
UNICODE_STRING Target;
|
||||
LIST_ENTRY Entry;
|
||||
} CSRSS_DOS_DEVICE_HISTORY_ENTRY, *PCSRSS_DOS_DEVICE_HISTORY_ENTRY;
|
||||
|
||||
/* Api functions */
|
||||
CSR_API(CsrGetTempFile);
|
||||
CSR_API(CsrDefineDosDevice);
|
||||
|
||||
/* functions */
|
||||
void CsrCleanupDefineDosDevice();
|
||||
|
||||
/* EOF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/guiconsole.h
|
||||
* PURPOSE: Interface to GUI consoles
|
||||
*/
|
||||
|
||||
#include "api.h"
|
||||
|
||||
#define CONGUI_MIN_WIDTH 10
|
||||
#define CONGUI_MIN_HEIGHT 10
|
||||
#define CONGUI_UPDATE_TIME 0
|
||||
#define CONGUI_UPDATE_TIMER 1
|
||||
|
||||
NTSTATUS FASTCALL GuiInitConsole(PCSRSS_CONSOLE Console, BOOL Visible);
|
||||
VOID FASTCALL GuiConsoleHandleScrollbarMenu(VOID);
|
||||
|
||||
/*EOF*/
|
||||
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* reactos/subsys/csrss/api/handle.c
|
||||
*
|
||||
* CSRSS handle functions
|
||||
*
|
||||
* ReactOS Operating System
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <w32csr.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static
|
||||
BOOL
|
||||
CsrIsConsoleHandle(HANDLE Handle)
|
||||
{
|
||||
return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
|
||||
}
|
||||
|
||||
static INT
|
||||
AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
|
||||
{
|
||||
Object_t *Object = Entry->Object;
|
||||
if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
|
||||
if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
|
||||
if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
|
||||
if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
|
||||
Object->HandleCount += Change;
|
||||
return Object->HandleCount;
|
||||
}
|
||||
|
||||
static VOID
|
||||
Win32CsrCreateHandleEntry(
|
||||
PCSRSS_HANDLE Entry)
|
||||
{
|
||||
Object_t *Object = Entry->Object;
|
||||
EnterCriticalSection(&Object->Console->Lock);
|
||||
AdjustHandleCounts(Entry, +1);
|
||||
LeaveCriticalSection(&Object->Console->Lock);
|
||||
}
|
||||
|
||||
static VOID
|
||||
Win32CsrCloseHandleEntry(
|
||||
PCSRSS_HANDLE Entry)
|
||||
{
|
||||
Object_t *Object = Entry->Object;
|
||||
if (Object != NULL)
|
||||
{
|
||||
PCSRSS_CONSOLE Console = Object->Console;
|
||||
EnterCriticalSection(&Console->Lock);
|
||||
/* If the last handle to a screen buffer is closed, delete it */
|
||||
if (AdjustHandleCounts(Entry, -1) == 0
|
||||
&& Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
|
||||
{
|
||||
PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
|
||||
/* ...unless it's the only buffer left. Windows allows deletion
|
||||
* even of the last buffer, but having to deal with a lack of
|
||||
* any active buffer might be error-prone. */
|
||||
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
|
||||
ConioDeleteScreenBuffer(Buffer);
|
||||
}
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
Entry->Object = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
Win32CsrReleaseObject(
|
||||
PCSR_PROCESS ProcessData,
|
||||
HANDLE Handle)
|
||||
{
|
||||
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
|
||||
Object_t *Object;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
if (h >= ProcessData->HandleTableSize
|
||||
|| (Object = ProcessData->HandleTable[h].Object) == NULL)
|
||||
{
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
Win32CsrLockObject(PCSR_PROCESS ProcessData,
|
||||
HANDLE Handle,
|
||||
Object_t **Object,
|
||||
DWORD Access,
|
||||
LONG Type)
|
||||
{
|
||||
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
|
||||
|
||||
DPRINT("CsrGetObject, Object: %x, %x, %x\n",
|
||||
Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
|
||||
|| (*Object = ProcessData->HandleTable[h].Object) == NULL
|
||||
|| ~ProcessData->HandleTable[h].Access & Access
|
||||
|| (Type != 0 && (*Object)->Type != Type))
|
||||
{
|
||||
DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
_InterlockedIncrement(&(*Object)->Console->ReferenceCount);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
EnterCriticalSection(&((*Object)->Console->Lock));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
Win32CsrUnlockObject(Object_t *Object)
|
||||
{
|
||||
PCSRSS_CONSOLE Console = Object->Console;
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
/* dec ref count */
|
||||
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
|
||||
ConioDeleteConsole(&Console->Header);
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
Win32CsrReleaseConsole(
|
||||
PCSR_PROCESS ProcessData)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
ULONG i;
|
||||
|
||||
/* Close all console handles and detach process from console */
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
||||
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
|
||||
ProcessData->HandleTableSize = 0;
|
||||
RtlFreeHeap(Win32CsrApiHeap, 0, ProcessData->HandleTable);
|
||||
ProcessData->HandleTable = NULL;
|
||||
|
||||
Console = ProcessData->Console;
|
||||
if (Console != NULL)
|
||||
{
|
||||
ProcessData->Console = NULL;
|
||||
EnterCriticalSection(&Console->Lock);
|
||||
RemoveEntryList(&ProcessData->ConsoleLink);
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
|
||||
ConioDeleteConsole(&Console->Header);
|
||||
//CloseHandle(ProcessData->ConsoleEvent);
|
||||
//ProcessData->ConsoleEvent = NULL;
|
||||
}
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
Win32CsrInsertObject(
|
||||
PCSR_PROCESS ProcessData,
|
||||
PHANDLE Handle,
|
||||
Object_t *Object,
|
||||
DWORD Access,
|
||||
BOOL Inheritable,
|
||||
DWORD ShareMode)
|
||||
{
|
||||
ULONG i;
|
||||
PCSRSS_HANDLE Block;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
||||
{
|
||||
if (ProcessData->HandleTable[i].Object == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= ProcessData->HandleTableSize)
|
||||
{
|
||||
Block = RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
(ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
|
||||
if (Block == NULL)
|
||||
{
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
RtlCopyMemory(Block,
|
||||
ProcessData->HandleTable,
|
||||
ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
|
||||
RtlFreeHeap(Win32CsrApiHeap, 0, ProcessData->HandleTable);
|
||||
ProcessData->HandleTable = Block;
|
||||
ProcessData->HandleTableSize += 64;
|
||||
}
|
||||
ProcessData->HandleTable[i].Object = Object;
|
||||
ProcessData->HandleTable[i].Access = Access;
|
||||
ProcessData->HandleTable[i].Inheritable = Inheritable;
|
||||
ProcessData->HandleTable[i].ShareMode = ShareMode;
|
||||
Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
|
||||
*Handle = UlongToHandle((i << 2) | 0x3);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
WINAPI
|
||||
Win32CsrDuplicateHandleTable(
|
||||
PCSR_PROCESS SourceProcessData,
|
||||
PCSR_PROCESS TargetProcessData)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
/* Only inherit if the flag was set */
|
||||
if (!TargetProcessData->bInheritHandles) return STATUS_SUCCESS;
|
||||
|
||||
if (TargetProcessData->HandleTableSize)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
|
||||
|
||||
/* we are called from CreateProcessData, it isn't necessary to lock the target process data */
|
||||
|
||||
TargetProcessData->HandleTable = RtlAllocateHeap(Win32CsrApiHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
SourceProcessData->HandleTableSize
|
||||
* sizeof(CSRSS_HANDLE));
|
||||
if (TargetProcessData->HandleTable == NULL)
|
||||
{
|
||||
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
|
||||
for (i = 0; i < SourceProcessData->HandleTableSize; i++)
|
||||
{
|
||||
if (SourceProcessData->HandleTable[i].Object != NULL &&
|
||||
SourceProcessData->HandleTable[i].Inheritable)
|
||||
{
|
||||
TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
|
||||
Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
CSR_API(CsrGetHandle)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
Request->Data.GetInputHandleRequest.Handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
if (ProcessData->Console)
|
||||
{
|
||||
DWORD DesiredAccess = Request->Data.GetInputHandleRequest.Access;
|
||||
DWORD ShareMode = Request->Data.GetInputHandleRequest.ShareMode;
|
||||
|
||||
PCSRSS_CONSOLE Console = ProcessData->Console;
|
||||
Object_t *Object;
|
||||
|
||||
EnterCriticalSection(&Console->Lock);
|
||||
if (Request->Type == GET_OUTPUT_HANDLE)
|
||||
Object = &Console->ActiveBuffer->Header;
|
||||
else
|
||||
Object = &Console->Header;
|
||||
|
||||
if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
|
||||
((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
|
||||
{
|
||||
DPRINT1("Sharing violation\n");
|
||||
Status = STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = Win32CsrInsertObject(ProcessData,
|
||||
&Request->Data.GetInputHandleRequest.Handle,
|
||||
Object,
|
||||
DesiredAccess,
|
||||
Request->Data.GetInputHandleRequest.Inheritable,
|
||||
ShareMode);
|
||||
}
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrCloseHandle)
|
||||
{
|
||||
return Win32CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
|
||||
}
|
||||
|
||||
CSR_API(CsrVerifyHandle)
|
||||
{
|
||||
ULONG_PTR Index;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
Index = (ULONG_PTR)Request->Data.VerifyHandleRequest.Handle >> 2;
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
if (Index >= ProcessData->HandleTableSize ||
|
||||
ProcessData->HandleTable[Index].Object == NULL)
|
||||
{
|
||||
DPRINT("CsrVerifyObject failed\n");
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrDuplicateHandle)
|
||||
{
|
||||
ULONG_PTR Index;
|
||||
PCSRSS_HANDLE Entry;
|
||||
DWORD DesiredAccess;
|
||||
|
||||
Index = (ULONG_PTR)Request->Data.DuplicateHandleRequest.Handle >> 2;
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
if (Index >= ProcessData->HandleTableSize
|
||||
|| (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
|
||||
{
|
||||
DPRINT1("Couldn't dup invalid handle %p\n", Request->Data.DuplicateHandleRequest.Handle);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (Request->Data.DuplicateHandleRequest.Options & DUPLICATE_SAME_ACCESS)
|
||||
{
|
||||
DesiredAccess = Entry->Access;
|
||||
}
|
||||
else
|
||||
{
|
||||
DesiredAccess = Request->Data.DuplicateHandleRequest.Access;
|
||||
/* Make sure the source handle has all the desired flags */
|
||||
if (~Entry->Access & DesiredAccess)
|
||||
{
|
||||
DPRINT1("Handle %p only has access %X; requested %X\n",
|
||||
Request->Data.DuplicateHandleRequest.Handle, Entry->Access, DesiredAccess);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
Request->Status = Win32CsrInsertObject(ProcessData,
|
||||
&Request->Data.DuplicateHandleRequest.Handle,
|
||||
Entry->Object,
|
||||
DesiredAccess,
|
||||
Request->Data.DuplicateHandleRequest.Inheritable,
|
||||
Entry->ShareMode);
|
||||
if (NT_SUCCESS(Request->Status)
|
||||
&& Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
|
||||
{
|
||||
Win32CsrCloseHandleEntry(Entry);
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Request->Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetInputWaitHandle)
|
||||
{
|
||||
Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,578 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/dllmain.c
|
||||
* PURPOSE: Initialization
|
||||
* PROGRAMMERS: Dmitry Philippov (shedon@mail.ru)
|
||||
* Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define IDTRYAGAIN 10
|
||||
#define IDCONTINUE 11
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CsrpGetClientFileName(
|
||||
OUT PUNICODE_STRING ClientFileNameU,
|
||||
HANDLE hProcess)
|
||||
{
|
||||
PLIST_ENTRY ModuleListHead;
|
||||
PLIST_ENTRY Entry;
|
||||
PLDR_DATA_TABLE_ENTRY Module;
|
||||
PPEB_LDR_DATA Ldr;
|
||||
PROCESS_BASIC_INFORMATION ClientBasicInfo;
|
||||
LDR_DATA_TABLE_ENTRY ModuleData;
|
||||
PVOID ClientDllBase;
|
||||
NTSTATUS Status;
|
||||
PPEB Peb;
|
||||
|
||||
/* Initialize string */
|
||||
ClientFileNameU->MaximumLength = 0;
|
||||
ClientFileNameU->Length = 0;
|
||||
ClientFileNameU->Buffer = NULL;
|
||||
|
||||
/* Query process information */
|
||||
Status = NtQueryInformationProcess(hProcess,
|
||||
ProcessBasicInformation,
|
||||
&ClientBasicInfo,
|
||||
sizeof(ClientBasicInfo),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Peb = ClientBasicInfo.PebBaseAddress;
|
||||
if (!Peb) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
ModuleListHead = &Ldr->InLoadOrderModuleList;
|
||||
Status = NtReadVirtualMemory(hProcess,
|
||||
&ModuleListHead->Flink,
|
||||
&Entry,
|
||||
sizeof(Entry),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
|
||||
Status = NtReadVirtualMemory(hProcess,
|
||||
Module,
|
||||
&ModuleData,
|
||||
sizeof(ModuleData),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Status = NtReadVirtualMemory(hProcess,
|
||||
&Peb->ImageBaseAddress,
|
||||
&ClientDllBase,
|
||||
sizeof(ClientDllBase),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL;
|
||||
|
||||
ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength;
|
||||
ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
ClientFileNameU->MaximumLength);
|
||||
|
||||
Status = NtReadVirtualMemory(hProcess,
|
||||
ModuleData.BaseDllName.Buffer,
|
||||
ClientFileNameU->Buffer,
|
||||
ClientFileNameU->MaximumLength,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer);
|
||||
ClientFileNameU->Buffer = NULL;
|
||||
ClientFileNameU->MaximumLength = 0;
|
||||
return Status;
|
||||
}
|
||||
|
||||
ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer)*sizeof(wchar_t);
|
||||
DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
CsrpFreeStringParameters(
|
||||
IN OUT PULONG_PTR Parameters,
|
||||
IN PHARDERROR_MSG HardErrorMessage)
|
||||
{
|
||||
ULONG nParam;
|
||||
|
||||
/* Loop all parameters */
|
||||
for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++)
|
||||
{
|
||||
/* Check if the current parameter is a string */
|
||||
if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam) && Parameters[nParam])
|
||||
{
|
||||
/* Free the string buffer */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CsrpCaptureStringParameters(
|
||||
OUT PULONG_PTR Parameters,
|
||||
OUT PULONG SizeOfAllUnicodeStrings,
|
||||
IN PHARDERROR_MSG HardErrorMessage,
|
||||
HANDLE hProcess)
|
||||
{
|
||||
ULONG nParam, Size = 0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
UNICODE_STRING TempStringU, ParamStringU;
|
||||
ANSI_STRING TempStringA;
|
||||
|
||||
/* Read all strings from client space */
|
||||
for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++)
|
||||
{
|
||||
Parameters[nParam] = 0;
|
||||
|
||||
/* Check if the current parameter is a unicode string */
|
||||
if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam))
|
||||
{
|
||||
/* Read the UNICODE_STRING from the process memory */
|
||||
Status = NtReadVirtualMemory(hProcess,
|
||||
(PVOID)HardErrorMessage->Parameters[nParam],
|
||||
&ParamStringU,
|
||||
sizeof(ParamStringU),
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
|
||||
/* Allocate a buffer for the string */
|
||||
TempStringU.MaximumLength = ParamStringU.Length;
|
||||
TempStringU.Length = ParamStringU.Length;
|
||||
TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
TempStringU.MaximumLength);
|
||||
|
||||
if (!TempStringU.Buffer)
|
||||
{
|
||||
DPRINT1("Cannot allocate memory %u\n", TempStringU.MaximumLength);
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Read the string buffer from the process memory */
|
||||
Status = NtReadVirtualMemory(hProcess,
|
||||
ParamStringU.Buffer,
|
||||
TempStringU.Buffer,
|
||||
ParamStringU.Length,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINT("ParamString=\'%wZ\'\n", &TempStringU);
|
||||
|
||||
/* Allocate a buffer for converted to ANSI string */
|
||||
TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU);
|
||||
TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
TempStringA.MaximumLength);
|
||||
|
||||
if (!TempStringA.Buffer)
|
||||
{
|
||||
DPRINT1("Cannot allocate memory %u\n", TempStringA.MaximumLength);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
||||
Status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Convert string to ANSI and free temporary buffer */
|
||||
Status = RtlUnicodeStringToAnsiString(&TempStringA, &TempStringU, FALSE);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */
|
||||
Parameters[nParam] = (ULONG_PTR)TempStringA.Buffer;
|
||||
Size += TempStringU.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's not a unicode string */
|
||||
Parameters[nParam] = HardErrorMessage->Parameters[nParam];
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
CsrpFreeStringParameters(Parameters, HardErrorMessage);
|
||||
return Status;
|
||||
}
|
||||
|
||||
*SizeOfAllUnicodeStrings = Size;
|
||||
return Status;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
CsrpFormatMessages(
|
||||
OUT PUNICODE_STRING TextStringU,
|
||||
OUT PUNICODE_STRING CaptionStringU,
|
||||
IN PULONG_PTR Parameters,
|
||||
IN ULONG SizeOfStrings,
|
||||
IN PHARDERROR_MSG Message,
|
||||
IN HANDLE hProcess)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING FileNameU, TempStringU, FormatU;
|
||||
ANSI_STRING FormatA;
|
||||
PMESSAGE_RESOURCE_ENTRY MessageResource;
|
||||
PWSTR FormatString;
|
||||
ULONG Size, ExceptionCode;
|
||||
|
||||
/* Get the file name of the client process */
|
||||
CsrpGetClientFileName(&FileNameU, hProcess);
|
||||
|
||||
/* Check if we have a file name */
|
||||
if (!FileNameU.Buffer)
|
||||
{
|
||||
/* No, use system */
|
||||
RtlInitUnicodeString(&FileNameU, L"System");
|
||||
}
|
||||
|
||||
/* Get text string of the error code */
|
||||
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
||||
(ULONG_PTR)RT_MESSAGETABLE,
|
||||
LANG_NEUTRAL,
|
||||
Message->Status,
|
||||
&MessageResource);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (MessageResource->Flags)
|
||||
{
|
||||
RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text);
|
||||
FormatA.Buffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text);
|
||||
RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fall back to hardcoded value */
|
||||
RtlInitUnicodeString(&FormatU, L"Unknown Hard Error");
|
||||
FormatA.Buffer = NULL;
|
||||
}
|
||||
|
||||
FormatString = FormatU.Buffer;
|
||||
|
||||
/* Check whether a caption exists */
|
||||
if (FormatString[0] == L'{')
|
||||
{
|
||||
/* Set caption start */
|
||||
TempStringU.Buffer = ++FormatString;
|
||||
|
||||
/* Get size of the caption */
|
||||
for (Size = 0; *FormatString != 0 && *FormatString != L'}'; Size++)
|
||||
FormatString++;
|
||||
|
||||
/* Skip '}', '\r', '\n' */
|
||||
FormatString += 3;
|
||||
|
||||
TempStringU.Length = Size * sizeof(WCHAR);
|
||||
TempStringU.MaximumLength = TempStringU.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Set string based on severity */
|
||||
RtlInitUnicodeString(&TempStringU, L"Application Error");
|
||||
}
|
||||
|
||||
/* Calculate buffer length for the caption */
|
||||
CaptionStringU->MaximumLength = FileNameU.Length + TempStringU.Length +
|
||||
4 * sizeof(WCHAR);
|
||||
|
||||
/* Allocate a buffer for the caption */
|
||||
CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
CaptionStringU->MaximumLength);
|
||||
|
||||
/* Append the file name, seperator and the caption text */
|
||||
CaptionStringU->Length = 0;
|
||||
RtlAppendUnicodeStringToString(CaptionStringU, &FileNameU);
|
||||
RtlAppendUnicodeToString(CaptionStringU, L" - ");
|
||||
RtlAppendUnicodeStringToString(CaptionStringU, &TempStringU);
|
||||
|
||||
/* Zero terminate the buffer */
|
||||
CaptionStringU->Buffer[CaptionStringU->Length / sizeof(WCHAR)] = 0;
|
||||
|
||||
/* Free the file name buffer */
|
||||
RtlFreeUnicodeString(&FileNameU);
|
||||
|
||||
/* Check if this is an exception message */
|
||||
if (Message->Status == STATUS_UNHANDLED_EXCEPTION)
|
||||
{
|
||||
ExceptionCode = Parameters[0];
|
||||
|
||||
/* Handle special cases */
|
||||
if (ExceptionCode == STATUS_ACCESS_VIOLATION)
|
||||
{
|
||||
Parameters[0] = Parameters[1];
|
||||
Parameters[1] = Parameters[3];
|
||||
if (Parameters[2]) Parameters[2] = (ULONG_PTR)L"written";
|
||||
else Parameters[2] = (ULONG_PTR)L"read";
|
||||
MessageResource = NULL;
|
||||
}
|
||||
else if (ExceptionCode == STATUS_IN_PAGE_ERROR)
|
||||
{
|
||||
Parameters[0] = Parameters[1];
|
||||
Parameters[1] = Parameters[3];
|
||||
MessageResource = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fall back to hardcoded value */
|
||||
Parameters[2] = Parameters[1];
|
||||
Parameters[1] = Parameters[0];
|
||||
Parameters[0] = (ULONG_PTR)L"unknown software exception";
|
||||
}
|
||||
|
||||
if (!MessageResource)
|
||||
{
|
||||
/* Get text string of the exception code */
|
||||
Status = RtlFindMessage(GetModuleHandleW(L"ntdll"),
|
||||
(ULONG_PTR)RT_MESSAGETABLE,
|
||||
LANG_NEUTRAL,
|
||||
ExceptionCode,
|
||||
&MessageResource);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
|
||||
|
||||
if (MessageResource->Flags)
|
||||
{
|
||||
RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text);
|
||||
FormatA.Buffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text);
|
||||
RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE);
|
||||
}
|
||||
FormatString = FormatU.Buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fall back to hardcoded value */
|
||||
Parameters[2] = Parameters[1];
|
||||
Parameters[1] = Parameters[0];
|
||||
Parameters[0] = (ULONG_PTR)L"unknown software exception";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate length of text buffer */
|
||||
TextStringU->MaximumLength = FormatU.Length + SizeOfStrings + 42 * sizeof(WCHAR);
|
||||
|
||||
/* Allocate a buffer for the text */
|
||||
TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
TextStringU->MaximumLength);
|
||||
|
||||
/* Wrap in SEH to protect from invalid string parameters */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Print the string into the buffer */
|
||||
StringCbPrintfW(TextStringU->Buffer,
|
||||
TextStringU->MaximumLength,
|
||||
FormatString,
|
||||
Parameters[0],
|
||||
Parameters[1],
|
||||
Parameters[2],
|
||||
Parameters[3]);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Set error and free buffers */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer);
|
||||
}
|
||||
_SEH2_END
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static
|
||||
ULONG
|
||||
CsrpMessageBox(
|
||||
PWSTR Text,
|
||||
PWSTR Caption,
|
||||
ULONG ValidResponseOptions,
|
||||
ULONG Severity)
|
||||
{
|
||||
ULONG Type, MessageBoxResponse;
|
||||
|
||||
/* Set the message box type */
|
||||
switch (ValidResponseOptions)
|
||||
{
|
||||
case OptionAbortRetryIgnore:
|
||||
Type = MB_ABORTRETRYIGNORE;
|
||||
break;
|
||||
case OptionOk:
|
||||
Type = MB_OK;
|
||||
break;
|
||||
case OptionOkCancel:
|
||||
Type = MB_OKCANCEL;
|
||||
break;
|
||||
case OptionRetryCancel:
|
||||
Type = MB_RETRYCANCEL;
|
||||
break;
|
||||
case OptionYesNo:
|
||||
Type = MB_YESNO;
|
||||
break;
|
||||
case OptionYesNoCancel:
|
||||
Type = MB_YESNOCANCEL;
|
||||
break;
|
||||
case OptionShutdownSystem:
|
||||
Type = MB_RETRYCANCEL; // FIXME???
|
||||
break;
|
||||
/* Anything else is invalid */
|
||||
default:
|
||||
return ResponseNotHandled;
|
||||
}
|
||||
|
||||
/* Set severity */
|
||||
if (Severity == STATUS_SEVERITY_INFORMATIONAL) Type |= MB_ICONINFORMATION;
|
||||
else if (Severity == STATUS_SEVERITY_WARNING) Type |= MB_ICONWARNING;
|
||||
else if (Severity == STATUS_SEVERITY_ERROR) Type |= MB_ICONERROR;
|
||||
|
||||
Type |= MB_SYSTEMMODAL | MB_SETFOREGROUND;
|
||||
|
||||
DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n",
|
||||
Text, Caption, Severity, Type);
|
||||
|
||||
/* Display a message box */
|
||||
MessageBoxResponse = MessageBoxW(0, Text, Caption, Type);
|
||||
|
||||
/* Return response value */
|
||||
switch (MessageBoxResponse)
|
||||
{
|
||||
case IDOK: return ResponseOk;
|
||||
case IDCANCEL: return ResponseCancel;
|
||||
case IDYES: return ResponseYes;
|
||||
case IDNO: return ResponseNo;
|
||||
case IDABORT: return ResponseAbort;
|
||||
case IDIGNORE: return ResponseIgnore;
|
||||
case IDRETRY: return ResponseRetry;
|
||||
case IDTRYAGAIN: return ResponseTryAgain;
|
||||
case IDCONTINUE: return ResponseContinue;
|
||||
}
|
||||
|
||||
return ResponseNotHandled;
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
Win32CsrHardError(
|
||||
IN PCSR_THREAD ThreadData,
|
||||
IN PHARDERROR_MSG Message)
|
||||
{
|
||||
#if DBG
|
||||
PCSR_PROCESS ProcessData = ThreadData->Process;
|
||||
#endif
|
||||
ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS];
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING TextU, CaptionU;
|
||||
NTSTATUS Status;
|
||||
HANDLE hProcess;
|
||||
ULONG Size;
|
||||
|
||||
/* Default to not handled */
|
||||
ASSERT(ProcessData != NULL);
|
||||
Message->Response = ResponseNotHandled;
|
||||
|
||||
/* Make sure we don't have too many parameters */
|
||||
if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
|
||||
Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS;
|
||||
|
||||
/* Initialize object attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||
|
||||
/* Open client process */
|
||||
Status = NtOpenProcess(&hProcess,
|
||||
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
|
||||
&ObjectAttributes,
|
||||
&Message->h.ClientId);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtOpenProcess failed with code: %lx\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Capture all string parameters from the process memory */
|
||||
Status = CsrpCaptureStringParameters(Parameters, &Size, Message, hProcess);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(hProcess);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Format the caption and message box text */
|
||||
Status = CsrpFormatMessages(&TextU,
|
||||
&CaptionU,
|
||||
Parameters,
|
||||
Size,
|
||||
Message,
|
||||
hProcess);
|
||||
|
||||
/* Cleanup */
|
||||
CsrpFreeStringParameters(Parameters, Message);
|
||||
NtClose(hProcess);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Display the message box */
|
||||
Message->Response = CsrpMessageBox(TextU.Buffer,
|
||||
CaptionU.Buffer,
|
||||
Message->ValidResponseOptions,
|
||||
(ULONG)Message->Status >> 30);
|
||||
|
||||
RtlFreeUnicodeString(&TextU);
|
||||
RtlFreeUnicodeString(&CaptionU);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* FILE: subsystems/win32/csrss/win32csr/lang/bg-BG.rc
|
||||
* PURPOSE: Bulgarian resource file
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Прекратяване на приложение - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Прекратяване на приложението... Почакайте",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Ход",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Ако решите да затворите приложението веднага, ще изгубите всички незаписани данни. За да прекратите приложението веднага, натиснете „Прекратяване веднага„.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Прекратяване веднага",IDC_END_NOW,150,71,60,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Прекратяване на приложение - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Отказ",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Прекратяване веднага",IDC_END_NOW,150,71,60,17
|
||||
LTEXT "Приложението не отговаря",IDC_STATIC,7,7,178,8
|
||||
LTEXT "За да се върнете в РеактОС и да проверите състоянието на приложението, натиснете „Отказ“.",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Ако решите да затворите приложението веднага, ще изгубите всички незаписани данни. За да прекратите приложението веднага, натиснете „Прекратяване веднага“.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Обработка"
|
||||
IDS_MARK "Отбелязване"
|
||||
IDS_COPY "Запомняне\tEnter"
|
||||
IDS_PASTE "Поставяне"
|
||||
IDS_SELECTALL "Избор на всичко"
|
||||
IDS_SCROLL "Прелистване"
|
||||
IDS_FIND "Търсене..."
|
||||
IDS_DEFAULTS "Подразбирани"
|
||||
IDS_PROPERTIES "Свойства"
|
||||
IDS_SCROLLHERE "Прелистване тук"
|
||||
IDS_SCROLLTOP "Прелистване до горе"
|
||||
IDS_SCROLLBOTTOM "Прелистване до долу"
|
||||
IDS_SCROLLPAGE_UP "Горна страница"
|
||||
IDS_SCROLLPAGE_DOWN "Долна страница"
|
||||
IDS_SCROLLUP "Прелистване нагоре"
|
||||
IDS_SCROLLDOWN "Прелистване надолу"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,63 @@
|
||||
/* FILE: subsystems/win32/csrss/win32csr/lang/cs-CZ.rc
|
||||
* TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com)
|
||||
* UPDATED: 2011-04-09
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ukonèit program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Probíhá ukonèení programu... Èekejte, prosím",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "IPokud zvolíte okamžité ukonèení programu, všechna neuložená data budou ztracena. Kliknutím na Ukonèit okamžitì ukonèíte program.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Ukonèit okamžitì",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ukonèit program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Storno",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Ukonèit okamžitì",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Tento program neodpovídá",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Kliknutím na Storno se lze vrátit do systému ReactOS a ovìøit stav programu",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Pokud zvolíte okamžité ukonèení programu, všechna neuložená data budou ztracena. Kliknutím na Ukonèit okamžitì ukonèíte program.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Upravit"
|
||||
IDS_MARK "Oznaèit"
|
||||
IDS_COPY "Kopírovat\tEnter"
|
||||
IDS_PASTE "Vložit"
|
||||
IDS_SELECTALL "Oznaèit vše"
|
||||
IDS_SCROLL "Posunout"
|
||||
IDS_FIND "Najít..."
|
||||
IDS_DEFAULTS "Výchozí"
|
||||
IDS_PROPERTIES "Vlastnosti"
|
||||
IDS_SCROLLHERE "Posunout sem"
|
||||
IDS_SCROLLTOP "Posunout na zaèátek"
|
||||
IDS_SCROLLBOTTOM "Posunout na konec"
|
||||
IDS_SCROLLPAGE_UP "O stránku výše"
|
||||
IDS_SCROLLPAGE_DOWN "O stránku níže"
|
||||
IDS_SCROLLUP "Posunout nahoru"
|
||||
IDS_SCROLLDOWN "Posunout dolù"
|
||||
|
||||
IDS_COMMAND_PROMPT "Pøíkazový øádek"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Programm beenden - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Programm wird beendet...",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Fortschritt",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Wenn Sie das Programm sofort beenden, werden Sie eventuell ungespeicherte Daten verlieren. Um das Programm zu beenden, wählen Sie Jetzt beenden.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "J&etzt beenden",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Programm beenden - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Abbechen",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "J&etzt beenden",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Das Programm reagiert nicht",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Um zu ReactOS zurückzukehren und den Status der Anwendung zu überprüfen, wählen Sie Abbrechen.",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Wenn Sie das Programm sofort beenden, werden Sie eventuell ungespeicherte Daten verlieren. Um das Programm zu beenden, wählen Sie Jetzt beenden.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Bearbeiten"
|
||||
IDS_MARK "Markieren"
|
||||
IDS_COPY "Kopieren\tEnter"
|
||||
IDS_PASTE "Einfügen"
|
||||
IDS_SELECTALL "Alles auswählen"
|
||||
IDS_SCROLL "Scrollen"
|
||||
IDS_FIND "Suchen..."
|
||||
IDS_DEFAULTS "Standardwerte"
|
||||
IDS_PROPERTIES "Eigenschaften"
|
||||
IDS_SCROLLHERE "Hier scrollen"
|
||||
IDS_SCROLLTOP "Ganz nach oben scrollen"
|
||||
IDS_SCROLLBOTTOM "Ganz nach unten scrollen"
|
||||
IDS_SCROLLPAGE_UP "Seite nach oben"
|
||||
IDS_SCROLLPAGE_DOWN "Seite nach unten"
|
||||
IDS_SCROLLUP "Nach oben scrollen"
|
||||
IDS_SCROLLDOWN "Nach unten scrollen"
|
||||
|
||||
IDS_COMMAND_PROMPT "Eingabeaufforderung"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_GREEK, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Êëåßóéìï ðñïãñÜììáôïò - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Êëåßóéìï ðñïãñÜììáôïò... Ðáñáêáëþ ðåñéìÝíåôå",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Ðñüïäïò",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Áí êëåßóåôå ôçí åöáñìïãÞ ôþñá , èá ÷Üóåôå üëá ôá ìç áðïèçêåõìÝíá äåäïìÝíá. Ãéá íá êëåßóåôå ôï ðñüãñáììá ôþñá, ðáôÞóôå 'Êëåßóéìï Ôþñá'.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Êëåßóéìï Ôþñá",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Êëåßóçìï ðñïãñÜììáôïò - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "¢êõñï",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Êëåßóéìï Ôþñá",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Ôï ðñüãñáììá äåí áðïêñßíåôáé",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Ãéá íá åðéóôñÝøåôå óôï ReactOS êáé íá åëÝãîåôå ôçí êáôÜóôáóç ôïõ ðñïãñÜììáôïò, ðáôÞóôå '¢êõñï'",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Áí êëåßóåôå ôçí åöáñìïãÞ ôþñá , èá ÷Üóåôå üëá ôá ìç áðïèçêåõìÝíá äåäïìÝíá. Ãéá íá êëåßóåôå ôï ðñüãñáììá ôþñá, ðáôÞóôå 'Êëåßóéìï Ôþñá'.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Åðåîåñãáóßá"
|
||||
IDS_MARK "ÌáñêÜñéóìá"
|
||||
IDS_COPY "ÁíôéãñáöÞ\tEnter"
|
||||
IDS_PASTE "Åðéêüëëçóç"
|
||||
IDS_SELECTALL "ÅðéëïãÞ üëùí"
|
||||
IDS_SCROLL "Êýëéóç"
|
||||
IDS_FIND "Åýñåóç..."
|
||||
IDS_DEFAULTS "ÐñïåðéëïãÞ"
|
||||
IDS_PROPERTIES "Éäéüôçôåò"
|
||||
IDS_SCROLLHERE "Êýëéóç åäþ"
|
||||
IDS_SCROLLTOP "Áñ÷Þ"
|
||||
IDS_SCROLLBOTTOM "ÔÝëïò"
|
||||
IDS_SCROLLPAGE_UP "Ðñïçãïýìåíç óåëßäá"
|
||||
IDS_SCROLLPAGE_DOWN "Åðüìåíç óåëßäá"
|
||||
IDS_SCROLLUP "Êýëéóç ðÜíù"
|
||||
IDS_SCROLLDOWN "Êýëéóç êÜôù"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "End Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Ending Program... Please wait",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "If you choose to end the program immediately, you will lose any unsaved data. To end the program now, click End Now.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&End Now",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "End Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Cancel",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&End Now",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "This program is not responding",IDC_STATIC,7,7,178,8
|
||||
LTEXT "To return to ReactOS and check the status of the program, click Cancel",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "If you choose to end the program immediately, you will lose any unsaved data. To end the program now, click End Now",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Edit"
|
||||
IDS_MARK "Mark"
|
||||
IDS_COPY "Copy\tEnter"
|
||||
IDS_PASTE "Paste"
|
||||
IDS_SELECTALL "Select All"
|
||||
IDS_SCROLL "Scroll"
|
||||
IDS_FIND "Find..."
|
||||
IDS_DEFAULTS "Defaults"
|
||||
IDS_PROPERTIES "Properties"
|
||||
IDS_SCROLLHERE "Scroll here"
|
||||
IDS_SCROLLTOP "Scroll top"
|
||||
IDS_SCROLLBOTTOM "Scroll bottom"
|
||||
IDS_SCROLLPAGE_UP "Page up"
|
||||
IDS_SCROLLPAGE_DOWN "Page down"
|
||||
IDS_SCROLLUP "Scroll up"
|
||||
IDS_SCROLLDOWN "Scroll down"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
*Spanish Language resource file
|
||||
* Traducido por: Javier Remacha 2008-26-01
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Finalizar programa - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Finalizando programa... Por favor, espere",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progreso",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Si elige finalizar el programa ahora, perderá todos los datos no guardados. Para finalizar el programa ahora, haga clic en Finalizar ahora.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Finalizar ahora",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Finalizar programa - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Cancelar",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Finalizar ahora",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Este programa no responde",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Para volver a ReactOS y ver el estado del programa, haga clic en Cancelar",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Si elige finalizar el programa ahora, perderá todos los datos no guardados. Para finalizar el programa ahora, haga clic en Finalizar ahora.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Editar"
|
||||
IDS_MARK "Marcar"
|
||||
IDS_COPY "Copiar\tIntroducir"
|
||||
IDS_PASTE "Pegar"
|
||||
IDS_SELECTALL "Seleccionar Todo"
|
||||
IDS_SCROLL "Desplazar"
|
||||
IDS_FIND "Buscar..."
|
||||
IDS_DEFAULTS "Por defecto"
|
||||
IDS_PROPERTIES "Propiedades"
|
||||
IDS_SCROLLHERE "Desplazar aquí"
|
||||
IDS_SCROLLTOP "Desplazar hasta arriba"
|
||||
IDS_SCROLLBOTTOM "Desplazar hasta abajo"
|
||||
IDS_SCROLLPAGE_UP "Subir página"
|
||||
IDS_SCROLLPAGE_DOWN "Bajar página"
|
||||
IDS_SCROLLUP "Desplazar arriba"
|
||||
IDS_SCROLLDOWN "Desplazar abajo"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,60 @@
|
||||
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Fin du programme - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Termine le programme... Veuillez patienter",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Avancement",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Si vous choisissez de terminer le programme immédiatement, vous perdrez toutes les données non sauvegardées. Pour terminer le programme maintenant, cliquez sur Terminer maintenant.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "T&erminer maintenant",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Fin du programme - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Annuler",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "T&erminer maintenant",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Ce programme ne répond pas",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Pour retourner à ReactOS et vérifier l'état du programme, cliquez sur Annuler",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Si vous choisissez de terminer le programme immédiatement, vous perdrez toutes les données non sauvegardées. Pour terminer le programme maintenant, cliquez sur Terminer maintenant",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
/* Fixme : Translation could be really improved, with context
|
||||
La traduction pourrait réellement être améliorée grâce au contexte */
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Éditer"
|
||||
IDS_MARK "Marquer"
|
||||
IDS_COPY "Copier\tEntrée"
|
||||
IDS_PASTE "Coller"
|
||||
IDS_SELECTALL "Tout sélectionner"
|
||||
IDS_SCROLL "Défiler"
|
||||
IDS_FIND "Trouver..."
|
||||
IDS_DEFAULTS "Défauts"
|
||||
IDS_PROPERTIES "Propriétés"
|
||||
IDS_SCROLLHERE "Défiler ici"
|
||||
IDS_SCROLLTOP "Défiler tout en haut"
|
||||
IDS_SCROLLBOTTOM "Défiler tout en bas"
|
||||
IDS_SCROLLPAGE_UP "Page précédente"
|
||||
IDS_SCROLLPAGE_DOWN "Page suivante"
|
||||
IDS_SCROLLUP "Défiler en haut"
|
||||
IDS_SCROLLDOWN "Défiler en bas"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "סיום תכנית - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "מסיים תכנית... נא להמתין",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "If you choose to end the program immediately, you will lose any unsaved data. To end the program now, click End Now.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "סיים כעת",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "סיום תכנית - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "ביטול",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "סיים כעת",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "התכנית אינה מגיבה",IDC_STATIC,7,7,178,8
|
||||
LTEXT "To return to ReactOS and check the status of the program, click Cancel",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "If you choose to end the program immediately, you will lose any unsaved data. To end the program now, click End Now",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "ערוך"
|
||||
IDS_MARK "סמן"
|
||||
IDS_COPY "העתק\tEnter"
|
||||
IDS_PASTE "הדבק"
|
||||
IDS_SELECTALL "בחר הכל"
|
||||
IDS_SCROLL "גלול"
|
||||
IDS_FIND "מצא..."
|
||||
IDS_DEFAULTS "ברירת מחדל"
|
||||
IDS_PROPERTIES "מאפיינים"
|
||||
IDS_SCROLLHERE "גלול לכאן"
|
||||
IDS_SCROLLTOP "גלול למעלה"
|
||||
IDS_SCROLLBOTTOM "גלול למטה"
|
||||
IDS_SCROLLPAGE_UP "עמוד מעלה"
|
||||
IDS_SCROLLPAGE_DOWN "עמוד מטה"
|
||||
IDS_SCROLLUP "גלול מעלה"
|
||||
IDS_SCROLLDOWN "גלול מטה"
|
||||
|
||||
IDS_COMMAND_PROMPT "שורת הפקודה"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Akhir Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Mengakhiri Program... Harap menunggu",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progres",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Jika anda memilih untuk segera mengakhiri program, anda akan kehilangan data yang belum disimpan. Untuk mengakhiri program sekarang, klik Akhiri Sekarang.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Akhiri Sekarang",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Mengakhiri Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Batal",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Akhiri Sekarang",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Program ini tidak merespon",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Untuk kembali ke ReactOS dan memeriksa status program, klik Batal",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Jika anda memilih untuk segera mengakhiri program, anda akan kehilangan data yang belum disimpan. Untuk mengakhiri program sekarang, klik Akhiri Sekarang.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Edit"
|
||||
IDS_MARK "Tandai"
|
||||
IDS_COPY "Copy\tEnter"
|
||||
IDS_PASTE "Paste"
|
||||
IDS_SELECTALL "Pilih Semua"
|
||||
IDS_SCROLL "Gulung"
|
||||
IDS_FIND "Cari..."
|
||||
IDS_DEFAULTS "Standar"
|
||||
IDS_PROPERTIES "Properti"
|
||||
IDS_SCROLLHERE "Gulung ke Sini"
|
||||
IDS_SCROLLTOP "Gulung ke Atas"
|
||||
IDS_SCROLLBOTTOM "Gulung ke Bawah"
|
||||
IDS_SCROLLPAGE_UP "Halaman Naik"
|
||||
IDS_SCROLLPAGE_DOWN "Halaman Turun"
|
||||
IDS_SCROLLUP "Gulung Naik"
|
||||
IDS_SCROLLDOWN "Gulung Turun"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Client/Server Runtime subsystem
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: subsystems/win32/csrss/win32csr/lang/it-IT.rc
|
||||
* PURPOSE: Italian Translation of subsystems/win32/csrss/win32csr/lang/en-US.rc
|
||||
* PROGRAMMERS:
|
||||
* Copyright (C) 2007 Daniele Forsi (dforsi at gmail.com) Italian Translation
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Arresto del programma - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Arresto del programma... Attendere",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progresso",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Se si sceglie di terminare il programma immediatamente, si perderanno tutti i dati non salvati. Per terminare il programma ora, selezionare Termina ora.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "T&ermina ora",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Arresto del programma - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Annulla",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "T&ermina ora",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Il programma non risponde",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Per tornare a ReactOS e controllare lo stato del programma, selezionare Annulla",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Se si sceglie di terminare il programma immediatamente, si perderanno tutti i dati non salvati. Per terminare il programma ora, selezionare Termina ora.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Modifica"
|
||||
IDS_MARK "Seleziona"
|
||||
IDS_COPY "Copia\tInvio"
|
||||
IDS_PASTE "Incolla"
|
||||
IDS_SELECTALL "Seleziona tutto"
|
||||
IDS_SCROLL "Scorri"
|
||||
IDS_FIND "Trova..."
|
||||
IDS_DEFAULTS "Impostazioni predefinite"
|
||||
IDS_PROPERTIES "Proprietà"
|
||||
IDS_SCROLLHERE "Scorri qui"
|
||||
IDS_SCROLLTOP "Scorri in cima"
|
||||
IDS_SCROLLBOTTOM "Scorri in fondo"
|
||||
IDS_SCROLLPAGE_UP "Pagina sù"
|
||||
IDS_SCROLLPAGE_DOWN "Pagina giù"
|
||||
IDS_SCROLLUP "Scorri sù"
|
||||
IDS_SCROLLDOWN "Scorri giù"
|
||||
|
||||
IDS_COMMAND_PROMPT "Prompt dei commandi"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "プログラムの終了 - "
|
||||
FONT 9, "MS UI Gothic"
|
||||
BEGIN
|
||||
LTEXT "プログラムを終了しています... しばらくお待ちください",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "プログラムをすぐに終了させるよう選択した場合、保存されていないデータはすべて失われます。プログラムを終了するには[すぐに終了]をクリックしてください。",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "すぐに終了(&E)",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "プログラムの終了 - "
|
||||
FONT 9, "MS UI Gothic"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "キャンセル",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "すぐに終了(&E)",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "このプログラムは応答していません",IDC_STATIC,7,7,178,8
|
||||
LTEXT "ReactOS に戻ってプログラムの状態を確認するには[キャンセル]をクリックしてください",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "プログラムをすぐに終了させるよう選択した場合、保存されていないデータはすべて失われます。プログラムを直ちに終了するには[すぐに終了]をクリックしてください",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 9, "MS UI Gothic", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "編集"
|
||||
IDS_MARK "範囲指定"
|
||||
IDS_COPY "コピー\tEnter"
|
||||
IDS_PASTE "貼\り付け"
|
||||
IDS_SELECTALL "すべて選択"
|
||||
IDS_SCROLL "スクロール"
|
||||
IDS_FIND "検索..."
|
||||
IDS_DEFAULTS "規定値"
|
||||
IDS_PROPERTIES "プロパティ"
|
||||
IDS_SCROLLHERE "ここにスクロール"
|
||||
IDS_SCROLLTOP "一番上にスクロール"
|
||||
IDS_SCROLLBOTTOM "一番下にスクロール"
|
||||
IDS_SCROLLPAGE_UP "Page up"
|
||||
IDS_SCROLLPAGE_DOWN "Page down"
|
||||
IDS_SCROLLUP "上にスクロール"
|
||||
IDS_SCROLLDOWN "下にスクロール"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Avslutt program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Avslutt Program... Vennligst vent",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Hvis du velger å avslutte programmet øyeblikkelig, vil du miste alt data som ikke er lagret. For å avslutte programmet nå, Trykk på Avslutt nå.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Avslutt nå",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Avslutt program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Avbryt",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Avslutt nå",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Programmet svarer ikke",IDC_STATIC,7,7,178,8
|
||||
LTEXT "For å returnere til ReactOS for å sjekke statusen på programmet, trykk på avbryt",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Hvis du velger å avslutte programmet øyeblikkelig, vil du miste alt data som ikke er lagret. For å avslutte programmet nå, Trykk på Avslutt nå",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Rediger"
|
||||
IDS_MARK "Merk"
|
||||
IDS_COPY "Kopier\tEnter"
|
||||
IDS_PASTE "Lim inn"
|
||||
IDS_SELECTALL "Velg alt"
|
||||
IDS_SCROLL "Rull"
|
||||
IDS_FIND "Finn..."
|
||||
IDS_DEFAULTS "Standard"
|
||||
IDS_PROPERTIES "Egenskaper"
|
||||
IDS_SCROLLHERE "Rull her"
|
||||
IDS_SCROLLTOP "Rull til toppen"
|
||||
IDS_SCROLLBOTTOM "Rull knapp"
|
||||
IDS_SCROLLPAGE_UP "Side opp"
|
||||
IDS_SCROLLPAGE_DOWN "Side ned"
|
||||
IDS_SCROLLUP "Rull opp"
|
||||
IDS_SCROLLDOWN "Rull ned"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* translated by xrogers
|
||||
* [email protected]
|
||||
* https://sourceforge.net/projects/reactospl
|
||||
* translation update by Olaf Siejka (Caemyr), Apr 2011
|
||||
* UTF-8 conversion by Caemyr (May, 2011)
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Zakończ program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Trwa zamykanie programu... Proszę czekać",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Postęp",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Jeśli zdecydujesz się zamknąć program natychmiastowo, utracisz wszelkie niezapisane dane. Aby zakończyć program, wciśnij Zakończ teraz.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Zakończ teraz",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Zakończ program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Anuluj",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Zakończ teraz",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Wybrany program nie odpowiada",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Aby powrócić do ReactOS i sprawdzić status programu, kliknij Anuluj",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Jeśli zdecydujesz się zamknąć program natychmiastowo, utracisz wszelkie niezapisane dane. Aby zakończyć program, wciśnij Zakończ teraz.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Edytuj"
|
||||
IDS_MARK "Zaznacz"
|
||||
IDS_COPY "Kopiuj\tWejdź"
|
||||
IDS_PASTE "Wklej"
|
||||
IDS_SELECTALL "Zaznacz wszystko"
|
||||
IDS_SCROLL "Przewiń"
|
||||
IDS_FIND "Znajdź..."
|
||||
IDS_DEFAULTS "Ustawienia domyślne"
|
||||
IDS_PROPERTIES "Właściwości"
|
||||
IDS_SCROLLHERE "Przewiń tutaj"
|
||||
IDS_SCROLLTOP "Przewiń na początek"
|
||||
IDS_SCROLLBOTTOM "Przewiń na koniec"
|
||||
IDS_SCROLLPAGE_UP "Poprzednia strona"
|
||||
IDS_SCROLLPAGE_DOWN "Następna strona"
|
||||
IDS_SCROLLUP "Przewiń do góry"
|
||||
IDS_SCROLLDOWN "Przewiń na dół"
|
||||
|
||||
IDS_COMMAND_PROMPT "Wiersz polecenia"
|
||||
END
|
||||
@@ -0,0 +1,60 @@
|
||||
/* Translation and UTF-8 Conversion by mkbu95 <[email protected]> (May, 2012) */
|
||||
|
||||
LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Finalizar Programa - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Finalizando Programa... Por favor aguarde",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Se você finalizar o programa imediatamente, você irá perder qualquer alteração não salva. Para finalizar o programa agora, pressione Finalizar Agora.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Finalizar Agora",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Finalizar Programa - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Cancelar",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Finalizar Agora",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "O programa não está respondendo",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Parar retornar ao ReactOS e verificar o estado do programa, pressione Cancelar",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Se você finalizar o programa imediatamente, você irá perder qualquer alteração não salva. Para finalizar o programa agora, pressione Finalizar Agora",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Editar"
|
||||
IDS_MARK "Marcar"
|
||||
IDS_COPY "Copiar\tEnter"
|
||||
IDS_PASTE "Colar"
|
||||
IDS_SELECTALL "Selecionar Tudo"
|
||||
IDS_SCROLL "Rolar"
|
||||
IDS_FIND "Procurar..."
|
||||
IDS_DEFAULTS "Padrões"
|
||||
IDS_PROPERTIES "Propriedades"
|
||||
IDS_SCROLLHERE "Rolar aqui"
|
||||
IDS_SCROLLTOP "Rolar até o topo"
|
||||
IDS_SCROLLBOTTOM "Rolar até o fim"
|
||||
IDS_SCROLLPAGE_UP "Page up"
|
||||
IDS_SCROLLPAGE_DOWN "Page down"
|
||||
IDS_SCROLLUP "Scroll up"
|
||||
IDS_SCROLLDOWN "Scroll down"
|
||||
|
||||
IDS_COMMAND_PROMPT "Prompt de Comando"
|
||||
END
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* FILE: subsystems/win32/csrss/win32csr/lang/ro-RO.rc
|
||||
* ReactOS Project (http://www.reactos.org)
|
||||
* TRANSLATOR: Fulea Ștefan (PM on ReactOS Forum at fulea.stefan)
|
||||
* CHANGE LOG: 2011-10-16 initial translation
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Terminare execuție - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Terminare execuție… așteptați",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress", IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Dacă alegeți închiderea forțată, riscați pierderi de date. Pentru a forța închiderea, apăsați „Termină forțat”.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "Termină &forțat",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Terminare execuție - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "A&nulează", IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "Termină &forțat",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Acest program nu răspunde",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Pentru a vă întoarce în ReactOS și a verifica starea programului, apăsați „Anulează”",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Dacă alegeți închiderea imediată a programului, riscați pierderi de date. Pentru a forța închiderea, apăsați „Termină forțat”.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Editare"
|
||||
IDS_MARK "Marchează"
|
||||
IDS_COPY "Copiază\tEnter"
|
||||
IDS_PASTE "Lipește"
|
||||
IDS_SELECTALL "Selectează tot"
|
||||
IDS_SCROLL "Derulează"
|
||||
IDS_FIND "Găsire…"
|
||||
IDS_DEFAULTS "Implicite"
|
||||
IDS_PROPERTIES "Proprietăți"
|
||||
IDS_SCROLLHERE "Derulează aici"
|
||||
IDS_SCROLLTOP "Derulează la început"
|
||||
IDS_SCROLLBOTTOM "Derulează la sfârșit"
|
||||
IDS_SCROLLPAGE_UP "Pagina anterioară"
|
||||
IDS_SCROLLPAGE_DOWN "Pagina următoare"
|
||||
IDS_SCROLLUP "Derulează în sus"
|
||||
IDS_SCROLLDOWN "Derulează în jos"
|
||||
|
||||
IDS_COMMAND_PROMPT "Linie de comandă"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Завершение программы - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Завершение программы... Пажалуйста подождите",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Если вы завершите программу сейчас, то вы можете потерять несохраненные данные. Чтобы завешить программу сейчас нажмите ""Завершить""",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Завешить",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Завершение программы - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Отмена",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Завершить",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Эта программа не отвечает",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Для возврата в ReactOS и сохранения данных нажмите ""Отмена""",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Если вы завершите программу сейчас, то вы можете потерять несохраненные данные. Чтобы завешить программу сейчас нажмите ""Завершить""",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Изменить"
|
||||
IDS_MARK "Пометить"
|
||||
IDS_COPY "Копировать\tEnter"
|
||||
IDS_PASTE "Вставить"
|
||||
IDS_SELECTALL "Выделить все"
|
||||
IDS_SCROLL "Прокрутить"
|
||||
IDS_FIND "Искать..."
|
||||
IDS_DEFAULTS "Умолчания"
|
||||
IDS_PROPERTIES "Свойства"
|
||||
IDS_SCROLLHERE "Scroll Here"
|
||||
IDS_SCROLLTOP "Scroll Top"
|
||||
IDS_SCROLLBOTTOM "Прокрутить вниз"
|
||||
IDS_SCROLLPAGE_UP "Вверх страницы"
|
||||
IDS_SCROLLPAGE_DOWN "Вниз страницы"
|
||||
IDS_SCROLLUP "Прокрутить вверх"
|
||||
IDS_SCROLLDOWN "Scroll Down"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,63 @@
|
||||
/* TRANSLATOR: Mário Kaèmár /Mario Kacmar/ aka Kario ([email protected])
|
||||
* DATE OF TR: 29-05-2008
|
||||
* LastChange: 12-04-2011
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ukonèenie programu - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Ukonèujem program... Poèkajte, prosím.",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Ak zvolíte okamžité ukonèenie programu, stratíte všetky neuložené údaje. Ak chcete program ukonèi� okamžite, kliknite na tlaèidlo Ukonèi� ihneï.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Ukonèi� ihneï",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ukonèenie programu - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Zruši�",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Ukonèi� ihneï",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Tento program neodpovedá.",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Pre návrat do systému ReactOS a overenie stavu programu kliknite na tlaèidlo Zruši�.",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Ak zvolíte okamžité ukonèenie programu, stratíte všetky neuložené údaje. Ak chcete program ukonèi� okamžite, kliknite na tlaèidlo Ukonèi� ihneï.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Upravi�"
|
||||
IDS_MARK "Oznaèi�"
|
||||
IDS_COPY "Kopírova�\tEnter"
|
||||
IDS_PASTE "Vloži�"
|
||||
IDS_SELECTALL "Vybra� všetko"
|
||||
IDS_SCROLL "Rolova�"
|
||||
IDS_FIND "Nájs�..." //Find
|
||||
IDS_DEFAULTS "Predvolené" //Defaults
|
||||
IDS_PROPERTIES "Vlastnosti"
|
||||
IDS_SCROLLHERE "Rolova� sem"
|
||||
IDS_SCROLLTOP "K hornému okraju"
|
||||
IDS_SCROLLBOTTOM "K dolnému okraju"
|
||||
IDS_SCROLLPAGE_UP "O stránku vyššie"
|
||||
IDS_SCROLLPAGE_DOWN "O stránku nižšie"
|
||||
IDS_SCROLLUP "Rolova� nahor"
|
||||
IDS_SCROLLDOWN "Rolova� nadol"
|
||||
|
||||
IDS_COMMAND_PROMPT "Príkazový riadok"
|
||||
END
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* FILE: subsystems/win32/csrss/win32csr/lang/sv-SE.rc
|
||||
* PURPOSE: Swedish resource file
|
||||
* Translation: Jaix Bly
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "End Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Avsluta Program... Var vänlig vänta",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Om du väljer att avsluta programmet omedelbart kommer du att förlora all osparad data. För att avsluta programmet, klicka Avsluta nu.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Avsluta Nu",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Avsluta Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Avbryt",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Avsluta Nu",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Detta programmet svarar inte",IDC_STATIC,7,7,178,8
|
||||
LTEXT "För att återgå till ReactOS och undersöka programmets status klicka Avbryt",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "m du väljer att avsluta programmet omedelbart kommer du att förlora all osparad data. För att avsluta programmet, klicka Avsluta nu.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Redigera"
|
||||
IDS_MARK "Markera"
|
||||
IDS_COPY "Kopiera\tEnter"
|
||||
IDS_PASTE "Klistra in"
|
||||
IDS_SELECTALL "Markera Allt"
|
||||
IDS_SCROLL "Skrolla"
|
||||
IDS_FIND "Sök..."
|
||||
IDS_DEFAULTS "Ursprunglig"
|
||||
IDS_PROPERTIES "Egenskaper"
|
||||
IDS_SCROLLHERE "Skrolla hit"
|
||||
IDS_SCROLLTOP "Skrolla till topp"
|
||||
IDS_SCROLLBOTTOM "Skrolla till botten"
|
||||
IDS_SCROLLPAGE_UP "Sida upp"
|
||||
IDS_SCROLLPAGE_DOWN "Sida ner"
|
||||
IDS_SCROLLUP "Skrolla upp"
|
||||
IDS_SCROLLDOWN "Skrolla ner"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Turkish resources
|
||||
*
|
||||
* Copyright 2012 Arda Tanrikulu <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Programı Sonlandır - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Program Sonlandırılıyor... Lütfen bekleyin",IDC_STATIC,7,7,186,11
|
||||
CONTROL "İşlem",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Programı hemen kapatmayı seçerseniz, kaydedilmemiş veriyi kaybedersiniz. Programdan şimdi çıkmak için Şimdi Sonlandır'ı tıklatın.",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Şimdi Sonlandır",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "End Program - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "İptal",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "Şimdi Sonlandır",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Bu program yanıt vermiyor.",IDC_STATIC,7,7,178,8
|
||||
LTEXT "ReactOS'a dönmek ve programın durumunu denetlemek için İptal'i tıklatın.",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Programı hemen kapatmayı seçerseniz, kaydedilmemiş veriyi kaybedersiniz. Programdan şimdi çıkmak için Şimdi Sonlandır'ı tıklatın.",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Düzenle"
|
||||
IDS_MARK "İşaretle"
|
||||
IDS_COPY "Kopyala\tEnter"
|
||||
IDS_PASTE "Yapıştır"
|
||||
IDS_SELECTALL "Tümünü Seç"
|
||||
IDS_SCROLL "Yuvarla"
|
||||
IDS_FIND "Bul..."
|
||||
IDS_DEFAULTS "Varsayılanlar"
|
||||
IDS_PROPERTIES "Özellikler"
|
||||
IDS_SCROLLHERE "Buraya yuvarla"
|
||||
IDS_SCROLLTOP "Üste yuvarla"
|
||||
IDS_SCROLLBOTTOM "Alta yuvarla"
|
||||
IDS_SCROLLPAGE_UP "Sayfa yukarı"
|
||||
IDS_SCROLLPAGE_DOWN "Sayfa aşağı"
|
||||
IDS_SCROLLUP "Yukarı yuvarla"
|
||||
IDS_SCROLLDOWN "Aşağı yuvarla"
|
||||
|
||||
IDS_COMMAND_PROMPT "Komut İstemi"
|
||||
END
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS subsystem
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: subsystems/win32/csrss/win32csr/lang/uk-UA.rc
|
||||
* PURPOSE: Ukraianian resource file
|
||||
* TRANSLATOR: Artem Reznikov
|
||||
*/
|
||||
|
||||
LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Завершення програми - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "Завершення програми... Зачекайте",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Прогрес",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "Якщо завершити програму негайно, то можна втратити всі незбережені дані. Щоб завершити програму зараз, натисніть 'Завершити зараз'",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "&Завершити зараз",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Завершення програми - "
|
||||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Скасувати",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "&Завершити зараз",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "Ця програма не відповідає",IDC_STATIC,7,7,178,8
|
||||
LTEXT "Щоб повернутися у ReactOS і перевірити стан програми, натисніть 'Скасувати'",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "Якщо завершити програму негайно, то можна втратити всі незбережені дані. Щоб завершити програму зараз, натисніть 'Завершити зараз'",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "Редагувати"
|
||||
IDS_MARK "Виділити"
|
||||
IDS_COPY "Копіювати\tEnter"
|
||||
IDS_PASTE "Вставити"
|
||||
IDS_SELECTALL "Виділити все"
|
||||
IDS_SCROLL "Прокрутити"
|
||||
IDS_FIND "Знайти..."
|
||||
IDS_DEFAULTS "Замовчування"
|
||||
IDS_PROPERTIES "Властивості"
|
||||
IDS_SCROLLHERE "Прокрутити сюди"
|
||||
IDS_SCROLLTOP "Прокрутити на початок"
|
||||
IDS_SCROLLBOTTOM "Прокрутити на кінець"
|
||||
IDS_SCROLLPAGE_UP "Попередня сотрінка"
|
||||
IDS_SCROLLPAGE_DOWN "Наступна сторінка"
|
||||
IDS_SCROLLUP "Прокрутити догори"
|
||||
IDS_SCROLLDOWN "Прокрутити донизу"
|
||||
|
||||
IDS_COMMAND_PROMPT "Командний рядок"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "终止程序 - "
|
||||
FONT 9, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "正在终止程序... 请等待",IDC_STATIC,7,7,186,11
|
||||
CONTROL "进程",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "如果您选择立即终止程序,您将失去所有未保存的数据。若要立即结束程序,单击“立即终止”。",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "立即终止(&E)",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "终止程序 - "
|
||||
FONT 9, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "取消",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "立即终止(&E)",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "此程序并未响应",IDC_STATIC,7,7,178,8
|
||||
LTEXT "若要返回至 ReactOS 并检查该程序的状态,请点击“取消”。",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "如果您选择立即终止程序,您将失去所有未保存的数据。若要立即结束程序,单击“立即终止”。",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 9, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "编辑"
|
||||
IDS_MARK "标记"
|
||||
IDS_COPY "复制\tEnter"
|
||||
IDS_PASTE "黏贴"
|
||||
IDS_SELECTALL "全部选择"
|
||||
IDS_SCROLL "滚动"
|
||||
IDS_FIND "查找..."
|
||||
IDS_DEFAULTS "默认"
|
||||
IDS_PROPERTIES "属性"
|
||||
IDS_SCROLLHERE "滚动到此"
|
||||
IDS_SCROLLTOP "滚动至顶端"
|
||||
IDS_SCROLLBOTTOM "滚动至末端"
|
||||
IDS_SCROLLPAGE_UP "上一页"
|
||||
IDS_SCROLLPAGE_DOWN "下一页"
|
||||
IDS_SCROLLUP "向上滚动"
|
||||
IDS_SCROLLDOWN "向下滚动"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,58 @@
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
|
||||
|
||||
IDD_END_NOW DIALOGEX DISCARDABLE 0, 0, 200, 95
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "結束程式"
|
||||
FONT 9, "MS Shell Dlg"
|
||||
BEGIN
|
||||
LTEXT "正在結束程式... 請稍等",IDC_STATIC,7,7,186,11
|
||||
CONTROL "Progress",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
|
||||
7,20,186,13
|
||||
LTEXT "如果您選擇立即結束程式,您將失去所有未儲存的資料。若要立即結束程式,請按下“立即結束”。",
|
||||
IDC_STATIC,7,40,186,26
|
||||
DEFPUSHBUTTON "立即結束(&E)",IDC_END_NOW,150,71,43,17
|
||||
END
|
||||
|
||||
IDD_NOT_RESPONDING DIALOGEX DISCARDABLE 0, 0, 192, 122
|
||||
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "結束程式 - "
|
||||
FONT 9, "MS Shell Dlg"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "取消",IDCANCEL,142,98,43,17
|
||||
PUSHBUTTON "立即結束(&E) ",IDC_END_NOW,78,98,43,17
|
||||
LTEXT "此程式並未響應",IDC_STATIC,7,7,178,8
|
||||
LTEXT "若要返回至 ReactOS 並檢視程式的狀態,請按下“取消”",
|
||||
IDC_STATIC,7,26,178,16
|
||||
LTEXT "如果您選擇立即結束程式,您將失去所有未儲存的資料。若要立即結束程式,請按下“立即結束”。",
|
||||
IDC_STATIC,7,53,178,26
|
||||
END
|
||||
|
||||
IDD_SWITCH_APP DIALOGEX 90, 90, 265, 170
|
||||
STYLE DS_SYSMODAL | DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE
|
||||
EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
|
||||
FONT 9, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "",IDC_STATIC_CUR_APP,39,139,204,16,SS_SUNKEN,WS_EX_STATICEDGE
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_EDIT "編輯"
|
||||
IDS_MARK "標記"
|
||||
IDS_COPY "複製\tEnter"
|
||||
IDS_PASTE "黏貼"
|
||||
IDS_SELECTALL "全部選擇"
|
||||
IDS_SCROLL "滾動"
|
||||
IDS_FIND "尋找..."
|
||||
IDS_DEFAULTS "預設"
|
||||
IDS_PROPERTIES "屬性"
|
||||
IDS_SCROLLHERE "滾動到此 "
|
||||
IDS_SCROLLTOP "滾動到頂置"
|
||||
IDS_SCROLLBOTTOM "滾動到末端"
|
||||
IDS_SCROLLPAGE_UP "上一頁"
|
||||
IDS_SCROLLPAGE_DOWN "下一頁"
|
||||
IDS_SCROLLUP "向上滾動"
|
||||
IDS_SCROLLDOWN "向下滾動"
|
||||
|
||||
IDS_COMMAND_PROMPT "Command Prompt"
|
||||
END
|
||||
@@ -0,0 +1,597 @@
|
||||
/*
|
||||
* PROJECT: ReactOS CSRSS
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: subsystems/win32/csrss/win32csr/lineinput.c
|
||||
* PURPOSE: Console line input functions
|
||||
* PROGRAMMERS: Jeffrey Morlan
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct tagHISTORY_BUFFER
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
WORD Position;
|
||||
WORD MaxEntries;
|
||||
WORD NumEntries;
|
||||
PUNICODE_STRING Entries;
|
||||
UNICODE_STRING ExeName;
|
||||
} HISTORY_BUFFER, *PHISTORY_BUFFER;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static PHISTORY_BUFFER
|
||||
HistoryCurrentBuffer(PCSRSS_CONSOLE Console)
|
||||
{
|
||||
/* TODO: use actual EXE name sent from process that called ReadConsole */
|
||||
UNICODE_STRING ExeName = { 14, 14, L"cmd.exe" };
|
||||
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
|
||||
PHISTORY_BUFFER Hist;
|
||||
|
||||
for (; Entry != &Console->HistoryBuffers; Entry = Entry->Flink)
|
||||
{
|
||||
Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
||||
if (RtlEqualUnicodeString(&ExeName, &Hist->ExeName, FALSE))
|
||||
return Hist;
|
||||
}
|
||||
|
||||
/* Couldn't find the buffer, create a new one */
|
||||
Hist = HeapAlloc(Win32CsrApiHeap, 0, sizeof(HISTORY_BUFFER) + ExeName.Length);
|
||||
if (!Hist)
|
||||
return NULL;
|
||||
Hist->MaxEntries = Console->HistoryBufferSize;
|
||||
Hist->NumEntries = 0;
|
||||
Hist->Entries = HeapAlloc(Win32CsrApiHeap, 0, Hist->MaxEntries * sizeof(UNICODE_STRING));
|
||||
if (!Hist->Entries)
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap, 0, Hist);
|
||||
return NULL;
|
||||
}
|
||||
Hist->ExeName.Length = Hist->ExeName.MaximumLength = ExeName.Length;
|
||||
Hist->ExeName.Buffer = (PWCHAR)(Hist + 1);
|
||||
memcpy(Hist->ExeName.Buffer, ExeName.Buffer, ExeName.Length);
|
||||
InsertHeadList(&Console->HistoryBuffers, &Hist->ListEntry);
|
||||
return Hist;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HistoryAddEntry(PCSRSS_CONSOLE Console)
|
||||
{
|
||||
UNICODE_STRING NewEntry;
|
||||
PHISTORY_BUFFER Hist;
|
||||
INT i;
|
||||
|
||||
NewEntry.Length = NewEntry.MaximumLength = Console->LineSize * sizeof(WCHAR);
|
||||
NewEntry.Buffer = Console->LineBuffer;
|
||||
|
||||
if (!(Hist = HistoryCurrentBuffer(Console)))
|
||||
return;
|
||||
|
||||
/* Don't add blank or duplicate entries */
|
||||
if (NewEntry.Length == 0 || Hist->MaxEntries == 0 ||
|
||||
(Hist->NumEntries > 0 &&
|
||||
RtlEqualUnicodeString(&Hist->Entries[Hist->NumEntries - 1], &NewEntry, FALSE)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Console->HistoryNoDup)
|
||||
{
|
||||
/* Check if this line has been entered before */
|
||||
for (i = Hist->NumEntries - 1; i >= 0; i--)
|
||||
{
|
||||
if (RtlEqualUnicodeString(&Hist->Entries[i], &NewEntry, FALSE))
|
||||
{
|
||||
/* Just rotate the list to bring this entry to the end */
|
||||
NewEntry = Hist->Entries[i];
|
||||
memmove(&Hist->Entries[i], &Hist->Entries[i + 1],
|
||||
(Hist->NumEntries - (i + 1)) * sizeof(UNICODE_STRING));
|
||||
Hist->Entries[Hist->NumEntries - 1] = NewEntry;
|
||||
Hist->Position = Hist->NumEntries - 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Hist->NumEntries == Hist->MaxEntries)
|
||||
{
|
||||
/* List is full, remove oldest entry */
|
||||
RtlFreeUnicodeString(&Hist->Entries[0]);
|
||||
memmove(&Hist->Entries[0], &Hist->Entries[1],
|
||||
--Hist->NumEntries * sizeof(UNICODE_STRING));
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(RtlDuplicateUnicodeString(0, &NewEntry, &Hist->Entries[Hist->NumEntries])))
|
||||
Hist->NumEntries++;
|
||||
Hist->Position = Hist->NumEntries - 1;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HistoryGetCurrentEntry(PCSRSS_CONSOLE Console, PUNICODE_STRING Entry)
|
||||
{
|
||||
PHISTORY_BUFFER Hist;
|
||||
if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0)
|
||||
Entry->Length = 0;
|
||||
else
|
||||
*Entry = Hist->Entries[Hist->Position];
|
||||
}
|
||||
|
||||
static PHISTORY_BUFFER
|
||||
HistoryFindBuffer(PCSRSS_CONSOLE Console, PUNICODE_STRING ExeName)
|
||||
{
|
||||
PLIST_ENTRY Entry = Console->HistoryBuffers.Flink;
|
||||
while (Entry != &Console->HistoryBuffers)
|
||||
{
|
||||
/* For the history APIs, the caller is allowed to give only part of the name */
|
||||
PHISTORY_BUFFER Hist = CONTAINING_RECORD(Entry, HISTORY_BUFFER, ListEntry);
|
||||
if (RtlPrefixUnicodeString(ExeName, &Hist->ExeName, TRUE))
|
||||
return Hist;
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
|
||||
{
|
||||
if (!Hist)
|
||||
return;
|
||||
while (Hist->NumEntries != 0)
|
||||
RtlFreeUnicodeString(&Hist->Entries[--Hist->NumEntries]);
|
||||
HeapFree(Win32CsrApiHeap, 0, Hist->Entries);
|
||||
RemoveEntryList(&Hist->ListEntry);
|
||||
HeapFree(Win32CsrApiHeap, 0, Hist);
|
||||
}
|
||||
|
||||
CSR_API(CsrGetCommandHistoryLength)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
PHISTORY_BUFFER Hist;
|
||||
ULONG Length = 0;
|
||||
INT i;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData,
|
||||
Request->Data.GetCommandHistoryLength.ExeName.Buffer,
|
||||
Request->Data.GetCommandHistoryLength.ExeName.Length, 1))
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &Request->Data.GetCommandHistory.ExeName);
|
||||
if (Hist)
|
||||
{
|
||||
for (i = 0; i < Hist->NumEntries; i++)
|
||||
Length += Hist->Entries[i].Length + sizeof(WCHAR);
|
||||
}
|
||||
Request->Data.GetCommandHistoryLength.Length = Length;
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetCommandHistory)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
PHISTORY_BUFFER Hist;
|
||||
PBYTE Buffer = (PBYTE)Request->Data.GetCommandHistory.History;
|
||||
ULONG BufferSize = Request->Data.GetCommandHistory.Length;
|
||||
INT i;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData, Buffer, BufferSize, 1) ||
|
||||
!Win32CsrValidateBuffer(ProcessData,
|
||||
Request->Data.GetCommandHistory.ExeName.Buffer,
|
||||
Request->Data.GetCommandHistory.ExeName.Length, 1))
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &Request->Data.GetCommandHistory.ExeName);
|
||||
if (Hist)
|
||||
{
|
||||
for (i = 0; i < Hist->NumEntries; i++)
|
||||
{
|
||||
if (BufferSize < (Hist->Entries[i].Length + sizeof(WCHAR)))
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
memcpy(Buffer, Hist->Entries[i].Buffer, Hist->Entries[i].Length);
|
||||
Buffer += Hist->Entries[i].Length;
|
||||
*(PWCHAR)Buffer = L'\0';
|
||||
Buffer += sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
Request->Data.GetCommandHistory.Length = Buffer - (PBYTE)Request->Data.GetCommandHistory.History;
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrExpungeCommandHistory)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
PHISTORY_BUFFER Hist;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData,
|
||||
Request->Data.ExpungeCommandHistory.ExeName.Buffer,
|
||||
Request->Data.ExpungeCommandHistory.ExeName.Length, 1))
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &Request->Data.ExpungeCommandHistory.ExeName);
|
||||
HistoryDeleteBuffer(Hist);
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetHistoryNumberCommands)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
PHISTORY_BUFFER Hist;
|
||||
NTSTATUS Status;
|
||||
WORD MaxEntries = Request->Data.SetHistoryNumberCommands.NumCommands;
|
||||
PUNICODE_STRING OldEntryList, NewEntryList;
|
||||
|
||||
if (!Win32CsrValidateBuffer(ProcessData,
|
||||
Request->Data.SetHistoryNumberCommands.ExeName.Buffer,
|
||||
Request->Data.SetHistoryNumberCommands.ExeName.Length, 1))
|
||||
{
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Hist = HistoryFindBuffer(Console, &Request->Data.SetHistoryNumberCommands.ExeName);
|
||||
if (Hist)
|
||||
{
|
||||
OldEntryList = Hist->Entries;
|
||||
NewEntryList = HeapAlloc(Win32CsrApiHeap, 0,
|
||||
MaxEntries * sizeof(UNICODE_STRING));
|
||||
if (!NewEntryList)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If necessary, shrink by removing oldest entries */
|
||||
for (; Hist->NumEntries > MaxEntries; Hist->NumEntries--)
|
||||
{
|
||||
RtlFreeUnicodeString(Hist->Entries++);
|
||||
Hist->Position += (Hist->Position == 0);
|
||||
}
|
||||
|
||||
Hist->MaxEntries = MaxEntries;
|
||||
Hist->Entries = memcpy(NewEntryList, Hist->Entries,
|
||||
Hist->NumEntries * sizeof(UNICODE_STRING));
|
||||
HeapFree(Win32CsrApiHeap, 0, OldEntryList);
|
||||
}
|
||||
}
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetHistoryInfo)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Request->Data.SetHistoryInfo.HistoryBufferSize = Console->HistoryBufferSize;
|
||||
Request->Data.SetHistoryInfo.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
|
||||
Request->Data.SetHistoryInfo.dwFlags = Console->HistoryNoDup;
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetHistoryInfo)
|
||||
{
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Console->HistoryBufferSize = (WORD)Request->Data.SetHistoryInfo.HistoryBufferSize;
|
||||
Console->NumberOfHistoryBuffers = (WORD)Request->Data.SetHistoryInfo.NumberOfHistoryBuffers;
|
||||
Console->HistoryNoDup = Request->Data.SetHistoryInfo.dwFlags & HISTORY_NO_DUP_FLAG;
|
||||
ConioUnlockConsole(Console);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID
|
||||
LineInputSetPos(PCSRSS_CONSOLE Console, UINT Pos)
|
||||
{
|
||||
if (Pos != Console->LinePos && Console->Mode & ENABLE_ECHO_INPUT)
|
||||
{
|
||||
PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
|
||||
UINT OldCursorX = Buffer->CurrentX;
|
||||
UINT OldCursorY = Buffer->CurrentY;
|
||||
INT XY = OldCursorY * Buffer->MaxX + OldCursorX;
|
||||
|
||||
XY += (Pos - Console->LinePos);
|
||||
if (XY < 0)
|
||||
XY = 0;
|
||||
else if (XY >= Buffer->MaxY * Buffer->MaxX)
|
||||
XY = Buffer->MaxY * Buffer->MaxX - 1;
|
||||
|
||||
Buffer->CurrentX = XY % Buffer->MaxX;
|
||||
Buffer->CurrentY = XY / Buffer->MaxX;
|
||||
ConioSetScreenInfo(Console, Buffer, OldCursorX, OldCursorY);
|
||||
}
|
||||
|
||||
Console->LinePos = Pos;
|
||||
}
|
||||
|
||||
static VOID
|
||||
LineInputEdit(PCSRSS_CONSOLE Console, UINT NumToDelete, UINT NumToInsert, WCHAR *Insertion)
|
||||
{
|
||||
UINT Pos = Console->LinePos;
|
||||
UINT NewSize = Console->LineSize - NumToDelete + NumToInsert;
|
||||
INT i;
|
||||
|
||||
/* Make sure there's always enough room for ending \r\n */
|
||||
if (NewSize + 2 > Console->LineMaxSize)
|
||||
return;
|
||||
|
||||
memmove(&Console->LineBuffer[Pos + NumToInsert],
|
||||
&Console->LineBuffer[Pos + NumToDelete],
|
||||
(Console->LineSize - (Pos + NumToDelete)) * sizeof(WCHAR));
|
||||
memcpy(&Console->LineBuffer[Pos], Insertion, NumToInsert * sizeof(WCHAR));
|
||||
|
||||
if (Console->Mode & ENABLE_ECHO_INPUT)
|
||||
{
|
||||
for (i = Pos; i < NewSize; i++)
|
||||
{
|
||||
CHAR AsciiChar;
|
||||
WideCharToMultiByte(Console->OutputCodePage, 0,
|
||||
&Console->LineBuffer[i], 1,
|
||||
&AsciiChar, 1, NULL, NULL);
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer, &AsciiChar, 1, TRUE);
|
||||
}
|
||||
for (; i < Console->LineSize; i++)
|
||||
{
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer, " ", 1, TRUE);
|
||||
}
|
||||
Console->LinePos = i;
|
||||
}
|
||||
|
||||
Console->LineSize = NewSize;
|
||||
LineInputSetPos(Console, Pos + NumToInsert);
|
||||
}
|
||||
|
||||
static VOID
|
||||
LineInputRecallHistory(PCSRSS_CONSOLE Console, INT Offset)
|
||||
{
|
||||
PHISTORY_BUFFER Hist;
|
||||
|
||||
if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0)
|
||||
return;
|
||||
|
||||
Offset += Hist->Position;
|
||||
Offset = max(Offset, 0);
|
||||
Offset = min(Offset, Hist->NumEntries - 1);
|
||||
Hist->Position = Offset;
|
||||
|
||||
LineInputSetPos(Console, 0);
|
||||
LineInputEdit(Console, Console->LineSize,
|
||||
Hist->Entries[Offset].Length / sizeof(WCHAR),
|
||||
Hist->Entries[Offset].Buffer);
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
LineInputKeyDown(PCSRSS_CONSOLE Console, KEY_EVENT_RECORD *KeyEvent)
|
||||
{
|
||||
UINT Pos = Console->LinePos;
|
||||
PHISTORY_BUFFER Hist;
|
||||
UNICODE_STRING Entry;
|
||||
INT HistPos;
|
||||
|
||||
switch (KeyEvent->wVirtualKeyCode)
|
||||
{
|
||||
case VK_ESCAPE:
|
||||
/* Clear entire line */
|
||||
LineInputSetPos(Console, 0);
|
||||
LineInputEdit(Console, Console->LineSize, 0, NULL);
|
||||
return;
|
||||
case VK_HOME:
|
||||
/* Move to start of line. With ctrl, erase everything left of cursor */
|
||||
LineInputSetPos(Console, 0);
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
LineInputEdit(Console, Pos, 0, NULL);
|
||||
return;
|
||||
case VK_END:
|
||||
/* Move to end of line. With ctrl, erase everything right of cursor */
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
LineInputEdit(Console, Console->LineSize - Pos, 0, NULL);
|
||||
else
|
||||
LineInputSetPos(Console, Console->LineSize);
|
||||
return;
|
||||
case VK_LEFT:
|
||||
/* Move left. With ctrl, move to beginning of previous word */
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
{
|
||||
while (Pos > 0 && Console->LineBuffer[Pos - 1] == L' ') Pos--;
|
||||
while (Pos > 0 && Console->LineBuffer[Pos - 1] != L' ') Pos--;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pos -= (Pos > 0);
|
||||
}
|
||||
LineInputSetPos(Console, Pos);
|
||||
return;
|
||||
case VK_RIGHT:
|
||||
case VK_F1:
|
||||
/* Move right. With ctrl, move to beginning of next word */
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
||||
{
|
||||
while (Pos < Console->LineSize && Console->LineBuffer[Pos] != L' ') Pos++;
|
||||
while (Pos < Console->LineSize && Console->LineBuffer[Pos] == L' ') Pos++;
|
||||
LineInputSetPos(Console, Pos);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Recall one character (but don't overwrite current line) */
|
||||
HistoryGetCurrentEntry(Console, &Entry);
|
||||
if (Pos < Console->LineSize)
|
||||
LineInputSetPos(Console, Pos + 1);
|
||||
else if (Pos * sizeof(WCHAR) < Entry.Length)
|
||||
LineInputEdit(Console, 0, 1, &Entry.Buffer[Pos]);
|
||||
}
|
||||
return;
|
||||
case VK_INSERT:
|
||||
/* Toggle between insert and overstrike */
|
||||
Console->LineInsertToggle = !Console->LineInsertToggle;
|
||||
ConioSetCursorInfo(Console, Console->ActiveBuffer);
|
||||
return;
|
||||
case VK_DELETE:
|
||||
/* Remove character to right of cursor */
|
||||
if (Pos != Console->LineSize)
|
||||
LineInputEdit(Console, 1, 0, NULL);
|
||||
return;
|
||||
case VK_PRIOR:
|
||||
/* Recall first history entry */
|
||||
LineInputRecallHistory(Console, -((WORD)-1));
|
||||
return;
|
||||
case VK_NEXT:
|
||||
/* Recall last history entry */
|
||||
LineInputRecallHistory(Console, +((WORD)-1));
|
||||
return;
|
||||
case VK_UP:
|
||||
case VK_F5:
|
||||
/* Recall previous history entry. On first time, actually recall the
|
||||
* current (usually last) entry; on subsequent times go back. */
|
||||
LineInputRecallHistory(Console, Console->LineUpPressed ? -1 : 0);
|
||||
Console->LineUpPressed = TRUE;
|
||||
return;
|
||||
case VK_DOWN:
|
||||
/* Recall next history entry */
|
||||
LineInputRecallHistory(Console, +1);
|
||||
return;
|
||||
case VK_F3:
|
||||
/* Recall remainder of current history entry */
|
||||
HistoryGetCurrentEntry(Console, &Entry);
|
||||
if (Pos * sizeof(WCHAR) < Entry.Length)
|
||||
{
|
||||
UINT InsertSize = (Entry.Length / sizeof(WCHAR) - Pos);
|
||||
UINT DeleteSize = min(Console->LineSize - Pos, InsertSize);
|
||||
LineInputEdit(Console, DeleteSize, InsertSize, &Entry.Buffer[Pos]);
|
||||
}
|
||||
return;
|
||||
case VK_F6:
|
||||
/* Insert a ^Z character */
|
||||
KeyEvent->uChar.UnicodeChar = 26;
|
||||
break;
|
||||
case VK_F7:
|
||||
if (KeyEvent->dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
||||
HistoryDeleteBuffer(HistoryCurrentBuffer(Console));
|
||||
return;
|
||||
case VK_F8:
|
||||
/* Search for history entries starting with input. */
|
||||
if (!(Hist = HistoryCurrentBuffer(Console)) || Hist->NumEntries == 0)
|
||||
return;
|
||||
|
||||
/* Like Up/F5, on first time start from current (usually last) entry,
|
||||
* but on subsequent times start at previous entry. */
|
||||
if (Console->LineUpPressed)
|
||||
Hist->Position = (Hist->Position ? Hist->Position : Hist->NumEntries) - 1;
|
||||
Console->LineUpPressed = TRUE;
|
||||
|
||||
Entry.Length = Console->LinePos * sizeof(WCHAR);
|
||||
Entry.Buffer = Console->LineBuffer;
|
||||
|
||||
/* Keep going backwards, even wrapping around to the end,
|
||||
* until we get back to starting point */
|
||||
HistPos = Hist->Position;
|
||||
do
|
||||
{
|
||||
if (RtlPrefixUnicodeString(&Entry, &Hist->Entries[HistPos], FALSE))
|
||||
{
|
||||
Hist->Position = HistPos;
|
||||
LineInputEdit(Console, Console->LineSize - Pos,
|
||||
Hist->Entries[HistPos].Length / sizeof(WCHAR) - Pos,
|
||||
&Hist->Entries[HistPos].Buffer[Pos]);
|
||||
/* Cursor stays where it was */
|
||||
LineInputSetPos(Console, Pos);
|
||||
return;
|
||||
}
|
||||
if (--HistPos < 0) HistPos += Hist->NumEntries;
|
||||
} while (HistPos != Hist->Position);
|
||||
return;
|
||||
}
|
||||
|
||||
if (KeyEvent->uChar.UnicodeChar == L'\b' && Console->Mode & ENABLE_PROCESSED_INPUT)
|
||||
{
|
||||
/* backspace handling - if processed input enabled then we handle it here
|
||||
* otherwise we treat it like a normal char. */
|
||||
if (Pos > 0)
|
||||
{
|
||||
LineInputSetPos(Console, Pos - 1);
|
||||
LineInputEdit(Console, 1, 0, NULL);
|
||||
}
|
||||
}
|
||||
else if (KeyEvent->uChar.UnicodeChar == L'\r')
|
||||
{
|
||||
HistoryAddEntry(Console);
|
||||
|
||||
/* TODO: Expand aliases */
|
||||
|
||||
LineInputSetPos(Console, Console->LineSize);
|
||||
Console->LineBuffer[Console->LineSize++] = L'\r';
|
||||
if (Console->Mode & ENABLE_ECHO_INPUT)
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer, "\r", 1, TRUE);
|
||||
|
||||
/* Add \n if processed input. There should usually be room for it,
|
||||
* but an exception to the rule exists: the buffer could have been
|
||||
* pre-filled with LineMaxSize - 1 characters. */
|
||||
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
|
||||
Console->LineSize < Console->LineMaxSize)
|
||||
{
|
||||
Console->LineBuffer[Console->LineSize++] = L'\n';
|
||||
if (Console->Mode & ENABLE_ECHO_INPUT)
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer, "\n", 1, TRUE);
|
||||
}
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
else if (KeyEvent->uChar.UnicodeChar != L'\0')
|
||||
{
|
||||
if (KeyEvent->uChar.UnicodeChar < 0x20 &&
|
||||
Console->LineWakeupMask & (1 << KeyEvent->uChar.UnicodeChar))
|
||||
{
|
||||
/* Control key client wants to handle itself (e.g. for tab completion) */
|
||||
Console->LineBuffer[Console->LineSize++] = L' ';
|
||||
Console->LineBuffer[Console->LinePos] = KeyEvent->uChar.UnicodeChar;
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal character */
|
||||
BOOL Overstrike = Console->LineInsertToggle && Console->LinePos != Console->LineSize;
|
||||
LineInputEdit(Console, Overstrike, 1, &KeyEvent->uChar.UnicodeChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 231 KiB |
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Win32 subsystem
|
||||
* FILE: subsys/csrss/win32csr/resource.h
|
||||
* PURPOSE: Resource #defines
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IDD_END_NOW 10
|
||||
#define IDD_NOT_RESPONDING 11
|
||||
#define IDD_SWITCH_APP 12
|
||||
|
||||
#define IDC_STATIC -1
|
||||
#define IDC_PROGRESS 101
|
||||
#define IDC_END_NOW 102
|
||||
#define IDC_STATIC_CUR_APP 103
|
||||
|
||||
|
||||
#define ID_SYSTEM_EDIT_MARK 1001
|
||||
#define ID_SYSTEM_EDIT_COPY 1002
|
||||
#define ID_SYSTEM_EDIT_PASTE 1003
|
||||
#define ID_SYSTEM_EDIT_SELECTALL 1004
|
||||
#define ID_SYSTEM_EDIT_SCROLL 1005
|
||||
#define ID_SYSTEM_EDIT_FIND 1006
|
||||
#define ID_SYSTEM_DEFAULTS 1007
|
||||
#define ID_SYSTEM_PROPERTIES 1008
|
||||
|
||||
#define NCPOPUP_MENU 103
|
||||
|
||||
#define IDS_EDIT 204
|
||||
#define IDS_MARK 205
|
||||
#define IDS_COPY 206
|
||||
#define IDS_PASTE 207
|
||||
#define IDS_SELECTALL 208
|
||||
#define IDS_SCROLL 209
|
||||
#define IDS_FIND 210
|
||||
#define IDS_DEFAULTS 211
|
||||
#define IDS_PROPERTIES 212
|
||||
|
||||
//scrollbar resource ids
|
||||
#define IDS_SCROLLHERE 304
|
||||
#define IDS_SCROLLTOP 305
|
||||
#define IDS_SCROLLBOTTOM 306
|
||||
#define IDS_SCROLLPAGE_UP 307
|
||||
#define IDS_SCROLLPAGE_DOWN 308
|
||||
#define IDS_SCROLLUP 309
|
||||
#define IDS_SCROLLDOWN 310
|
||||
|
||||
#define IDS_COMMAND_PROMPT 500
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,73 @@
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
|
||||
1 ICON DISCARDABLE res/terminal.ico
|
||||
|
||||
#ifdef LANGUAGE_BG_BG
|
||||
#include "lang/bg-BG.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_CS_CZ
|
||||
#include "lang/cs-CZ.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_DE_DE
|
||||
#include "lang/de-DE.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_EL_GR
|
||||
#include "lang/el-GR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_EN_US
|
||||
#include "lang/en-US.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ES_ES
|
||||
#include "lang/es-ES.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_FR_FR
|
||||
#include "lang/fr-FR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ID_ID
|
||||
#include "lang/id-ID.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_IT_IT
|
||||
#include "lang/it-IT.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_JA_JP
|
||||
#include "lang/ja-JP.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_NB_NO
|
||||
#include "lang/no-NO.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_SK_SK
|
||||
#include "lang/sk-SK.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_SV_SE
|
||||
#include "lang/sv-SE.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ZH_CN
|
||||
#include "lang/zh-CN.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_ZH_TW
|
||||
#include "lang/zh-TW.rc"
|
||||
#endif
|
||||
|
||||
// UTF-8
|
||||
#pragma code_page(65001)
|
||||
#ifdef LANGUAGE_HE_IL
|
||||
#include "lang/he-IL.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_PL_PL
|
||||
#include "lang/pl-PL.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_PT_BR
|
||||
#include "lang/pt-BR.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_RO_RO
|
||||
#include "lang/ro-RO.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_RU_RU
|
||||
#include "lang/ru-RU.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_UK_UA
|
||||
#include "lang/uk-UA.rc"
|
||||
#endif
|
||||
#ifdef LANGUAGE_TR_TR
|
||||
#include "lang/tr-TR.rc"
|
||||
#endif
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/tuiconsole.c
|
||||
* PURPOSE: Implementation of text-mode consoles
|
||||
*/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
CRITICAL_SECTION ActiveConsoleLock;
|
||||
static COORD PhysicalConsoleSize;
|
||||
static HANDLE ConsoleDeviceHandle;
|
||||
static PCSRSS_CONSOLE ActiveConsole;
|
||||
|
||||
static BOOL ConsInitialized = FALSE;
|
||||
|
||||
static LRESULT CALLBACK
|
||||
TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (msg == WM_ACTIVATE)
|
||||
{
|
||||
if (LOWORD(wParam) != WA_INACTIVE)
|
||||
{
|
||||
SetFocus(hWnd);
|
||||
ConioDrawConsole(ActiveConsole);
|
||||
}
|
||||
}
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static BOOL FASTCALL
|
||||
TuiStartService(LPCWSTR lpServiceName)
|
||||
{
|
||||
SC_HANDLE hSCManager = NULL;
|
||||
SC_HANDLE hService = NULL;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
hSCManager = OpenSCManagerW(NULL, NULL, 0);
|
||||
if (hSCManager == NULL)
|
||||
goto cleanup;
|
||||
|
||||
hService = OpenServiceW(hSCManager, lpServiceName, SERVICE_START);
|
||||
if (hService == NULL)
|
||||
goto cleanup;
|
||||
|
||||
ret = StartServiceW(hService, 0, NULL);
|
||||
if (!ret)
|
||||
goto cleanup;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
if (hSCManager != NULL)
|
||||
CloseServiceHandle(hSCManager);
|
||||
if (hService != NULL)
|
||||
CloseServiceHandle(hService);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL FASTCALL
|
||||
TuiInit(DWORD OemCP)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
|
||||
DWORD BytesReturned;
|
||||
WNDCLASSEXW wc;
|
||||
USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||||
|
||||
TuiStartService(L"Blue");
|
||||
|
||||
ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen", FILE_ALL_ACCESS, 0, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle)
|
||||
{
|
||||
DPRINT1("Failed to open BlueScreen.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT,
|
||||
&OemCP, sizeof(OemCP), NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to load the font for codepage %d\n", OemCP);
|
||||
/* Let's suppose the font is good enough to continue */
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
|
||||
&TextAttribute, sizeof(TextAttribute), NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to set text attribute\n");
|
||||
}
|
||||
|
||||
ActiveConsole = NULL;
|
||||
InitializeCriticalSection(&ActiveConsoleLock);
|
||||
if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
|
||||
NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to get console info\n");
|
||||
return FALSE;
|
||||
}
|
||||
PhysicalConsoleSize = ScrInfo.dwSize;
|
||||
|
||||
RtlZeroMemory(&wc, sizeof(WNDCLASSEXW));
|
||||
wc.cbSize = sizeof(WNDCLASSEXW);
|
||||
wc.lpszClassName = L"TuiConsoleWindowClass";
|
||||
wc.lpfnWndProc = TuiConsoleWndProc;
|
||||
wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
|
||||
if (RegisterClassExW(&wc) == 0)
|
||||
{
|
||||
DPRINT1("Failed to register console wndproc\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer)
|
||||
{
|
||||
Buffer->DefaultAttrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||||
}
|
||||
|
||||
static void FASTCALL
|
||||
TuiCopyRect(char *Dest, PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *Region)
|
||||
{
|
||||
UINT SrcDelta, DestDelta;
|
||||
LONG i;
|
||||
PBYTE Src, SrcEnd;
|
||||
|
||||
Src = ConioCoordToPointer(Buff, Region->Left, Region->Top);
|
||||
SrcDelta = Buff->MaxX * 2;
|
||||
SrcEnd = Buff->Buffer + Buff->MaxY * Buff->MaxX * 2;
|
||||
DestDelta = ConioRectWidth(Region) * 2;
|
||||
for (i = Region->Top; i <= Region->Bottom; i++)
|
||||
{
|
||||
memcpy(Dest, Src, DestDelta);
|
||||
Src += SrcDelta;
|
||||
if (SrcEnd <= Src)
|
||||
{
|
||||
Src -= Buff->MaxY * Buff->MaxX * 2;
|
||||
}
|
||||
Dest += DestDelta;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT *Region)
|
||||
{
|
||||
DWORD BytesReturned;
|
||||
PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
|
||||
PCONSOLE_DRAW ConsoleDraw;
|
||||
UINT ConsoleDrawSize;
|
||||
|
||||
if (ActiveConsole != Console)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConsoleDrawSize = sizeof(CONSOLE_DRAW) +
|
||||
(ConioRectWidth(Region) * ConioRectHeight(Region)) * 2;
|
||||
ConsoleDraw = HeapAlloc(Win32CsrApiHeap, 0, ConsoleDrawSize);
|
||||
if (NULL == ConsoleDraw)
|
||||
{
|
||||
DPRINT1("HeapAlloc failed\n");
|
||||
return;
|
||||
}
|
||||
ConsoleDraw->X = Region->Left;
|
||||
ConsoleDraw->Y = Region->Top;
|
||||
ConsoleDraw->SizeX = ConioRectWidth(Region);
|
||||
ConsoleDraw->SizeY = ConioRectHeight(Region);
|
||||
ConsoleDraw->CursorX = Buff->CurrentX;
|
||||
ConsoleDraw->CursorY = Buff->CurrentY;
|
||||
|
||||
TuiCopyRect((char *) (ConsoleDraw + 1), Buff, Region);
|
||||
|
||||
if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW,
|
||||
NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1("Failed to draw console\n");
|
||||
HeapFree(Win32CsrApiHeap, 0, ConsoleDraw);
|
||||
return;
|
||||
}
|
||||
|
||||
HeapFree(Win32CsrApiHeap, 0, ConsoleDraw);
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiWriteStream(PCSRSS_CONSOLE Console, SMALL_RECT *Region, LONG CursorStartX, LONG CursorStartY,
|
||||
UINT ScrolledLines, CHAR *Buffer, UINT Length)
|
||||
{
|
||||
DWORD BytesWritten;
|
||||
PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
|
||||
|
||||
if (ActiveConsole->ActiveBuffer != Buff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (! WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL))
|
||||
{
|
||||
DPRINT1("Error writing to BlueScreen\n");
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
|
||||
{
|
||||
CONSOLE_CURSOR_INFO Info;
|
||||
DWORD BytesReturned;
|
||||
|
||||
if (ActiveConsole->ActiveBuffer != Buff)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Info.dwSize = ConioEffectiveCursorSize(Console, 100);
|
||||
Info.bVisible = Buff->CursorInfo.bVisible;
|
||||
|
||||
if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO,
|
||||
&Info, sizeof(Info), NULL, 0, &BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1( "Failed to set cursor info\n" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO Info;
|
||||
DWORD BytesReturned;
|
||||
|
||||
if (ActiveConsole->ActiveBuffer != Buff)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Info.dwCursorPosition.X = Buff->CurrentX;
|
||||
Info.dwCursorPosition.Y = Buff->CurrentY;
|
||||
Info.wAttributes = Buff->DefaultAttrib;
|
||||
|
||||
if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
|
||||
&Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1( "Failed to set cursor position\n" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiUpdateScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiChangeTitle(PCSRSS_CONSOLE Console)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
TuiCleanupConsole(PCSRSS_CONSOLE Console)
|
||||
{
|
||||
DestroyWindow(Console->hWindow);
|
||||
|
||||
EnterCriticalSection(&ActiveConsoleLock);
|
||||
|
||||
/* Switch to next console */
|
||||
if (ActiveConsole == Console)
|
||||
{
|
||||
ActiveConsole = Console->Next != Console ? Console->Next : NULL;
|
||||
}
|
||||
|
||||
if (Console->Next != Console)
|
||||
{
|
||||
Console->Prev->Next = Console->Next;
|
||||
Console->Next->Prev = Console->Prev;
|
||||
}
|
||||
LeaveCriticalSection(&ActiveConsoleLock);
|
||||
|
||||
if (NULL != ActiveConsole)
|
||||
{
|
||||
ConioDrawConsole(ActiveConsole);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiChangeIcon(PCSRSS_CONSOLE Console, HICON hWindowIcon)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI
|
||||
TuiResizeBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, COORD Size)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
TuiConsoleThread (PVOID Data)
|
||||
{
|
||||
PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Data;
|
||||
HWND NewWindow;
|
||||
MSG msg;
|
||||
|
||||
NewWindow = CreateWindowW(L"TuiConsoleWindowClass",
|
||||
Console->Title.Buffer,
|
||||
0,
|
||||
-32000, -32000, 0, 0,
|
||||
NULL, NULL,
|
||||
(HINSTANCE) GetModuleHandleW(NULL),
|
||||
(PVOID) Console);
|
||||
Console->hWindow = NewWindow;
|
||||
if (NULL == NewWindow)
|
||||
{
|
||||
DPRINT1("CSR: Unable to create console window\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
SetForegroundWindow(Console->hWindow);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GetMessageW(&msg, 0, 0, 0);
|
||||
DispatchMessage(&msg);
|
||||
TranslateMessage(&msg);
|
||||
|
||||
if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR ||
|
||||
msg.message == WM_KEYDOWN || msg.message == WM_KEYUP ||
|
||||
msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP)
|
||||
{
|
||||
ConioProcessKey(&msg, Console, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CSRSS_CONSOLE_VTBL TuiVtbl =
|
||||
{
|
||||
TuiInitScreenBuffer,
|
||||
TuiWriteStream,
|
||||
TuiDrawRegion,
|
||||
TuiSetCursorInfo,
|
||||
TuiSetScreenInfo,
|
||||
TuiUpdateScreenInfo,
|
||||
TuiChangeTitle,
|
||||
TuiCleanupConsole,
|
||||
TuiChangeIcon,
|
||||
TuiResizeBuffer,
|
||||
};
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
TuiInitConsole(PCSRSS_CONSOLE Console)
|
||||
{
|
||||
HANDLE ThreadHandle;
|
||||
|
||||
if (! ConsInitialized)
|
||||
{
|
||||
ConsInitialized = TRUE;
|
||||
if (! TuiInit(Console->CodePage))
|
||||
{
|
||||
ConsInitialized = FALSE;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
Console->Vtbl = &TuiVtbl;
|
||||
Console->hWindow = NULL;
|
||||
Console->Size = PhysicalConsoleSize;
|
||||
Console->ActiveBuffer->MaxX = PhysicalConsoleSize.X;
|
||||
Console->ActiveBuffer->MaxY = PhysicalConsoleSize.Y;
|
||||
|
||||
ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TuiConsoleThread,
|
||||
Console, 0, NULL);
|
||||
if (NULL == ThreadHandle)
|
||||
{
|
||||
DPRINT1("CSR: Unable to create console thread\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
CloseHandle(ThreadHandle);
|
||||
|
||||
EnterCriticalSection(&ActiveConsoleLock);
|
||||
if (NULL != ActiveConsole)
|
||||
{
|
||||
Console->Prev = ActiveConsole;
|
||||
Console->Next = ActiveConsole->Next;
|
||||
ActiveConsole->Next->Prev = Console;
|
||||
ActiveConsole->Next = Console;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console->Prev = Console;
|
||||
Console->Next = Console;
|
||||
}
|
||||
ActiveConsole = Console;
|
||||
LeaveCriticalSection(&ActiveConsoleLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PCSRSS_CONSOLE FASTCALL
|
||||
TuiGetFocusConsole(VOID)
|
||||
{
|
||||
return ActiveConsole;
|
||||
}
|
||||
|
||||
BOOL FASTCALL
|
||||
TuiSwapConsole(int Next)
|
||||
{
|
||||
static PCSRSS_CONSOLE SwapConsole = NULL; /* console we are thinking about swapping with */
|
||||
DWORD BytesReturned;
|
||||
ANSI_STRING Title;
|
||||
void * Buffer;
|
||||
COORD *pos;
|
||||
|
||||
if (0 != Next)
|
||||
{
|
||||
/* alt-tab, swap consoles */
|
||||
/* move SwapConsole to next console, and print its title */
|
||||
EnterCriticalSection(&ActiveConsoleLock);
|
||||
if (! SwapConsole)
|
||||
{
|
||||
SwapConsole = ActiveConsole;
|
||||
}
|
||||
|
||||
SwapConsole = (0 < Next ? SwapConsole->Next : SwapConsole->Prev);
|
||||
Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Title);
|
||||
Title.Length = 0;
|
||||
Buffer = HeapAlloc(Win32CsrApiHeap,
|
||||
0,
|
||||
sizeof(COORD) + Title.MaximumLength);
|
||||
pos = (COORD *)Buffer;
|
||||
Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof( COORD ));
|
||||
|
||||
RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE);
|
||||
pos->Y = PhysicalConsoleSize.Y / 2;
|
||||
pos->X = (PhysicalConsoleSize.X - Title.Length) / 2;
|
||||
/* redraw the console to clear off old title */
|
||||
ConioDrawConsole(ActiveConsole);
|
||||
if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
|
||||
NULL, 0, Buffer, sizeof(COORD) + Title.Length,
|
||||
&BytesReturned, NULL))
|
||||
{
|
||||
DPRINT1( "Error writing to console\n" );
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, Buffer);
|
||||
LeaveCriticalSection(&ActiveConsoleLock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (NULL != SwapConsole)
|
||||
{
|
||||
EnterCriticalSection(&ActiveConsoleLock);
|
||||
if (SwapConsole != ActiveConsole)
|
||||
{
|
||||
/* first remove swapconsole from the list */
|
||||
SwapConsole->Prev->Next = SwapConsole->Next;
|
||||
SwapConsole->Next->Prev = SwapConsole->Prev;
|
||||
/* now insert before activeconsole */
|
||||
SwapConsole->Next = ActiveConsole;
|
||||
SwapConsole->Prev = ActiveConsole->Prev;
|
||||
ActiveConsole->Prev->Next = SwapConsole;
|
||||
ActiveConsole->Prev = SwapConsole;
|
||||
}
|
||||
ActiveConsole = SwapConsole;
|
||||
SwapConsole = NULL;
|
||||
ConioDrawConsole(ActiveConsole);
|
||||
LeaveCriticalSection(&ActiveConsoleLock);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/tuiconsole.h
|
||||
* PURPOSE: Interface to text-mode consoles
|
||||
*/
|
||||
|
||||
#include "api.h"
|
||||
|
||||
extern NTSTATUS FASTCALL TuiInitConsole(PCSRSS_CONSOLE Console);
|
||||
extern PCSRSS_CONSOLE FASTCALL TuiGetFocusConsole(VOID);
|
||||
extern BOOL FASTCALL TuiSwapConsole(int Next);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,46 @@
|
||||
/* PSDK/NDK Headers */
|
||||
#define WIN32_NO_STATUS
|
||||
#define _INC_WINDOWS
|
||||
#define COM_NO_WINDOWS_H
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <wingdi.h>
|
||||
#include <winnls.h>
|
||||
#include <winreg.h>
|
||||
#include <winsvc.h>
|
||||
#include <wincon.h>
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/iofuncs.h>
|
||||
#include <ndk/kefuncs.h>
|
||||
#include <ndk/mmfuncs.h>
|
||||
#include <ndk/obfuncs.h>
|
||||
#include <ndk/umfuncs.h>
|
||||
#include <psapi.h>
|
||||
|
||||
/* External Winlogon Header */
|
||||
#include <winlogon.h>
|
||||
|
||||
/* Internal CSRSS Headers */
|
||||
#include <conio.h>
|
||||
#include <csrplugin.h>
|
||||
#include <desktopbg.h>
|
||||
#include "guiconsole.h"
|
||||
#include "tuiconsole.h"
|
||||
|
||||
/* Public Win32K Headers */
|
||||
#include <ntuser.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
/* shared header with console.dll */
|
||||
#include "console.h"
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
Win32CsrHardError(
|
||||
IN PCSR_THREAD ThreadData,
|
||||
IN PHARDERROR_MSG Message);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: subsys/csrss/win32csr/win32csr.h
|
||||
* PURPOSE: Interface to win32csr.dll
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <objbase.h>
|
||||
|
||||
extern HANDLE Win32CsrApiHeap;
|
||||
extern HINSTANCE Win32CsrDllHandle;
|
||||
|
||||
typedef struct Object_tt
|
||||
{
|
||||
LONG Type;
|
||||
struct tagCSRSS_CONSOLE *Console;
|
||||
LONG AccessRead, AccessWrite;
|
||||
LONG ExclusiveRead, ExclusiveWrite;
|
||||
LONG HandleCount;
|
||||
} Object_t;
|
||||
|
||||
typedef struct _CSRSS_HANDLE
|
||||
{
|
||||
Object_t *Object;
|
||||
DWORD Access;
|
||||
BOOL Inheritable;
|
||||
DWORD ShareMode;
|
||||
} CSRSS_HANDLE, *PCSRSS_HANDLE;
|
||||
|
||||
typedef VOID (WINAPI *CSR_CLEANUP_OBJECT_PROC)(Object_t *Object);
|
||||
|
||||
typedef struct tagCSRSS_OBJECT_DEFINITION
|
||||
{
|
||||
LONG Type;
|
||||
CSR_CLEANUP_OBJECT_PROC CsrCleanupObjectProc;
|
||||
} CSRSS_OBJECT_DEFINITION, *PCSRSS_OBJECT_DEFINITION;
|
||||
|
||||
/* handle.c */
|
||||
NTSTATUS FASTCALL Win32CsrInsertObject(PCSR_PROCESS ProcessData,
|
||||
PHANDLE Handle,
|
||||
Object_t *Object,
|
||||
DWORD Access,
|
||||
BOOL Inheritable,
|
||||
DWORD ShareMode);
|
||||
NTSTATUS FASTCALL Win32CsrLockObject(PCSR_PROCESS ProcessData,
|
||||
HANDLE Handle,
|
||||
Object_t **Object,
|
||||
DWORD Access,
|
||||
long Type);
|
||||
VOID FASTCALL Win32CsrUnlockObject(Object_t *Object);
|
||||
NTSTATUS FASTCALL Win32CsrReleaseObject(PCSR_PROCESS ProcessData,
|
||||
HANDLE Object);
|
||||
VOID WINAPI Win32CsrReleaseConsole(PCSR_PROCESS ProcessData);
|
||||
NTSTATUS WINAPI Win32CsrDuplicateHandleTable(PCSR_PROCESS SourceProcessData,
|
||||
PCSR_PROCESS TargetProcessData);
|
||||
CSR_API(CsrGetHandle);
|
||||
CSR_API(CsrCloseHandle);
|
||||
CSR_API(CsrVerifyHandle);
|
||||
CSR_API(CsrDuplicateHandle);
|
||||
CSR_API(CsrGetInputWaitHandle);
|
||||
|
||||
BOOL FASTCALL Win32CsrValidateBuffer(PCSR_PROCESS ProcessData,
|
||||
PVOID Buffer,
|
||||
SIZE_T NumElements,
|
||||
SIZE_T ElementSize);
|
||||
NTSTATUS FASTCALL Win32CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc,
|
||||
PVOID Context);
|
||||
|
||||
/* exitros.c */
|
||||
CSR_API(CsrExitReactos);
|
||||
CSR_API(CsrSetLogonNotifyWindow);
|
||||
CSR_API(CsrRegisterLogonProcess);
|
||||
|
||||
CSR_API(CsrSoundSentry);
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <windef.h>
|
||||
#include <winuser.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "CSRSS subsystem usermode code\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "win32csr\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "win32csr.dll\0"
|
||||
#include <reactos/version.rc>
|
||||
|
||||
#include "rsrc.rc"
|
||||
@@ -0,0 +1 @@
|
||||
@ stdcall Win32CsrInitialization(ptr)
|
||||
Reference in New Issue
Block a user