From 9c283d750852f725cbe069a2a1572822536b23dc Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Fri, 7 Mar 2014 23:46:43 +0000 Subject: [PATCH] [BASESRV] - Move more constants to the global header. - Implement GetConsoleRecordBySessionId. - Implement BaseSrvUpdateVDMEntry. - Improve and fix bugs in the cleanup code. svn path=/branches/ntvdm/; revision=62451 --- dll/win32/kernel32/include/vdm.h | 17 ---- include/reactos/subsys/win/vdm.h | 17 ++++ subsystems/win/basesrv/vdm.c | 163 ++++++++++++++++++++++++++++++- subsystems/win/basesrv/vdm.h | 1 + 4 files changed, 177 insertions(+), 21 deletions(-) diff --git a/dll/win32/kernel32/include/vdm.h b/dll/win32/kernel32/include/vdm.h index 82834fbdbe0..56e872683c3 100644 --- a/dll/win32/kernel32/include/vdm.h +++ b/dll/win32/kernel32/include/vdm.h @@ -8,23 +8,6 @@ #pragma once -/* CONSTANTS ******************************************************************/ - -typedef enum _VDM_ENTRY_CODE -{ - VdmEntryUndo, - VdmEntryUpdateProcess, - VdmEntryUpdateControlCHandler -} VDM_ENTRY_CODE; - -// -// Undo States -// -#define VDM_UNDO_PARTIAL 0x01 -#define VDM_UNDO_FULL 0x02 -#define VDM_UNDO_REUSE 0x04 -#define VDM_UNDO_COMPLETED 0x08 - /* FUNCTION PROTOTYPES ********************************************************/ BOOL diff --git a/include/reactos/subsys/win/vdm.h b/include/reactos/subsys/win/vdm.h index 03b72e70fb0..97dafcd2e09 100644 --- a/include/reactos/subsys/win/vdm.h +++ b/include/reactos/subsys/win/vdm.h @@ -12,6 +12,23 @@ #pragma once +/* CONSTANTS ******************************************************************/ + +typedef enum _VDM_ENTRY_CODE +{ + VdmEntryUndo, + VdmEntryUpdateProcess, + VdmEntryUpdateControlCHandler +} VDM_ENTRY_CODE; + +// +// Undo States +// +#define VDM_UNDO_PARTIAL 0x01 +#define VDM_UNDO_FULL 0x02 +#define VDM_UNDO_REUSE 0x04 +#define VDM_UNDO_COMPLETED 0x08 + // // Binary Types to share with VDM // diff --git a/subsystems/win/basesrv/vdm.c b/subsystems/win/basesrv/vdm.c index 2934f8f293d..a311dafe154 100644 --- a/subsystems/win/basesrv/vdm.c +++ b/subsystems/win/basesrv/vdm.c @@ -40,6 +40,22 @@ NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND; } +NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record) +{ + PLIST_ENTRY i; + PVDM_CONSOLE_RECORD CurrentRecord = NULL; + + /* Search for a record that has the same console handle */ + for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink) + { + CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry); + if (CurrentRecord->SessionId == TaskId) break; + } + + *Record = CurrentRecord; + return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND; +} + ULONG NTAPI GetNextDosSesId(VOID) { ULONG SessionId; @@ -463,6 +479,9 @@ CSR_API(BaseSrvCheckVDM) Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent); if (!NT_SUCCESS(Status)) goto Cleanup; + /* Return the client event handle */ + CheckVdmRequest->WaitObjectForParent = DosRecord->ClientEvent; + /* Translate the input structure into a VDM command structure and set it in the DOS record */ if (!BaseSrvCopyCommand(CheckVdmRequest, DosRecord)) { @@ -487,7 +506,7 @@ CSR_API(BaseSrvCheckVDM) { // TODO: NOT IMPLEMENTED UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; } Cleanup: @@ -497,6 +516,19 @@ Cleanup: /* Free the DOS record */ if (DosRecord != NULL) { + if (DosRecord->ServerEvent) NtClose(DosRecord->ServerEvent); + if (DosRecord->ClientEvent) + { + /* Close the remote handle */ + NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle, + DosRecord->ClientEvent, + NULL, + NULL, + 0, + 0, + DUPLICATE_CLOSE_SOURCE); + } + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); DosRecord = NULL; } @@ -517,8 +549,125 @@ Cleanup: CSR_API(BaseSrvUpdateVDMEntry) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.UpdateVDMEntryRequest; + PRTL_CRITICAL_SECTION CriticalSection = NULL; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord = NULL; + + CriticalSection = (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW) + ? &DosCriticalSection + : &WowCriticalSection; + + /* Enter the critical section */ + RtlEnterCriticalSection(CriticalSection); + + /* Check if this is a DOS or WOW VDM */ + if (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW) + { + if (UpdateVdmEntryRequest->iTask != 0) + { + /* Get the console record using the task ID */ + Status = GetConsoleRecordBySessionId(UpdateVdmEntryRequest->iTask, + &ConsoleRecord); + } + else + { + /* Get the console record using the console handle */ + Status = BaseSrvGetConsoleRecord(UpdateVdmEntryRequest->ConsoleHandle, + &ConsoleRecord); + } + + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Get the primary DOS record */ + DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, + VDM_DOS_RECORD, + Entry); + + switch (UpdateVdmEntryRequest->EntryIndex) + { + case VdmEntryUndo: + { + /* Close the server event handle, the client will close the client handle */ + NtClose(DosRecord->ServerEvent); + DosRecord->ServerEvent = DosRecord->ClientEvent = NULL; + + if (UpdateVdmEntryRequest->VDMCreationState & (VDM_UNDO_PARTIAL | VDM_UNDO_FULL)) + { + /* Remove the DOS record */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + RemoveEntryList(&DosRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); + + /* + * Since this is an undo, if that was the only DOS record the VDM + * won't even start, so the console record should be removed too. + */ + if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead) + { + RemoveEntryList(&ConsoleRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + } + } + + /* It was successful */ + Status = STATUS_SUCCESS; + + break; + } + + case VdmEntryUpdateProcess: + { + /* Duplicate the VDM process handle */ + Status = NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle, + UpdateVdmEntryRequest->VDMProcessHandle, + NtCurrentProcess(), + &ConsoleRecord->ProcessHandle, + 0, + 0, + DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Create a pair of handles to one event object */ + Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, + &DosRecord->ClientEvent); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Return the client event handle */ + UpdateVdmEntryRequest->WaitObjectForParent = DosRecord->ClientEvent; + + break; + } + + case VdmEntryUpdateControlCHandler: + { + // TODO: NOT IMPLEMENTED + DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!"); + Status = STATUS_NOT_IMPLEMENTED; + + break; + } + + default: + { + /* Invalid */ + Status = STATUS_INVALID_PARAMETER; + } + } + } + else + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; + } + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(CriticalSection); + + return Status; } CSR_API(BaseSrvGetNextVDMCommand) @@ -555,7 +704,12 @@ CSR_API(BaseSrvExitVDM) VDM_DOS_RECORD, Entry); + /* Set the event and close it */ + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + /* Remove the DOS entry */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); RemoveEntryList(&DosRecord->Entry); RtlFreeHeap(BaseSrvHeap, 0, DosRecord); } @@ -576,7 +730,7 @@ CSR_API(BaseSrvExitVDM) { // TODO: NOT IMPLEMENTED UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; } Cleanup: @@ -639,6 +793,7 @@ CSR_API(BaseSrvGetVDMExitCode) GetVDMExitCodeRequest->ExitCode = DosRecord->ExitCode; /* Since this is a zombie task record, remove it */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); RemoveEntryList(&DosRecord->Entry); RtlFreeHeap(BaseSrvHeap, 0, DosRecord); diff --git a/subsystems/win/basesrv/vdm.h b/subsystems/win/basesrv/vdm.h index a6df20577d0..10e65a156cb 100644 --- a/subsystems/win/basesrv/vdm.h +++ b/subsystems/win/basesrv/vdm.h @@ -20,6 +20,7 @@ typedef struct _VDM_CONSOLE_RECORD { LIST_ENTRY Entry; HANDLE ConsoleHandle; + HANDLE ProcessHandle; PCHAR CurrentDirs; ULONG CurDirsLength; ULONG SessionId; -- 2.17.1