[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
This commit is contained in:
Aleksandar Andrejevic 2014-03-07 23:46:43 +00:00
parent fd0de4552b
commit 9c283d7508
4 changed files with 177 additions and 21 deletions

View file

@ -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

View file

@ -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
//

View file

@ -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);

View file

@ -20,6 +20,7 @@ typedef struct _VDM_CONSOLE_RECORD
{
LIST_ENTRY Entry;
HANDLE ConsoleHandle;
HANDLE ProcessHandle;
PCHAR CurrentDirs;
ULONG CurDirsLength;
ULONG SessionId;