2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Base API Server DLL
4 * FILE: subsystems/win/basesrv/vdm.c
5 * PURPOSE: Virtual DOS Machines (VDM) Support
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 * Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
10 /* INCLUDES *******************************************************************/
18 /* GLOBALS ********************************************************************/
20 BOOLEAN FirstVDM
= TRUE
;
21 LIST_ENTRY VDMConsoleListHead
;
22 RTL_CRITICAL_SECTION DosCriticalSection
;
23 RTL_CRITICAL_SECTION WowCriticalSection
;
25 /* FUNCTIONS ******************************************************************/
27 NTSTATUS NTAPI
BaseSrvGetConsoleRecord(HANDLE ConsoleHandle
, PVDM_CONSOLE_RECORD
*Record
)
30 PVDM_CONSOLE_RECORD CurrentRecord
= NULL
;
32 /* NULL is not a valid console handle */
33 if (ConsoleHandle
== NULL
) return STATUS_INVALID_PARAMETER
;
35 /* Search for a record that has the same console handle */
36 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
38 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
39 if (CurrentRecord
->ConsoleHandle
== ConsoleHandle
) break;
42 /* Check if nothing was found */
43 if (i
== &VDMConsoleListHead
) CurrentRecord
= NULL
;
45 *Record
= CurrentRecord
;
46 return CurrentRecord
? STATUS_SUCCESS
: STATUS_NOT_FOUND
;
49 NTSTATUS NTAPI
GetConsoleRecordBySessionId(ULONG TaskId
, PVDM_CONSOLE_RECORD
*Record
)
52 PVDM_CONSOLE_RECORD CurrentRecord
= NULL
;
54 /* Search for a record that has the same console handle */
55 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
57 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
58 if (CurrentRecord
->SessionId
== TaskId
) break;
61 /* Check if nothing was found */
62 if (i
== &VDMConsoleListHead
) CurrentRecord
= NULL
;
64 *Record
= CurrentRecord
;
65 return CurrentRecord
? STATUS_SUCCESS
: STATUS_NOT_FOUND
;
68 ULONG NTAPI
GetNextDosSesId(VOID
)
72 PVDM_CONSOLE_RECORD CurrentRecord
= NULL
;
75 /* Search for an available session ID */
76 for (SessionId
= 1; SessionId
!= 0; SessionId
++)
80 /* Check if the ID is already in use */
81 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
83 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
84 if (CurrentRecord
->SessionId
== SessionId
) Found
= TRUE
;
87 /* If not, we found one */
91 ASSERT(SessionId
!= 0);
93 /* Return the session ID */
97 BOOLEAN NTAPI
BaseSrvIsVdmAllowed(VOID
)
100 BOOLEAN VdmAllowed
= TRUE
;
101 HANDLE RootKey
, KeyHandle
;
102 UNICODE_STRING KeyName
, ValueName
, MachineKeyName
;
103 OBJECT_ATTRIBUTES Attributes
;
104 UCHAR ValueBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
105 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
108 /* Initialize the unicode strings */
109 RtlInitUnicodeString(&MachineKeyName
, L
"\\Registry\\Machine");
110 RtlInitUnicodeString(&KeyName
, VDM_POLICY_KEY_NAME
);
111 RtlInitUnicodeString(&ValueName
, VDM_DISALLOWED_VALUE_NAME
);
113 InitializeObjectAttributes(&Attributes
,
115 OBJ_CASE_INSENSITIVE
,
119 /* Open the local machine key */
120 Status
= NtOpenKey(&RootKey
, KEY_READ
, &Attributes
);
121 if (!NT_SUCCESS(Status
)) return FALSE
;
123 InitializeObjectAttributes(&Attributes
,
125 OBJ_CASE_INSENSITIVE
,
129 /* Open the policy key in the local machine hive, if it exists */
130 if (NT_SUCCESS(NtOpenKey(&KeyHandle
, KEY_READ
, &Attributes
)))
132 /* Read the value, if it's set */
133 if (NT_SUCCESS(NtQueryValueKey(KeyHandle
,
135 KeyValuePartialInformation
,
140 if (*((PULONG
)ValueInfo
->Data
))
142 /* The VDM has been disabled in the registry */
150 /* Close the local machine key */
153 /* If it's disabled system-wide, there's no need to check the user key */
154 if (!VdmAllowed
) return FALSE
;
156 /* Open the current user key of the client */
157 if (!CsrImpersonateClient(NULL
)) return VdmAllowed
;
158 Status
= RtlOpenCurrentUser(KEY_READ
, &RootKey
);
161 /* If that fails, return the system-wide setting */
162 if (!NT_SUCCESS(Status
)) return VdmAllowed
;
164 InitializeObjectAttributes(&Attributes
,
166 OBJ_CASE_INSENSITIVE
,
170 /* Open the policy key in the current user hive, if it exists */
171 if (NT_SUCCESS(NtOpenKey(&KeyHandle
, KEY_READ
, &Attributes
)))
173 /* Read the value, if it's set */
174 if (NT_SUCCESS(NtQueryValueKey(KeyHandle
,
176 KeyValuePartialInformation
,
181 if (*((PULONG
)ValueInfo
->Data
))
183 /* The VDM has been disabled in the registry */
194 NTSTATUS NTAPI
BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent
, PHANDLE ClientEvent
)
198 /* Create the event */
199 Status
= NtCreateEvent(ServerEvent
, EVENT_ALL_ACCESS
, NULL
, NotificationEvent
, FALSE
);
200 if (!NT_SUCCESS(Status
)) return Status
;
202 /* Duplicate the event into the client process */
203 Status
= NtDuplicateObject(NtCurrentProcess(),
205 CsrGetClientThread()->Process
->ProcessHandle
,
209 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
211 if (!NT_SUCCESS(Status
)) NtClose(*ServerEvent
);
215 VOID NTAPI
BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo
)
217 /* Free the allocated structure members */
218 if (CommandInfo
->CmdLine
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->CmdLine
);
219 if (CommandInfo
->AppName
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->AppName
);
220 if (CommandInfo
->PifFile
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->PifFile
);
221 if (CommandInfo
->CurDirectory
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->CurDirectory
);
222 if (CommandInfo
->Env
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Env
);
223 if (CommandInfo
->Desktop
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Desktop
);
224 if (CommandInfo
->Title
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Title
);
225 if (CommandInfo
->Reserved
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Reserved
);
227 /* Free the structure itself */
228 RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
);
231 VOID NTAPI
BaseSrvCleanupVdmRecords(ULONG ProcessId
)
234 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
235 PVDM_DOS_RECORD DosRecord
;
237 /* Enter the critical section */
238 RtlEnterCriticalSection(&DosCriticalSection
);
240 /* Search for a record that has the same process handle */
241 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
243 ConsoleRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
245 if (ConsoleRecord
->ProcessId
== ProcessId
)
247 /* Cleanup the DOS records */
248 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
250 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
254 /* Set the event and close it */
255 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
256 NtClose(DosRecord
->ServerEvent
);
258 /* Remove the DOS entry */
259 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
260 RemoveEntryList(&DosRecord
->Entry
);
261 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
264 if (ConsoleRecord
->CurrentDirs
!= NULL
)
266 /* Free the current directories */
267 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
268 ConsoleRecord
->CurrentDirs
= NULL
;
269 ConsoleRecord
->CurDirsLength
= 0;
272 /* Close the process handle */
273 if (ConsoleRecord
->ProcessHandle
) NtClose(ConsoleRecord
->ProcessHandle
);
275 /* Close the event handle */
276 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
278 /* Remove the console record */
280 RemoveEntryList(&ConsoleRecord
->Entry
);
281 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
285 /* Leave the critical section */
286 RtlLeaveCriticalSection(&DosCriticalSection
);
289 BOOLEAN NTAPI
BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest
, PVDM_DOS_RECORD DosRecord
)
291 BOOLEAN Success
= FALSE
;
292 PVDM_COMMAND_INFO CommandInfo
= NULL
;
294 /* Allocate the command information structure */
295 CommandInfo
= (PVDM_COMMAND_INFO
)RtlAllocateHeap(BaseSrvHeap
,
297 sizeof(VDM_COMMAND_INFO
));
298 if (CommandInfo
== NULL
) return FALSE
;
300 /* Fill the structure */
301 CommandInfo
->TaskId
= CheckVdmRequest
->iTask
;
302 CommandInfo
->ExitCode
= DosRecord
->ExitCode
;
303 CommandInfo
->CodePage
= CheckVdmRequest
->CodePage
;
304 CommandInfo
->StdIn
= CheckVdmRequest
->StdIn
;
305 CommandInfo
->StdOut
= CheckVdmRequest
->StdOut
;
306 CommandInfo
->StdErr
= CheckVdmRequest
->StdErr
;
308 /* Allocate memory for the command line */
309 CommandInfo
->CmdLine
= RtlAllocateHeap(BaseSrvHeap
,
311 CheckVdmRequest
->CmdLen
);
312 if (CommandInfo
->CmdLine
== NULL
) goto Cleanup
;
314 /* Copy the command line */
315 RtlMoveMemory(CommandInfo
->CmdLine
, CheckVdmRequest
->CmdLine
, CheckVdmRequest
->CmdLen
);
317 /* Allocate memory for the application name */
318 CommandInfo
->AppName
= RtlAllocateHeap(BaseSrvHeap
,
320 CheckVdmRequest
->AppLen
);
321 if (CommandInfo
->AppName
== NULL
) goto Cleanup
;
323 /* Copy the application name */
324 RtlMoveMemory(CommandInfo
->AppName
, CheckVdmRequest
->AppName
, CheckVdmRequest
->AppLen
);
326 /* Allocate memory for the PIF file name */
327 if (CheckVdmRequest
->PifLen
!= 0)
329 CommandInfo
->PifFile
= RtlAllocateHeap(BaseSrvHeap
,
331 CheckVdmRequest
->PifLen
);
332 if (CommandInfo
->PifFile
== NULL
) goto Cleanup
;
334 /* Copy the PIF file name */
335 RtlMoveMemory(CommandInfo
->PifFile
, CheckVdmRequest
->PifFile
, CheckVdmRequest
->PifLen
);
337 else CommandInfo
->PifFile
= NULL
;
339 /* Allocate memory for the current directory */
340 if (CheckVdmRequest
->CurDirectoryLen
!= 0)
342 CommandInfo
->CurDirectory
= RtlAllocateHeap(BaseSrvHeap
,
344 CheckVdmRequest
->CurDirectoryLen
);
345 if (CommandInfo
->CurDirectory
== NULL
) goto Cleanup
;
347 /* Copy the current directory */
348 RtlMoveMemory(CommandInfo
->CurDirectory
,
349 CheckVdmRequest
->CurDirectory
,
350 CheckVdmRequest
->CurDirectoryLen
);
352 else CommandInfo
->CurDirectory
= NULL
;
354 /* Allocate memory for the environment block */
355 CommandInfo
->Env
= RtlAllocateHeap(BaseSrvHeap
,
357 CheckVdmRequest
->EnvLen
);
358 if (CommandInfo
->Env
== NULL
) goto Cleanup
;
360 /* Copy the environment block */
361 RtlMoveMemory(CommandInfo
->Env
, CheckVdmRequest
->Env
, CheckVdmRequest
->EnvLen
);
363 CommandInfo
->EnvLen
= CheckVdmRequest
->EnvLen
;
364 RtlMoveMemory(&CommandInfo
->StartupInfo
,
365 CheckVdmRequest
->StartupInfo
,
366 sizeof(STARTUPINFOA
));
368 /* Allocate memory for the desktop */
369 if (CheckVdmRequest
->DesktopLen
!= 0)
371 CommandInfo
->Desktop
= RtlAllocateHeap(BaseSrvHeap
,
373 CheckVdmRequest
->DesktopLen
);
374 if (CommandInfo
->Desktop
== NULL
) goto Cleanup
;
376 /* Copy the desktop name */
377 RtlMoveMemory(CommandInfo
->Desktop
, CheckVdmRequest
->Desktop
, CheckVdmRequest
->DesktopLen
);
379 else CommandInfo
->Desktop
= NULL
;
381 CommandInfo
->DesktopLen
= CheckVdmRequest
->DesktopLen
;
383 /* Allocate memory for the title */
384 if (CheckVdmRequest
->TitleLen
!= 0)
386 CommandInfo
->Title
= RtlAllocateHeap(BaseSrvHeap
,
388 CheckVdmRequest
->TitleLen
);
389 if (CommandInfo
->Title
== NULL
) goto Cleanup
;
392 RtlMoveMemory(CommandInfo
->Title
, CheckVdmRequest
->Title
, CheckVdmRequest
->TitleLen
);
394 else CommandInfo
->Title
= NULL
;
396 CommandInfo
->TitleLen
= CheckVdmRequest
->TitleLen
;
398 /* Allocate memory for the reserved field */
399 if (CheckVdmRequest
->ReservedLen
!= 0)
401 CommandInfo
->Reserved
= RtlAllocateHeap(BaseSrvHeap
,
403 CheckVdmRequest
->ReservedLen
);
404 if (CommandInfo
->Reserved
== NULL
) goto Cleanup
;
406 /* Copy the reserved field */
407 RtlMoveMemory(CommandInfo
->Reserved
,
408 CheckVdmRequest
->Reserved
,
409 CheckVdmRequest
->ReservedLen
);
411 else CommandInfo
->Reserved
= NULL
;
413 CommandInfo
->ReservedLen
= CheckVdmRequest
->ReservedLen
;
415 CommandInfo
->CmdLen
= CheckVdmRequest
->CmdLen
;
416 CommandInfo
->AppLen
= CheckVdmRequest
->AppLen
;
417 CommandInfo
->PifLen
= CheckVdmRequest
->PifLen
;
418 CommandInfo
->CurDirectoryLen
= CheckVdmRequest
->CurDirectoryLen
;
419 CommandInfo
->VDMState
= DosRecord
->State
;
420 // TODO: Set CommandInfo->CurrentDrive
421 // TODO: Set CommandInfo->ComingFromBat
423 /* Set the DOS record's command structure */
424 DosRecord
->CommandInfo
= CommandInfo
;
426 /* The operation was successful */
430 /* If it wasn't successful, free the memory */
431 if (!Success
) BaseSrvFreeVDMInfo(CommandInfo
);
436 NTSTATUS NTAPI
BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo
,
437 PBASE_GET_NEXT_VDM_COMMAND Message
)
439 NTSTATUS Status
= STATUS_SUCCESS
;
442 Message
->iTask
= CommandInfo
->TaskId
;
443 Message
->StdIn
= CommandInfo
->StdIn
;
444 Message
->StdOut
= CommandInfo
->StdOut
;
445 Message
->StdErr
= CommandInfo
->StdErr
;
446 Message
->CodePage
= CommandInfo
->CodePage
;
447 Message
->dwCreationFlags
= CommandInfo
->CreationFlags
;
448 Message
->ExitCode
= CommandInfo
->ExitCode
;
449 Message
->CurrentDrive
= CommandInfo
->CurrentDrive
;
450 Message
->VDMState
= CommandInfo
->VDMState
;
451 Message
->fComingFromBat
= CommandInfo
->ComingFromBat
;
453 if (CommandInfo
->CmdLen
&& Message
->CmdLen
)
455 if (Message
->CmdLen
>= CommandInfo
->CmdLen
)
457 /* Copy the command line */
458 RtlMoveMemory(Message
->CmdLine
, CommandInfo
->CmdLine
, CommandInfo
->CmdLen
);
460 else Status
= STATUS_BUFFER_TOO_SMALL
;
462 Message
->CmdLen
= CommandInfo
->CmdLen
;
465 if (CommandInfo
->AppLen
&& Message
->AppLen
)
467 if (Message
->AppLen
>= CommandInfo
->AppLen
)
469 /* Copy the application name */
470 RtlMoveMemory(Message
->AppName
, CommandInfo
->AppName
, CommandInfo
->AppLen
);
472 else Status
= STATUS_BUFFER_TOO_SMALL
;
474 Message
->AppLen
= CommandInfo
->AppLen
;
477 if (CommandInfo
->PifLen
&& Message
->PifLen
)
479 if (Message
->PifLen
>= CommandInfo
->PifLen
)
481 /* Copy the PIF file name */
482 RtlMoveMemory(Message
->PifFile
, CommandInfo
->PifFile
, CommandInfo
->PifLen
);
484 else Status
= STATUS_BUFFER_TOO_SMALL
;
486 Message
->PifLen
= CommandInfo
->PifLen
;
489 if (CommandInfo
->CurDirectoryLen
&& Message
->CurDirectoryLen
)
491 if (Message
->CurDirectoryLen
>= CommandInfo
->CurDirectoryLen
)
493 /* Copy the current directory */
494 RtlMoveMemory(Message
->CurDirectory
, CommandInfo
->CurDirectory
, CommandInfo
->CurDirectoryLen
);
496 else Status
= STATUS_BUFFER_TOO_SMALL
;
498 Message
->CurDirectoryLen
= CommandInfo
->CurDirectoryLen
;
501 if (CommandInfo
->EnvLen
&& Message
->EnvLen
)
503 if (Message
->EnvLen
>= CommandInfo
->EnvLen
)
505 /* Copy the environment */
506 RtlMoveMemory(Message
->Env
, CommandInfo
->Env
, CommandInfo
->EnvLen
);
508 else Status
= STATUS_BUFFER_TOO_SMALL
;
510 Message
->EnvLen
= CommandInfo
->EnvLen
;
513 /* Copy the startup info */
514 RtlMoveMemory(Message
->StartupInfo
,
515 &CommandInfo
->StartupInfo
,
516 sizeof(STARTUPINFOA
));
518 if (CommandInfo
->DesktopLen
&& Message
->DesktopLen
)
520 if (Message
->DesktopLen
>= CommandInfo
->DesktopLen
)
522 /* Copy the desktop name */
523 RtlMoveMemory(Message
->Desktop
, CommandInfo
->Desktop
, CommandInfo
->DesktopLen
);
525 else Status
= STATUS_BUFFER_TOO_SMALL
;
527 Message
->DesktopLen
= CommandInfo
->DesktopLen
;
530 if (CommandInfo
->TitleLen
&& Message
->TitleLen
)
532 if (Message
->TitleLen
>= CommandInfo
->TitleLen
)
535 RtlMoveMemory(Message
->Title
, CommandInfo
->Title
, CommandInfo
->TitleLen
);
537 else Status
= STATUS_BUFFER_TOO_SMALL
;
539 Message
->TitleLen
= CommandInfo
->TitleLen
;
542 if (CommandInfo
->ReservedLen
&& Message
->ReservedLen
)
544 if (Message
->ReservedLen
>= CommandInfo
->ReservedLen
)
546 /* Copy the reserved parameter */
547 RtlMoveMemory(Message
->Reserved
, CommandInfo
->Reserved
, CommandInfo
->ReservedLen
);
549 else Status
= STATUS_BUFFER_TOO_SMALL
;
551 Message
->ReservedLen
= CommandInfo
->ReservedLen
;
557 VOID NTAPI
BaseInitializeVDM(VOID
)
559 /* Initialize the list head */
560 InitializeListHead(&VDMConsoleListHead
);
562 /* Initialize the critical section */
563 RtlInitializeCriticalSection(&DosCriticalSection
);
564 RtlInitializeCriticalSection(&WowCriticalSection
);
567 /* PUBLIC SERVER APIS *********************************************************/
569 CSR_API(BaseSrvCheckVDM
)
572 PBASE_CHECK_VDM CheckVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CheckVDMRequest
;
573 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
574 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
575 PVDM_DOS_RECORD DosRecord
= NULL
;
576 BOOLEAN NewConsoleRecord
= FALSE
;
578 /* Don't do anything if the VDM has been disabled in the registry */
579 if (!BaseSrvIsVdmAllowed()) return STATUS_ACCESS_DENIED
;
581 /* Validate the message buffers */
582 if (!CsrValidateMessageBuffer(ApiMessage
,
583 (PVOID
*)&CheckVdmRequest
->CmdLine
,
584 CheckVdmRequest
->CmdLen
,
585 sizeof(*CheckVdmRequest
->CmdLine
))
586 || !CsrValidateMessageBuffer(ApiMessage
,
587 (PVOID
*)&CheckVdmRequest
->AppName
,
588 CheckVdmRequest
->AppLen
,
589 sizeof(*CheckVdmRequest
->AppName
))
590 || !CsrValidateMessageBuffer(ApiMessage
,
591 (PVOID
*)&CheckVdmRequest
->PifFile
,
592 CheckVdmRequest
->PifLen
,
593 sizeof(*CheckVdmRequest
->PifFile
))
594 || !CsrValidateMessageBuffer(ApiMessage
,
595 (PVOID
*)&CheckVdmRequest
->CurDirectory
,
596 CheckVdmRequest
->CurDirectoryLen
,
597 sizeof(*CheckVdmRequest
->CurDirectory
))
598 || !CsrValidateMessageBuffer(ApiMessage
,
599 (PVOID
*)&CheckVdmRequest
->Desktop
,
600 CheckVdmRequest
->DesktopLen
,
601 sizeof(*CheckVdmRequest
->Desktop
))
602 || !CsrValidateMessageBuffer(ApiMessage
,
603 (PVOID
*)&CheckVdmRequest
->Title
,
604 CheckVdmRequest
->TitleLen
,
605 sizeof(*CheckVdmRequest
->Title
))
606 || !CsrValidateMessageBuffer(ApiMessage
,
607 (PVOID
*)&CheckVdmRequest
->Reserved
,
608 CheckVdmRequest
->ReservedLen
,
609 sizeof(*CheckVdmRequest
->Reserved
)))
611 return STATUS_INVALID_PARAMETER
;
614 CriticalSection
= (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
615 ? &DosCriticalSection
616 : &WowCriticalSection
;
618 /* Enter the critical section */
619 RtlEnterCriticalSection(CriticalSection
);
621 /* Check if this is a DOS or WOW VDM */
622 if (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
624 /* Get the console record */
625 Status
= BaseSrvGetConsoleRecord(CheckVdmRequest
->ConsoleHandle
,
628 if (!NT_SUCCESS(Status
))
630 /* Allocate a new console record */
631 ConsoleRecord
= (PVDM_CONSOLE_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
633 sizeof(VDM_CONSOLE_RECORD
));
634 if (ConsoleRecord
== NULL
)
636 Status
= STATUS_NO_MEMORY
;
640 /* Remember that the console record was allocated here */
641 NewConsoleRecord
= TRUE
;
643 /* Initialize the console record */
644 ConsoleRecord
->ConsoleHandle
= CheckVdmRequest
->ConsoleHandle
;
645 ConsoleRecord
->ProcessHandle
= NULL
;
646 ConsoleRecord
->ServerEvent
= ConsoleRecord
->ClientEvent
= NULL
;
647 ConsoleRecord
->ReenterCount
= 0;
648 ConsoleRecord
->CurrentDirs
= NULL
;
649 ConsoleRecord
->CurDirsLength
= 0;
650 ConsoleRecord
->SessionId
= GetNextDosSesId();
651 InitializeListHead(&ConsoleRecord
->DosListHead
);
654 /* Allocate a new DOS record */
655 DosRecord
= (PVDM_DOS_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
657 sizeof(VDM_DOS_RECORD
));
658 if (DosRecord
== NULL
)
660 Status
= STATUS_NO_MEMORY
;
664 /* Initialize the DOS record */
665 DosRecord
->State
= VDM_NOT_LOADED
;
666 DosRecord
->ExitCode
= 0;
668 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
, &DosRecord
->ClientEvent
);
669 if (!NT_SUCCESS(Status
)) goto Cleanup
;
671 /* Return the client event handle */
672 CheckVdmRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
674 /* Translate the input structure into a VDM command structure and set it in the DOS record */
675 if (!BaseSrvCopyCommand(CheckVdmRequest
, DosRecord
))
677 /* The only possibility is that an allocation failure occurred */
678 Status
= STATUS_NO_MEMORY
;
682 /* Add the DOS record */
683 InsertHeadList(&ConsoleRecord
->DosListHead
, &DosRecord
->Entry
);
685 if (ConsoleRecord
->ServerEvent
)
687 /* Signal the session event */
688 NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
691 if (NewConsoleRecord
)
693 /* Add the console record */
694 InsertTailList(&VDMConsoleListHead
, &ConsoleRecord
->Entry
);
697 if (ConsoleRecord
->ConsoleHandle
== NULL
)
699 /* The parent doesn't have a console, so return the session ID */
700 CheckVdmRequest
->iTask
= ConsoleRecord
->SessionId
;
702 else CheckVdmRequest
->iTask
= 0;
704 CheckVdmRequest
->VDMState
= NewConsoleRecord
? VDM_NOT_LOADED
: VDM_READY
;
705 Status
= STATUS_SUCCESS
;
709 // TODO: NOT IMPLEMENTED
711 Status
= STATUS_NOT_IMPLEMENTED
;
715 /* Check if it failed */
716 if (!NT_SUCCESS(Status
))
718 /* Free the DOS record */
719 if (DosRecord
!= NULL
)
721 if (DosRecord
->ServerEvent
) NtClose(DosRecord
->ServerEvent
);
722 if (DosRecord
->ClientEvent
)
724 /* Close the remote handle */
725 NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
726 DosRecord
->ClientEvent
,
731 DUPLICATE_CLOSE_SOURCE
);
734 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
738 /* Free the console record if it was allocated here */
739 if (NewConsoleRecord
)
741 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
742 ConsoleRecord
= NULL
;
746 /* Leave the critical section */
747 RtlLeaveCriticalSection(CriticalSection
);
752 CSR_API(BaseSrvUpdateVDMEntry
)
755 PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.UpdateVDMEntryRequest
;
756 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
757 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
758 PVDM_DOS_RECORD DosRecord
= NULL
;
760 CriticalSection
= (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
761 ? &DosCriticalSection
762 : &WowCriticalSection
;
764 /* Enter the critical section */
765 RtlEnterCriticalSection(CriticalSection
);
767 /* Check if this is a DOS or WOW VDM */
768 if (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
770 if (UpdateVdmEntryRequest
->iTask
!= 0)
772 /* Get the console record using the task ID */
773 Status
= GetConsoleRecordBySessionId(UpdateVdmEntryRequest
->iTask
,
778 /* Get the console record using the console handle */
779 Status
= BaseSrvGetConsoleRecord(UpdateVdmEntryRequest
->ConsoleHandle
,
783 if (!NT_SUCCESS(Status
)) goto Cleanup
;
785 /* Get the primary DOS record */
786 DosRecord
= (PVDM_DOS_RECORD
)CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
790 switch (UpdateVdmEntryRequest
->EntryIndex
)
794 /* Close the server event handle, the client will close the client handle */
795 NtClose(DosRecord
->ServerEvent
);
796 DosRecord
->ServerEvent
= DosRecord
->ClientEvent
= NULL
;
798 if (UpdateVdmEntryRequest
->VDMCreationState
& (VDM_UNDO_PARTIAL
| VDM_UNDO_FULL
))
800 /* Remove the DOS record */
801 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
802 RemoveEntryList(&DosRecord
->Entry
);
803 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
806 * Since this is an undo, if that was the only DOS record the VDM
807 * won't even start, so the console record should be removed too.
809 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
811 if (ConsoleRecord
->ProcessHandle
) NtClose(ConsoleRecord
->ProcessHandle
);
812 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
813 RemoveEntryList(&ConsoleRecord
->Entry
);
814 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
818 /* It was successful */
819 Status
= STATUS_SUCCESS
;
824 case VdmEntryUpdateProcess
:
826 /* Duplicate the VDM process handle */
827 Status
= NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
828 UpdateVdmEntryRequest
->VDMProcessHandle
,
830 &ConsoleRecord
->ProcessHandle
,
833 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
834 if (!NT_SUCCESS(Status
)) goto Cleanup
;
836 /* Create a pair of handles to one event object */
837 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
,
838 &DosRecord
->ClientEvent
);
839 if (!NT_SUCCESS(Status
)) goto Cleanup
;
841 /* Return the client event handle */
842 UpdateVdmEntryRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
847 case VdmEntryUpdateControlCHandler
:
849 // TODO: NOT IMPLEMENTED
850 DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!");
851 Status
= STATUS_NOT_IMPLEMENTED
;
859 Status
= STATUS_INVALID_PARAMETER
;
865 // TODO: NOT IMPLEMENTED
867 Status
= STATUS_NOT_IMPLEMENTED
;
871 /* Leave the critical section */
872 RtlLeaveCriticalSection(CriticalSection
);
877 CSR_API(BaseSrvGetNextVDMCommand
)
880 PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest
=
881 &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetNextVDMCommandRequest
;
882 PRTL_CRITICAL_SECTION CriticalSection
;
883 PLIST_ENTRY i
= NULL
;
884 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
885 PVDM_DOS_RECORD DosRecord
= NULL
;
887 /* Validate the message buffers */
888 if (!CsrValidateMessageBuffer(ApiMessage
,
889 (PVOID
*)&GetNextVdmCommandRequest
->CmdLine
,
890 GetNextVdmCommandRequest
->CmdLen
,
891 sizeof(*GetNextVdmCommandRequest
->CmdLine
))
892 || !CsrValidateMessageBuffer(ApiMessage
,
893 (PVOID
*)&GetNextVdmCommandRequest
->AppName
,
894 GetNextVdmCommandRequest
->AppLen
,
895 sizeof(*GetNextVdmCommandRequest
->AppName
))
896 || !CsrValidateMessageBuffer(ApiMessage
,
897 (PVOID
*)&GetNextVdmCommandRequest
->PifFile
,
898 GetNextVdmCommandRequest
->PifLen
,
899 sizeof(*GetNextVdmCommandRequest
->PifFile
))
900 || !CsrValidateMessageBuffer(ApiMessage
,
901 (PVOID
*)&GetNextVdmCommandRequest
->CurDirectory
,
902 GetNextVdmCommandRequest
->CurDirectoryLen
,
903 sizeof(*GetNextVdmCommandRequest
->CurDirectory
))
904 || !CsrValidateMessageBuffer(ApiMessage
,
905 (PVOID
*)&GetNextVdmCommandRequest
->Env
,
906 GetNextVdmCommandRequest
->EnvLen
,
907 sizeof(*GetNextVdmCommandRequest
->Env
))
908 || !CsrValidateMessageBuffer(ApiMessage
,
909 (PVOID
*)&GetNextVdmCommandRequest
->Desktop
,
910 GetNextVdmCommandRequest
->DesktopLen
,
911 sizeof(*GetNextVdmCommandRequest
->Desktop
))
912 || !CsrValidateMessageBuffer(ApiMessage
,
913 (PVOID
*)&GetNextVdmCommandRequest
->Title
,
914 GetNextVdmCommandRequest
->TitleLen
,
915 sizeof(*GetNextVdmCommandRequest
->Title
))
916 || !CsrValidateMessageBuffer(ApiMessage
,
917 (PVOID
*)&GetNextVdmCommandRequest
->Reserved
,
918 GetNextVdmCommandRequest
->ReservedLen
,
919 sizeof(*GetNextVdmCommandRequest
->Reserved
))
920 || !CsrValidateMessageBuffer(ApiMessage
,
921 (PVOID
*)&GetNextVdmCommandRequest
->StartupInfo
,
923 sizeof(STARTUPINFOA
)))
925 return STATUS_INVALID_PARAMETER
;
928 CriticalSection
= (GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
)
929 ? &WowCriticalSection
930 : &DosCriticalSection
;
932 /* Enter the critical section */
933 RtlEnterCriticalSection(CriticalSection
);
935 if (!(GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
))
937 if (GetNextVdmCommandRequest
->iTask
!= 0)
939 /* Get the console record using the task ID */
940 Status
= GetConsoleRecordBySessionId(GetNextVdmCommandRequest
->iTask
,
945 /* Get the console record using the console handle */
946 Status
= BaseSrvGetConsoleRecord(GetNextVdmCommandRequest
->ConsoleHandle
,
950 /* Make sure we found the console record */
951 if (!NT_SUCCESS(Status
)) goto Cleanup
;
953 /* Return the session ID */
954 GetNextVdmCommandRequest
->iTask
= ConsoleRecord
->SessionId
;
955 GetNextVdmCommandRequest
->WaitObjectForVDM
= NULL
;
957 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_FIRST_COMMAND
)
959 /* Check if the DOS record list is empty */
960 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
962 Status
= STATUS_INVALID_PARAMETER
;
966 /* Get the first DOS record */
967 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
, VDM_DOS_RECORD
, Entry
);
969 /* Make sure its command information is still there */
970 if (DosRecord
->CommandInfo
== NULL
)
972 Status
= STATUS_INVALID_PARAMETER
;
976 /* Fill the command information */
977 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
981 /* Check if we should set the state of a running DOS record to ready */
982 if (!(GetNextVdmCommandRequest
->VDMState
983 & (VDM_FLAG_FIRST_TASK
| VDM_FLAG_RETRY
| VDM_FLAG_NESTED_TASK
)))
985 /* Search for a DOS record that is currently running */
986 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
988 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
989 if (DosRecord
->State
== VDM_NOT_READY
) break;
992 /* Check if we found any */
993 if (i
== &ConsoleRecord
->DosListHead
)
995 Status
= STATUS_INVALID_PARAMETER
;
999 /* Set the exit code */
1000 DosRecord
->ExitCode
= GetNextVdmCommandRequest
->ExitCode
;
1002 /* Update the VDM state */
1003 DosRecord
->State
= VDM_READY
;
1005 /* Notify all waiting threads that the task is finished */
1006 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
1007 NtClose(DosRecord
->ServerEvent
);
1008 DosRecord
->ServerEvent
= NULL
;
1011 /* Search for a DOS record that isn't loaded yet */
1012 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
1014 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
1015 if (DosRecord
->State
== VDM_NOT_LOADED
) break;
1018 if (i
!= &ConsoleRecord
->DosListHead
)
1020 /* DOS tasks which haven't been loaded yet should have a command info structure */
1021 ASSERT(DosRecord
->CommandInfo
!= NULL
);
1023 /* Check if the caller only wants environment data */
1024 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_ENVIRONMENT
)
1026 if (GetNextVdmCommandRequest
->EnvLen
< DosRecord
->CommandInfo
->EnvLen
)
1028 /* Not enough space was reserved */
1029 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
1030 Status
= STATUS_BUFFER_OVERFLOW
;
1034 /* Copy the environment data */
1035 RtlMoveMemory(GetNextVdmCommandRequest
->Env
,
1036 DosRecord
->CommandInfo
->Env
,
1037 DosRecord
->CommandInfo
->EnvLen
);
1039 /* Return the actual size to the caller */
1040 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
1044 /* Fill the command information */
1045 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
1046 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1048 /* Free the command information, it's no longer needed */
1049 BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1050 DosRecord
->CommandInfo
= NULL
;
1052 /* Update the VDM state */
1053 GetNextVdmCommandRequest
->VDMState
= DosRecord
->State
= VDM_NOT_READY
;
1056 Status
= STATUS_SUCCESS
;
1062 // TODO: WOW SUPPORT NOT IMPLEMENTED
1063 Status
= STATUS_NOT_IMPLEMENTED
;
1067 /* There is no command yet */
1068 if ((GetNextVdmCommandRequest
->VDMState
& (VDM_FLAG_DONT_WAIT
| VDM_FLAG_RETRY
))
1069 != (VDM_FLAG_DONT_WAIT
| VDM_FLAG_RETRY
))
1071 if (ConsoleRecord
->ServerEvent
)
1073 /* Reset the event */
1074 NtResetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1078 /* Create a pair of wait handles */
1079 Status
= BaseSrvCreatePairWaitHandles(&ConsoleRecord
->ServerEvent
,
1080 &ConsoleRecord
->ClientEvent
);
1081 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1084 /* Return the client event handle */
1085 GetNextVdmCommandRequest
->WaitObjectForVDM
= ConsoleRecord
->ClientEvent
;
1089 /* Leave the critical section */
1090 RtlLeaveCriticalSection(CriticalSection
);
1095 CSR_API(BaseSrvExitVDM
)
1098 PBASE_EXIT_VDM ExitVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitVDMRequest
;
1099 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
1100 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1101 PVDM_DOS_RECORD DosRecord
;
1103 CriticalSection
= (ExitVdmRequest
->iWowTask
== 0)
1104 ? &DosCriticalSection
1105 : &WowCriticalSection
;
1107 /* Enter the critical section */
1108 RtlEnterCriticalSection(CriticalSection
);
1110 if (ExitVdmRequest
->iWowTask
== 0)
1112 /* Get the console record */
1113 Status
= BaseSrvGetConsoleRecord(ExitVdmRequest
->ConsoleHandle
, &ConsoleRecord
);
1114 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1116 /* Cleanup the DOS records */
1117 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
1119 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
1123 /* Set the event and close it */
1124 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
1125 NtClose(DosRecord
->ServerEvent
);
1127 /* Remove the DOS entry */
1128 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1129 RemoveEntryList(&DosRecord
->Entry
);
1130 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1133 if (ConsoleRecord
->CurrentDirs
!= NULL
)
1135 /* Free the current directories */
1136 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
1137 ConsoleRecord
->CurrentDirs
= NULL
;
1138 ConsoleRecord
->CurDirsLength
= 0;
1141 /* Close the event handle */
1142 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
1144 /* Remove the console record */
1145 RemoveEntryList(&ConsoleRecord
->Entry
);
1146 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
1150 // TODO: NOT IMPLEMENTED
1152 Status
= STATUS_NOT_IMPLEMENTED
;
1156 /* Leave the critical section */
1157 RtlLeaveCriticalSection(CriticalSection
);
1162 CSR_API(BaseSrvIsFirstVDM
)
1164 PBASE_IS_FIRST_VDM IsFirstVDMRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.IsFirstVDMRequest
;
1166 /* Return the result */
1167 IsFirstVDMRequest
->FirstVDM
= FirstVDM
;
1169 /* Clear the first VDM flag */
1172 return STATUS_SUCCESS
;
1175 CSR_API(BaseSrvGetVDMExitCode
)
1178 PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetVDMExitCodeRequest
;
1179 PLIST_ENTRY i
= NULL
;
1180 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1181 PVDM_DOS_RECORD DosRecord
= NULL
;
1183 /* Enter the critical section */
1184 RtlEnterCriticalSection(&DosCriticalSection
);
1186 /* Get the console record */
1187 Status
= BaseSrvGetConsoleRecord(GetVDMExitCodeRequest
->ConsoleHandle
, &ConsoleRecord
);
1188 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1190 /* Search for a DOS record that has the same parent process handle */
1191 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
1193 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
1194 if (DosRecord
->ClientEvent
== GetVDMExitCodeRequest
->hParent
) break;
1197 /* Check if no DOS record was found */
1198 if (i
== &ConsoleRecord
->DosListHead
)
1200 Status
= STATUS_NOT_FOUND
;
1204 /* Check if this task is still running */
1205 if (DosRecord
->State
== VDM_READY
)
1207 GetVDMExitCodeRequest
->ExitCode
= STATUS_PENDING
;
1211 /* Return the exit code */
1212 GetVDMExitCodeRequest
->ExitCode
= DosRecord
->ExitCode
;
1214 /* Since this is a zombie task record, remove it */
1215 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1216 RemoveEntryList(&DosRecord
->Entry
);
1217 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1220 /* Leave the critical section */
1221 RtlLeaveCriticalSection(&DosCriticalSection
);
1226 CSR_API(BaseSrvSetReenterCount
)
1228 NTSTATUS Status
= STATUS_SUCCESS
;
1229 PBASE_SET_REENTER_COUNT SetReenterCountRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetReenterCountRequest
;
1230 PVDM_CONSOLE_RECORD ConsoleRecord
;
1232 /* Enter the critical section */
1233 RtlEnterCriticalSection(&DosCriticalSection
);
1235 /* Get the console record */
1236 Status
= BaseSrvGetConsoleRecord(SetReenterCountRequest
->ConsoleHandle
, &ConsoleRecord
);
1237 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1239 if (SetReenterCountRequest
->fIncDec
== VDM_INC_REENTER_COUNT
) ConsoleRecord
->ReenterCount
++;
1240 else if (SetReenterCountRequest
->fIncDec
== VDM_DEC_REENTER_COUNT
)
1242 ConsoleRecord
->ReenterCount
--;
1243 if (ConsoleRecord
->ServerEvent
!= NULL
) NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1245 else Status
= STATUS_INVALID_PARAMETER
;
1248 /* Leave the critical section */
1249 RtlLeaveCriticalSection(&DosCriticalSection
);
1254 CSR_API(BaseSrvSetVDMCurDirs
)
1257 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1258 PVDM_CONSOLE_RECORD ConsoleRecord
;
1259 PCHAR Buffer
= NULL
;
1261 /* Validate the input buffer */
1262 if (!CsrValidateMessageBuffer(ApiMessage
,
1263 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1264 VDMCurrentDirsRequest
->cchCurDirs
,
1265 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1267 return STATUS_INVALID_PARAMETER
;
1270 /* Enter the critical section */
1271 RtlEnterCriticalSection(&DosCriticalSection
);
1273 /* Find the console record */
1274 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1275 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1277 if (ConsoleRecord
->CurrentDirs
== NULL
)
1279 /* Allocate memory for the current directory information */
1280 Buffer
= RtlAllocateHeap(BaseSrvHeap
,
1282 VDMCurrentDirsRequest
->cchCurDirs
);
1286 /* Resize the amount of allocated memory */
1287 Buffer
= RtlReAllocateHeap(BaseSrvHeap
,
1289 ConsoleRecord
->CurrentDirs
,
1290 VDMCurrentDirsRequest
->cchCurDirs
);
1295 /* Allocation failed */
1296 Status
= STATUS_NO_MEMORY
;
1300 /* Update the console record */
1301 ConsoleRecord
->CurrentDirs
= Buffer
;
1302 ConsoleRecord
->CurDirsLength
= VDMCurrentDirsRequest
->cchCurDirs
;
1305 RtlMoveMemory(ConsoleRecord
->CurrentDirs
,
1306 VDMCurrentDirsRequest
->lpszzCurDirs
,
1307 VDMCurrentDirsRequest
->cchCurDirs
);
1310 /* Leave the critical section */
1311 RtlLeaveCriticalSection(&DosCriticalSection
);
1316 CSR_API(BaseSrvGetVDMCurDirs
)
1319 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1320 PVDM_CONSOLE_RECORD ConsoleRecord
;
1322 /* Validate the output buffer */
1323 if (!CsrValidateMessageBuffer(ApiMessage
,
1324 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1325 VDMCurrentDirsRequest
->cchCurDirs
,
1326 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1328 return STATUS_INVALID_PARAMETER
;
1331 /* Enter the critical section */
1332 RtlEnterCriticalSection(&DosCriticalSection
);
1334 /* Find the console record */
1335 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1336 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1338 /* Return the actual size of the current directory information */
1339 VDMCurrentDirsRequest
->cchCurDirs
= ConsoleRecord
->CurDirsLength
;
1341 /* Check if the buffer is large enough */
1342 if (VDMCurrentDirsRequest
->cchCurDirs
< ConsoleRecord
->CurDirsLength
)
1344 Status
= STATUS_BUFFER_TOO_SMALL
;
1349 RtlMoveMemory(VDMCurrentDirsRequest
->lpszzCurDirs
,
1350 ConsoleRecord
->CurrentDirs
,
1351 ConsoleRecord
->CurDirsLength
);
1354 /* Leave the critical section */
1355 RtlLeaveCriticalSection(&DosCriticalSection
);
1360 CSR_API(BaseSrvBatNotification
)
1362 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1363 return STATUS_NOT_IMPLEMENTED
;
1366 CSR_API(BaseSrvRegisterWowExec
)
1368 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1369 return STATUS_NOT_IMPLEMENTED
;
1372 CSR_API(BaseSrvRefreshIniFileMapping
)
1374 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1375 return STATUS_NOT_IMPLEMENTED
;