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
);
233 BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess
)
235 ULONG ProcessId
= HandleToUlong(CsrProcess
->ClientId
.UniqueProcess
);
236 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
237 PVDM_DOS_RECORD DosRecord
;
240 /* Enter the critical section */
241 RtlEnterCriticalSection(&DosCriticalSection
);
243 /* Search for a record that has the same process handle */
244 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
246 ConsoleRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
248 if (ConsoleRecord
->ProcessId
== ProcessId
)
250 /* Cleanup the DOS records */
251 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
253 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
257 /* Set the event and close it */
258 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
259 NtClose(DosRecord
->ServerEvent
);
261 /* Remove the DOS entry */
262 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
263 RemoveEntryList(&DosRecord
->Entry
);
264 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
267 if (ConsoleRecord
->CurrentDirs
!= NULL
)
269 /* Free the current directories */
270 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
271 ConsoleRecord
->CurrentDirs
= NULL
;
272 ConsoleRecord
->CurDirsLength
= 0;
275 /* Close the process handle */
276 if (ConsoleRecord
->ProcessHandle
) NtClose(ConsoleRecord
->ProcessHandle
);
278 /* Close the event handle */
279 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
281 /* Remove the console record */
283 RemoveEntryList(&ConsoleRecord
->Entry
);
284 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
288 /* Leave the critical section */
289 RtlLeaveCriticalSection(&DosCriticalSection
);
292 BOOLEAN NTAPI
BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest
, PVDM_DOS_RECORD DosRecord
)
294 BOOLEAN Success
= FALSE
;
295 PVDM_COMMAND_INFO CommandInfo
= NULL
;
297 /* Allocate the command information structure */
298 CommandInfo
= (PVDM_COMMAND_INFO
)RtlAllocateHeap(BaseSrvHeap
,
300 sizeof(VDM_COMMAND_INFO
));
301 if (CommandInfo
== NULL
) return FALSE
;
303 /* Fill the structure */
304 CommandInfo
->TaskId
= CheckVdmRequest
->iTask
;
305 CommandInfo
->ExitCode
= DosRecord
->ExitCode
;
306 CommandInfo
->CodePage
= CheckVdmRequest
->CodePage
;
307 CommandInfo
->StdIn
= CheckVdmRequest
->StdIn
;
308 CommandInfo
->StdOut
= CheckVdmRequest
->StdOut
;
309 CommandInfo
->StdErr
= CheckVdmRequest
->StdErr
;
311 /* Allocate memory for the command line */
312 CommandInfo
->CmdLine
= RtlAllocateHeap(BaseSrvHeap
,
314 CheckVdmRequest
->CmdLen
);
315 if (CommandInfo
->CmdLine
== NULL
) goto Cleanup
;
317 /* Copy the command line */
318 RtlMoveMemory(CommandInfo
->CmdLine
, CheckVdmRequest
->CmdLine
, CheckVdmRequest
->CmdLen
);
320 /* Allocate memory for the application name */
321 CommandInfo
->AppName
= RtlAllocateHeap(BaseSrvHeap
,
323 CheckVdmRequest
->AppLen
);
324 if (CommandInfo
->AppName
== NULL
) goto Cleanup
;
326 /* Copy the application name */
327 RtlMoveMemory(CommandInfo
->AppName
, CheckVdmRequest
->AppName
, CheckVdmRequest
->AppLen
);
329 /* Allocate memory for the PIF file name */
330 if (CheckVdmRequest
->PifLen
!= 0)
332 CommandInfo
->PifFile
= RtlAllocateHeap(BaseSrvHeap
,
334 CheckVdmRequest
->PifLen
);
335 if (CommandInfo
->PifFile
== NULL
) goto Cleanup
;
337 /* Copy the PIF file name */
338 RtlMoveMemory(CommandInfo
->PifFile
, CheckVdmRequest
->PifFile
, CheckVdmRequest
->PifLen
);
340 else CommandInfo
->PifFile
= NULL
;
342 /* Allocate memory for the current directory */
343 if (CheckVdmRequest
->CurDirectoryLen
!= 0)
345 CommandInfo
->CurDirectory
= RtlAllocateHeap(BaseSrvHeap
,
347 CheckVdmRequest
->CurDirectoryLen
);
348 if (CommandInfo
->CurDirectory
== NULL
) goto Cleanup
;
350 /* Copy the current directory */
351 RtlMoveMemory(CommandInfo
->CurDirectory
,
352 CheckVdmRequest
->CurDirectory
,
353 CheckVdmRequest
->CurDirectoryLen
);
355 else CommandInfo
->CurDirectory
= NULL
;
357 /* Allocate memory for the environment block */
358 CommandInfo
->Env
= RtlAllocateHeap(BaseSrvHeap
,
360 CheckVdmRequest
->EnvLen
);
361 if (CommandInfo
->Env
== NULL
) goto Cleanup
;
363 /* Copy the environment block */
364 RtlMoveMemory(CommandInfo
->Env
, CheckVdmRequest
->Env
, CheckVdmRequest
->EnvLen
);
366 CommandInfo
->EnvLen
= CheckVdmRequest
->EnvLen
;
367 RtlMoveMemory(&CommandInfo
->StartupInfo
,
368 CheckVdmRequest
->StartupInfo
,
369 sizeof(STARTUPINFOA
));
371 /* Allocate memory for the desktop */
372 if (CheckVdmRequest
->DesktopLen
!= 0)
374 CommandInfo
->Desktop
= RtlAllocateHeap(BaseSrvHeap
,
376 CheckVdmRequest
->DesktopLen
);
377 if (CommandInfo
->Desktop
== NULL
) goto Cleanup
;
379 /* Copy the desktop name */
380 RtlMoveMemory(CommandInfo
->Desktop
, CheckVdmRequest
->Desktop
, CheckVdmRequest
->DesktopLen
);
382 else CommandInfo
->Desktop
= NULL
;
384 CommandInfo
->DesktopLen
= CheckVdmRequest
->DesktopLen
;
386 /* Allocate memory for the title */
387 if (CheckVdmRequest
->TitleLen
!= 0)
389 CommandInfo
->Title
= RtlAllocateHeap(BaseSrvHeap
,
391 CheckVdmRequest
->TitleLen
);
392 if (CommandInfo
->Title
== NULL
) goto Cleanup
;
395 RtlMoveMemory(CommandInfo
->Title
, CheckVdmRequest
->Title
, CheckVdmRequest
->TitleLen
);
397 else CommandInfo
->Title
= NULL
;
399 CommandInfo
->TitleLen
= CheckVdmRequest
->TitleLen
;
401 /* Allocate memory for the reserved field */
402 if (CheckVdmRequest
->ReservedLen
!= 0)
404 CommandInfo
->Reserved
= RtlAllocateHeap(BaseSrvHeap
,
406 CheckVdmRequest
->ReservedLen
);
407 if (CommandInfo
->Reserved
== NULL
) goto Cleanup
;
409 /* Copy the reserved field */
410 RtlMoveMemory(CommandInfo
->Reserved
,
411 CheckVdmRequest
->Reserved
,
412 CheckVdmRequest
->ReservedLen
);
414 else CommandInfo
->Reserved
= NULL
;
416 CommandInfo
->ReservedLen
= CheckVdmRequest
->ReservedLen
;
418 CommandInfo
->CmdLen
= CheckVdmRequest
->CmdLen
;
419 CommandInfo
->AppLen
= CheckVdmRequest
->AppLen
;
420 CommandInfo
->PifLen
= CheckVdmRequest
->PifLen
;
421 CommandInfo
->CurDirectoryLen
= CheckVdmRequest
->CurDirectoryLen
;
422 CommandInfo
->VDMState
= DosRecord
->State
;
423 // TODO: Set CommandInfo->CurrentDrive
424 // TODO: Set CommandInfo->ComingFromBat
426 /* Set the DOS record's command structure */
427 DosRecord
->CommandInfo
= CommandInfo
;
429 /* The operation was successful */
433 /* If it wasn't successful, free the memory */
434 if (!Success
) BaseSrvFreeVDMInfo(CommandInfo
);
439 NTSTATUS NTAPI
BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo
,
440 PBASE_GET_NEXT_VDM_COMMAND Message
)
442 NTSTATUS Status
= STATUS_SUCCESS
;
445 Message
->iTask
= CommandInfo
->TaskId
;
446 Message
->StdIn
= CommandInfo
->StdIn
;
447 Message
->StdOut
= CommandInfo
->StdOut
;
448 Message
->StdErr
= CommandInfo
->StdErr
;
449 Message
->CodePage
= CommandInfo
->CodePage
;
450 Message
->dwCreationFlags
= CommandInfo
->CreationFlags
;
451 Message
->ExitCode
= CommandInfo
->ExitCode
;
452 Message
->CurrentDrive
= CommandInfo
->CurrentDrive
;
453 Message
->VDMState
= CommandInfo
->VDMState
;
454 Message
->fComingFromBat
= CommandInfo
->ComingFromBat
;
456 if (CommandInfo
->CmdLen
&& Message
->CmdLen
)
458 if (Message
->CmdLen
>= CommandInfo
->CmdLen
)
460 /* Copy the command line */
461 RtlMoveMemory(Message
->CmdLine
, CommandInfo
->CmdLine
, CommandInfo
->CmdLen
);
463 else Status
= STATUS_BUFFER_TOO_SMALL
;
465 Message
->CmdLen
= CommandInfo
->CmdLen
;
468 if (CommandInfo
->AppLen
&& Message
->AppLen
)
470 if (Message
->AppLen
>= CommandInfo
->AppLen
)
472 /* Copy the application name */
473 RtlMoveMemory(Message
->AppName
, CommandInfo
->AppName
, CommandInfo
->AppLen
);
475 else Status
= STATUS_BUFFER_TOO_SMALL
;
477 Message
->AppLen
= CommandInfo
->AppLen
;
480 if (CommandInfo
->PifLen
&& Message
->PifLen
)
482 if (Message
->PifLen
>= CommandInfo
->PifLen
)
484 /* Copy the PIF file name */
485 RtlMoveMemory(Message
->PifFile
, CommandInfo
->PifFile
, CommandInfo
->PifLen
);
487 else Status
= STATUS_BUFFER_TOO_SMALL
;
489 Message
->PifLen
= CommandInfo
->PifLen
;
492 if (CommandInfo
->CurDirectoryLen
&& Message
->CurDirectoryLen
)
494 if (Message
->CurDirectoryLen
>= CommandInfo
->CurDirectoryLen
)
496 /* Copy the current directory */
497 RtlMoveMemory(Message
->CurDirectory
, CommandInfo
->CurDirectory
, CommandInfo
->CurDirectoryLen
);
499 else Status
= STATUS_BUFFER_TOO_SMALL
;
501 Message
->CurDirectoryLen
= CommandInfo
->CurDirectoryLen
;
504 if (CommandInfo
->EnvLen
&& Message
->EnvLen
)
506 if (Message
->EnvLen
>= CommandInfo
->EnvLen
)
508 /* Copy the environment */
509 RtlMoveMemory(Message
->Env
, CommandInfo
->Env
, CommandInfo
->EnvLen
);
511 else Status
= STATUS_BUFFER_TOO_SMALL
;
513 Message
->EnvLen
= CommandInfo
->EnvLen
;
516 /* Copy the startup info */
517 RtlMoveMemory(Message
->StartupInfo
,
518 &CommandInfo
->StartupInfo
,
519 sizeof(STARTUPINFOA
));
521 if (CommandInfo
->DesktopLen
&& Message
->DesktopLen
)
523 if (Message
->DesktopLen
>= CommandInfo
->DesktopLen
)
525 /* Copy the desktop name */
526 RtlMoveMemory(Message
->Desktop
, CommandInfo
->Desktop
, CommandInfo
->DesktopLen
);
528 else Status
= STATUS_BUFFER_TOO_SMALL
;
530 Message
->DesktopLen
= CommandInfo
->DesktopLen
;
533 if (CommandInfo
->TitleLen
&& Message
->TitleLen
)
535 if (Message
->TitleLen
>= CommandInfo
->TitleLen
)
538 RtlMoveMemory(Message
->Title
, CommandInfo
->Title
, CommandInfo
->TitleLen
);
540 else Status
= STATUS_BUFFER_TOO_SMALL
;
542 Message
->TitleLen
= CommandInfo
->TitleLen
;
545 if (CommandInfo
->ReservedLen
&& Message
->ReservedLen
)
547 if (Message
->ReservedLen
>= CommandInfo
->ReservedLen
)
549 /* Copy the reserved parameter */
550 RtlMoveMemory(Message
->Reserved
, CommandInfo
->Reserved
, CommandInfo
->ReservedLen
);
552 else Status
= STATUS_BUFFER_TOO_SMALL
;
554 Message
->ReservedLen
= CommandInfo
->ReservedLen
;
560 VOID NTAPI
BaseInitializeVDM(VOID
)
562 /* Initialize the list head */
563 InitializeListHead(&VDMConsoleListHead
);
565 /* Initialize the critical section */
566 RtlInitializeCriticalSection(&DosCriticalSection
);
567 RtlInitializeCriticalSection(&WowCriticalSection
);
570 /* PUBLIC SERVER APIS *********************************************************/
572 CSR_API(BaseSrvCheckVDM
)
575 PBASE_CHECK_VDM CheckVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CheckVDMRequest
;
576 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
577 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
578 PVDM_DOS_RECORD DosRecord
= NULL
;
579 BOOLEAN NewConsoleRecord
= FALSE
;
581 /* Don't do anything if the VDM has been disabled in the registry */
582 if (!BaseSrvIsVdmAllowed()) return STATUS_VDM_DISALLOWED
;
584 /* Validate the message buffers */
585 if (!CsrValidateMessageBuffer(ApiMessage
,
586 (PVOID
*)&CheckVdmRequest
->CmdLine
,
587 CheckVdmRequest
->CmdLen
,
588 sizeof(*CheckVdmRequest
->CmdLine
))
589 || !CsrValidateMessageBuffer(ApiMessage
,
590 (PVOID
*)&CheckVdmRequest
->AppName
,
591 CheckVdmRequest
->AppLen
,
592 sizeof(*CheckVdmRequest
->AppName
))
593 || !CsrValidateMessageBuffer(ApiMessage
,
594 (PVOID
*)&CheckVdmRequest
->PifFile
,
595 CheckVdmRequest
->PifLen
,
596 sizeof(*CheckVdmRequest
->PifFile
))
597 || !CsrValidateMessageBuffer(ApiMessage
,
598 (PVOID
*)&CheckVdmRequest
->CurDirectory
,
599 CheckVdmRequest
->CurDirectoryLen
,
600 sizeof(*CheckVdmRequest
->CurDirectory
))
601 || !CsrValidateMessageBuffer(ApiMessage
,
602 (PVOID
*)&CheckVdmRequest
->Desktop
,
603 CheckVdmRequest
->DesktopLen
,
604 sizeof(*CheckVdmRequest
->Desktop
))
605 || !CsrValidateMessageBuffer(ApiMessage
,
606 (PVOID
*)&CheckVdmRequest
->Title
,
607 CheckVdmRequest
->TitleLen
,
608 sizeof(*CheckVdmRequest
->Title
))
609 || !CsrValidateMessageBuffer(ApiMessage
,
610 (PVOID
*)&CheckVdmRequest
->Reserved
,
611 CheckVdmRequest
->ReservedLen
,
612 sizeof(*CheckVdmRequest
->Reserved
)))
614 return STATUS_INVALID_PARAMETER
;
617 CriticalSection
= (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
618 ? &DosCriticalSection
619 : &WowCriticalSection
;
621 /* Enter the critical section */
622 RtlEnterCriticalSection(CriticalSection
);
624 /* Check if this is a DOS or WOW VDM */
625 if (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
627 /* Get the console record */
628 Status
= BaseSrvGetConsoleRecord(CheckVdmRequest
->ConsoleHandle
,
631 if (!NT_SUCCESS(Status
))
633 /* Allocate a new console record */
634 ConsoleRecord
= (PVDM_CONSOLE_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
636 sizeof(VDM_CONSOLE_RECORD
));
637 if (ConsoleRecord
== NULL
)
639 Status
= STATUS_NO_MEMORY
;
643 /* Remember that the console record was allocated here */
644 NewConsoleRecord
= TRUE
;
646 /* Initialize the console record */
647 ConsoleRecord
->ConsoleHandle
= CheckVdmRequest
->ConsoleHandle
;
648 ConsoleRecord
->ProcessHandle
= NULL
;
649 ConsoleRecord
->ServerEvent
= ConsoleRecord
->ClientEvent
= NULL
;
650 ConsoleRecord
->ReenterCount
= 0;
651 ConsoleRecord
->CurrentDirs
= NULL
;
652 ConsoleRecord
->CurDirsLength
= 0;
653 ConsoleRecord
->SessionId
= GetNextDosSesId();
654 InitializeListHead(&ConsoleRecord
->DosListHead
);
657 /* Allocate a new DOS record */
658 DosRecord
= (PVDM_DOS_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
660 sizeof(VDM_DOS_RECORD
));
661 if (DosRecord
== NULL
)
663 Status
= STATUS_NO_MEMORY
;
667 /* Initialize the DOS record */
668 DosRecord
->State
= VDM_NOT_LOADED
;
669 DosRecord
->ExitCode
= 0;
671 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
, &DosRecord
->ClientEvent
);
672 if (!NT_SUCCESS(Status
)) goto Cleanup
;
674 /* Return the client event handle */
675 CheckVdmRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
677 /* Translate the input structure into a VDM command structure and set it in the DOS record */
678 if (!BaseSrvCopyCommand(CheckVdmRequest
, DosRecord
))
680 /* The only possibility is that an allocation failure occurred */
681 Status
= STATUS_NO_MEMORY
;
685 /* Add the DOS record */
686 InsertHeadList(&ConsoleRecord
->DosListHead
, &DosRecord
->Entry
);
688 if (ConsoleRecord
->ServerEvent
)
690 /* Signal the session event */
691 NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
694 if (NewConsoleRecord
)
696 /* Add the console record */
697 InsertTailList(&VDMConsoleListHead
, &ConsoleRecord
->Entry
);
700 if (ConsoleRecord
->ConsoleHandle
== NULL
)
702 /* The parent doesn't have a console, so return the session ID */
703 CheckVdmRequest
->iTask
= ConsoleRecord
->SessionId
;
705 else CheckVdmRequest
->iTask
= 0;
707 CheckVdmRequest
->VDMState
= NewConsoleRecord
? VDM_NOT_LOADED
: VDM_READY
;
708 Status
= STATUS_SUCCESS
;
712 // TODO: NOT IMPLEMENTED
714 Status
= STATUS_NOT_IMPLEMENTED
;
718 /* Check if it failed */
719 if (!NT_SUCCESS(Status
))
721 /* Free the DOS record */
722 if (DosRecord
!= NULL
)
724 if (DosRecord
->ServerEvent
) NtClose(DosRecord
->ServerEvent
);
725 if (DosRecord
->ClientEvent
)
727 /* Close the remote handle */
728 NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
729 DosRecord
->ClientEvent
,
734 DUPLICATE_CLOSE_SOURCE
);
737 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
741 /* Free the console record if it was allocated here */
742 if (NewConsoleRecord
)
744 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
745 ConsoleRecord
= NULL
;
749 /* Leave the critical section */
750 RtlLeaveCriticalSection(CriticalSection
);
755 CSR_API(BaseSrvUpdateVDMEntry
)
758 PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.UpdateVDMEntryRequest
;
759 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
760 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
761 PVDM_DOS_RECORD DosRecord
= NULL
;
763 CriticalSection
= (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
764 ? &DosCriticalSection
765 : &WowCriticalSection
;
767 /* Enter the critical section */
768 RtlEnterCriticalSection(CriticalSection
);
770 /* Check if this is a DOS or WOW VDM */
771 if (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
773 if (UpdateVdmEntryRequest
->iTask
!= 0)
775 /* Get the console record using the task ID */
776 Status
= GetConsoleRecordBySessionId(UpdateVdmEntryRequest
->iTask
,
781 /* Get the console record using the console handle */
782 Status
= BaseSrvGetConsoleRecord(UpdateVdmEntryRequest
->ConsoleHandle
,
786 if (!NT_SUCCESS(Status
)) goto Cleanup
;
788 /* Get the primary DOS record */
789 DosRecord
= (PVDM_DOS_RECORD
)CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
793 switch (UpdateVdmEntryRequest
->EntryIndex
)
797 /* Close the server event handle, the client will close the client handle */
798 NtClose(DosRecord
->ServerEvent
);
799 DosRecord
->ServerEvent
= DosRecord
->ClientEvent
= NULL
;
801 if (UpdateVdmEntryRequest
->VDMCreationState
& (VDM_UNDO_PARTIAL
| VDM_UNDO_FULL
))
803 /* Remove the DOS record */
804 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
805 RemoveEntryList(&DosRecord
->Entry
);
806 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
809 * Since this is an undo, if that was the only DOS record the VDM
810 * won't even start, so the console record should be removed too.
812 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
814 if (ConsoleRecord
->ProcessHandle
) NtClose(ConsoleRecord
->ProcessHandle
);
815 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
816 RemoveEntryList(&ConsoleRecord
->Entry
);
817 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
821 /* It was successful */
822 Status
= STATUS_SUCCESS
;
827 case VdmEntryUpdateProcess
:
829 /* Duplicate the VDM process handle */
830 Status
= NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
831 UpdateVdmEntryRequest
->VDMProcessHandle
,
833 &ConsoleRecord
->ProcessHandle
,
836 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
837 if (!NT_SUCCESS(Status
)) goto Cleanup
;
839 /* Create a pair of handles to one event object */
840 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
,
841 &DosRecord
->ClientEvent
);
842 if (!NT_SUCCESS(Status
)) goto Cleanup
;
844 /* Return the client event handle */
845 UpdateVdmEntryRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
850 case VdmEntryUpdateControlCHandler
:
852 // TODO: NOT IMPLEMENTED
853 DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!");
854 Status
= STATUS_NOT_IMPLEMENTED
;
862 Status
= STATUS_INVALID_PARAMETER
;
868 // TODO: NOT IMPLEMENTED
870 Status
= STATUS_NOT_IMPLEMENTED
;
874 /* Leave the critical section */
875 RtlLeaveCriticalSection(CriticalSection
);
880 CSR_API(BaseSrvGetNextVDMCommand
)
883 PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest
=
884 &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetNextVDMCommandRequest
;
885 PRTL_CRITICAL_SECTION CriticalSection
;
886 PLIST_ENTRY i
= NULL
;
887 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
888 PVDM_DOS_RECORD DosRecord
= NULL
;
890 /* Validate the message buffers */
891 if (!CsrValidateMessageBuffer(ApiMessage
,
892 (PVOID
*)&GetNextVdmCommandRequest
->CmdLine
,
893 GetNextVdmCommandRequest
->CmdLen
,
894 sizeof(*GetNextVdmCommandRequest
->CmdLine
))
895 || !CsrValidateMessageBuffer(ApiMessage
,
896 (PVOID
*)&GetNextVdmCommandRequest
->AppName
,
897 GetNextVdmCommandRequest
->AppLen
,
898 sizeof(*GetNextVdmCommandRequest
->AppName
))
899 || !CsrValidateMessageBuffer(ApiMessage
,
900 (PVOID
*)&GetNextVdmCommandRequest
->PifFile
,
901 GetNextVdmCommandRequest
->PifLen
,
902 sizeof(*GetNextVdmCommandRequest
->PifFile
))
903 || !CsrValidateMessageBuffer(ApiMessage
,
904 (PVOID
*)&GetNextVdmCommandRequest
->CurDirectory
,
905 GetNextVdmCommandRequest
->CurDirectoryLen
,
906 sizeof(*GetNextVdmCommandRequest
->CurDirectory
))
907 || !CsrValidateMessageBuffer(ApiMessage
,
908 (PVOID
*)&GetNextVdmCommandRequest
->Env
,
909 GetNextVdmCommandRequest
->EnvLen
,
910 sizeof(*GetNextVdmCommandRequest
->Env
))
911 || !CsrValidateMessageBuffer(ApiMessage
,
912 (PVOID
*)&GetNextVdmCommandRequest
->Desktop
,
913 GetNextVdmCommandRequest
->DesktopLen
,
914 sizeof(*GetNextVdmCommandRequest
->Desktop
))
915 || !CsrValidateMessageBuffer(ApiMessage
,
916 (PVOID
*)&GetNextVdmCommandRequest
->Title
,
917 GetNextVdmCommandRequest
->TitleLen
,
918 sizeof(*GetNextVdmCommandRequest
->Title
))
919 || !CsrValidateMessageBuffer(ApiMessage
,
920 (PVOID
*)&GetNextVdmCommandRequest
->Reserved
,
921 GetNextVdmCommandRequest
->ReservedLen
,
922 sizeof(*GetNextVdmCommandRequest
->Reserved
))
923 || !CsrValidateMessageBuffer(ApiMessage
,
924 (PVOID
*)&GetNextVdmCommandRequest
->StartupInfo
,
926 sizeof(STARTUPINFOA
)))
928 return STATUS_INVALID_PARAMETER
;
931 CriticalSection
= (GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
)
932 ? &WowCriticalSection
933 : &DosCriticalSection
;
935 /* Enter the critical section */
936 RtlEnterCriticalSection(CriticalSection
);
938 if (!(GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
))
940 if (GetNextVdmCommandRequest
->iTask
!= 0)
942 /* Get the console record using the task ID */
943 Status
= GetConsoleRecordBySessionId(GetNextVdmCommandRequest
->iTask
,
948 /* Get the console record using the console handle */
949 Status
= BaseSrvGetConsoleRecord(GetNextVdmCommandRequest
->ConsoleHandle
,
953 /* Make sure we found the console record */
954 if (!NT_SUCCESS(Status
)) goto Cleanup
;
956 /* Return the session ID */
957 GetNextVdmCommandRequest
->iTask
= ConsoleRecord
->SessionId
;
958 GetNextVdmCommandRequest
->WaitObjectForVDM
= NULL
;
960 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_FIRST_COMMAND
)
962 /* Check if the DOS record list is empty */
963 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
965 Status
= STATUS_INVALID_PARAMETER
;
969 /* Get the first DOS record */
970 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
, VDM_DOS_RECORD
, Entry
);
972 /* Make sure its command information is still there */
973 if (DosRecord
->CommandInfo
== NULL
)
975 Status
= STATUS_INVALID_PARAMETER
;
979 /* Check if the console handle hasn't been set yet */
980 if (ConsoleRecord
->ConsoleHandle
== NULL
)
983 ConsoleRecord
->ConsoleHandle
= GetNextVdmCommandRequest
->ConsoleHandle
;
986 /* Fill the command information */
987 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
991 /* Check if we should set the state of a running DOS record to ready */
992 if (!(GetNextVdmCommandRequest
->VDMState
993 & (VDM_FLAG_FIRST_TASK
| VDM_FLAG_RETRY
| VDM_FLAG_NESTED_TASK
)))
995 /* Search for a DOS record that is currently running */
996 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
998 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
999 if (DosRecord
->State
== VDM_NOT_READY
) break;
1002 /* Check if we found any */
1003 if (i
== &ConsoleRecord
->DosListHead
)
1005 Status
= STATUS_INVALID_PARAMETER
;
1009 /* Set the exit code */
1010 DosRecord
->ExitCode
= GetNextVdmCommandRequest
->ExitCode
;
1012 /* Update the VDM state */
1013 DosRecord
->State
= VDM_READY
;
1015 /* Notify all waiting threads that the task is finished */
1016 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
1017 NtClose(DosRecord
->ServerEvent
);
1018 DosRecord
->ServerEvent
= NULL
;
1021 /* Search for a DOS record that isn't loaded yet */
1022 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
1024 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
1025 if (DosRecord
->State
== VDM_NOT_LOADED
) break;
1028 if (i
!= &ConsoleRecord
->DosListHead
)
1030 /* DOS tasks which haven't been loaded yet should have a command info structure */
1031 ASSERT(DosRecord
->CommandInfo
!= NULL
);
1033 /* Check if the caller only wants environment data */
1034 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_ENVIRONMENT
)
1036 if (GetNextVdmCommandRequest
->EnvLen
< DosRecord
->CommandInfo
->EnvLen
)
1038 /* Not enough space was reserved */
1039 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
1040 Status
= STATUS_BUFFER_OVERFLOW
;
1044 /* Copy the environment data */
1045 RtlMoveMemory(GetNextVdmCommandRequest
->Env
,
1046 DosRecord
->CommandInfo
->Env
,
1047 DosRecord
->CommandInfo
->EnvLen
);
1049 /* Return the actual size to the caller */
1050 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
1054 /* Fill the command information */
1055 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
1056 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1058 /* Free the command information, it's no longer needed */
1059 BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1060 DosRecord
->CommandInfo
= NULL
;
1062 /* Update the VDM state */
1063 GetNextVdmCommandRequest
->VDMState
= DosRecord
->State
= VDM_NOT_READY
;
1066 Status
= STATUS_SUCCESS
;
1072 // TODO: WOW SUPPORT NOT IMPLEMENTED
1073 Status
= STATUS_NOT_IMPLEMENTED
;
1077 /* There is no command yet */
1078 if (!(GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_DONT_WAIT
))
1080 if (ConsoleRecord
->ServerEvent
)
1082 /* Reset the event */
1083 NtResetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1087 /* Create a pair of wait handles */
1088 Status
= BaseSrvCreatePairWaitHandles(&ConsoleRecord
->ServerEvent
,
1089 &ConsoleRecord
->ClientEvent
);
1090 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1093 /* Return the client event handle */
1094 GetNextVdmCommandRequest
->WaitObjectForVDM
= ConsoleRecord
->ClientEvent
;
1098 /* Leave the critical section */
1099 RtlLeaveCriticalSection(CriticalSection
);
1104 CSR_API(BaseSrvExitVDM
)
1107 PBASE_EXIT_VDM ExitVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitVDMRequest
;
1108 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
1109 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1110 PVDM_DOS_RECORD DosRecord
;
1112 CriticalSection
= (ExitVdmRequest
->iWowTask
== 0)
1113 ? &DosCriticalSection
1114 : &WowCriticalSection
;
1116 /* Enter the critical section */
1117 RtlEnterCriticalSection(CriticalSection
);
1119 if (ExitVdmRequest
->iWowTask
== 0)
1121 /* Get the console record */
1122 Status
= BaseSrvGetConsoleRecord(ExitVdmRequest
->ConsoleHandle
, &ConsoleRecord
);
1123 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1125 /* Cleanup the DOS records */
1126 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
1128 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
1132 /* Set the event and close it */
1133 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
1134 NtClose(DosRecord
->ServerEvent
);
1136 /* Remove the DOS entry */
1137 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1138 RemoveEntryList(&DosRecord
->Entry
);
1139 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1142 if (ConsoleRecord
->CurrentDirs
!= NULL
)
1144 /* Free the current directories */
1145 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
1146 ConsoleRecord
->CurrentDirs
= NULL
;
1147 ConsoleRecord
->CurDirsLength
= 0;
1150 /* Close the event handle */
1151 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
1153 /* Remove the console record */
1154 RemoveEntryList(&ConsoleRecord
->Entry
);
1155 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
1159 // TODO: NOT IMPLEMENTED
1161 Status
= STATUS_NOT_IMPLEMENTED
;
1165 /* Leave the critical section */
1166 RtlLeaveCriticalSection(CriticalSection
);
1171 CSR_API(BaseSrvIsFirstVDM
)
1173 PBASE_IS_FIRST_VDM IsFirstVDMRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.IsFirstVDMRequest
;
1175 /* Return the result */
1176 IsFirstVDMRequest
->FirstVDM
= FirstVDM
;
1178 /* Clear the first VDM flag */
1181 return STATUS_SUCCESS
;
1184 CSR_API(BaseSrvGetVDMExitCode
)
1187 PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetVDMExitCodeRequest
;
1188 PLIST_ENTRY i
= NULL
;
1189 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1190 PVDM_DOS_RECORD DosRecord
= NULL
;
1192 /* Enter the critical section */
1193 RtlEnterCriticalSection(&DosCriticalSection
);
1195 /* Get the console record */
1196 Status
= BaseSrvGetConsoleRecord(GetVDMExitCodeRequest
->ConsoleHandle
, &ConsoleRecord
);
1197 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1199 /* Search for a DOS record that has the same parent process handle */
1200 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
1202 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
1203 if (DosRecord
->ClientEvent
== GetVDMExitCodeRequest
->hParent
) break;
1206 /* Check if no DOS record was found */
1207 if (i
== &ConsoleRecord
->DosListHead
)
1209 Status
= STATUS_NOT_FOUND
;
1213 /* Check if this task is still running */
1214 if (DosRecord
->State
!= VDM_READY
)
1216 GetVDMExitCodeRequest
->ExitCode
= STATUS_PENDING
;
1220 /* Return the exit code */
1221 GetVDMExitCodeRequest
->ExitCode
= DosRecord
->ExitCode
;
1223 /* Since this is a zombie task record, remove it */
1224 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1225 RemoveEntryList(&DosRecord
->Entry
);
1226 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1229 /* Leave the critical section */
1230 RtlLeaveCriticalSection(&DosCriticalSection
);
1235 CSR_API(BaseSrvSetReenterCount
)
1237 NTSTATUS Status
= STATUS_SUCCESS
;
1238 PBASE_SET_REENTER_COUNT SetReenterCountRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetReenterCountRequest
;
1239 PVDM_CONSOLE_RECORD ConsoleRecord
;
1241 /* Enter the critical section */
1242 RtlEnterCriticalSection(&DosCriticalSection
);
1244 /* Get the console record */
1245 Status
= BaseSrvGetConsoleRecord(SetReenterCountRequest
->ConsoleHandle
, &ConsoleRecord
);
1246 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1248 if (SetReenterCountRequest
->fIncDec
== VDM_INC_REENTER_COUNT
) ConsoleRecord
->ReenterCount
++;
1249 else if (SetReenterCountRequest
->fIncDec
== VDM_DEC_REENTER_COUNT
)
1251 ConsoleRecord
->ReenterCount
--;
1252 if (ConsoleRecord
->ServerEvent
!= NULL
) NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1254 else Status
= STATUS_INVALID_PARAMETER
;
1257 /* Leave the critical section */
1258 RtlLeaveCriticalSection(&DosCriticalSection
);
1263 CSR_API(BaseSrvSetVDMCurDirs
)
1266 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1267 PVDM_CONSOLE_RECORD ConsoleRecord
;
1268 PCHAR Buffer
= NULL
;
1270 /* Validate the input buffer */
1271 if (!CsrValidateMessageBuffer(ApiMessage
,
1272 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1273 VDMCurrentDirsRequest
->cchCurDirs
,
1274 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1276 return STATUS_INVALID_PARAMETER
;
1279 /* Enter the critical section */
1280 RtlEnterCriticalSection(&DosCriticalSection
);
1282 /* Find the console record */
1283 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1284 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1286 if (ConsoleRecord
->CurrentDirs
== NULL
)
1288 /* Allocate memory for the current directory information */
1289 Buffer
= RtlAllocateHeap(BaseSrvHeap
,
1291 VDMCurrentDirsRequest
->cchCurDirs
);
1295 /* Resize the amount of allocated memory */
1296 Buffer
= RtlReAllocateHeap(BaseSrvHeap
,
1298 ConsoleRecord
->CurrentDirs
,
1299 VDMCurrentDirsRequest
->cchCurDirs
);
1304 /* Allocation failed */
1305 Status
= STATUS_NO_MEMORY
;
1309 /* Update the console record */
1310 ConsoleRecord
->CurrentDirs
= Buffer
;
1311 ConsoleRecord
->CurDirsLength
= VDMCurrentDirsRequest
->cchCurDirs
;
1314 RtlMoveMemory(ConsoleRecord
->CurrentDirs
,
1315 VDMCurrentDirsRequest
->lpszzCurDirs
,
1316 VDMCurrentDirsRequest
->cchCurDirs
);
1319 /* Leave the critical section */
1320 RtlLeaveCriticalSection(&DosCriticalSection
);
1325 CSR_API(BaseSrvGetVDMCurDirs
)
1328 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1329 PVDM_CONSOLE_RECORD ConsoleRecord
;
1331 /* Validate the output buffer */
1332 if (!CsrValidateMessageBuffer(ApiMessage
,
1333 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1334 VDMCurrentDirsRequest
->cchCurDirs
,
1335 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1337 return STATUS_INVALID_PARAMETER
;
1340 /* Enter the critical section */
1341 RtlEnterCriticalSection(&DosCriticalSection
);
1343 /* Find the console record */
1344 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1345 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1347 /* Return the actual size of the current directory information */
1348 VDMCurrentDirsRequest
->cchCurDirs
= ConsoleRecord
->CurDirsLength
;
1350 /* Check if the buffer is large enough */
1351 if (VDMCurrentDirsRequest
->cchCurDirs
< ConsoleRecord
->CurDirsLength
)
1353 Status
= STATUS_BUFFER_TOO_SMALL
;
1358 RtlMoveMemory(VDMCurrentDirsRequest
->lpszzCurDirs
,
1359 ConsoleRecord
->CurrentDirs
,
1360 ConsoleRecord
->CurDirsLength
);
1363 /* Leave the critical section */
1364 RtlLeaveCriticalSection(&DosCriticalSection
);
1369 CSR_API(BaseSrvBatNotification
)
1371 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1372 return STATUS_NOT_IMPLEMENTED
;
1375 CSR_API(BaseSrvRegisterWowExec
)
1377 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1378 return STATUS_NOT_IMPLEMENTED
;
1381 CSR_API(BaseSrvRefreshIniFileMapping
)
1383 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1384 return STATUS_NOT_IMPLEMENTED
;