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 event handle */
273 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
275 /* Remove the console record */
277 RemoveEntryList(&ConsoleRecord
->Entry
);
278 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
282 /* Leave the critical section */
283 RtlLeaveCriticalSection(&DosCriticalSection
);
286 BOOLEAN NTAPI
BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest
, PVDM_DOS_RECORD DosRecord
)
288 BOOLEAN Success
= FALSE
;
289 PVDM_COMMAND_INFO CommandInfo
= NULL
;
291 /* Allocate the command information structure */
292 CommandInfo
= (PVDM_COMMAND_INFO
)RtlAllocateHeap(BaseSrvHeap
,
294 sizeof(VDM_COMMAND_INFO
));
295 if (CommandInfo
== NULL
) return FALSE
;
297 /* Fill the structure */
298 CommandInfo
->TaskId
= CheckVdmRequest
->iTask
;
299 CommandInfo
->ExitCode
= DosRecord
->ExitCode
;
300 CommandInfo
->CodePage
= CheckVdmRequest
->CodePage
;
301 CommandInfo
->StdIn
= CheckVdmRequest
->StdIn
;
302 CommandInfo
->StdOut
= CheckVdmRequest
->StdOut
;
303 CommandInfo
->StdErr
= CheckVdmRequest
->StdErr
;
305 /* Allocate memory for the command line */
306 CommandInfo
->CmdLine
= RtlAllocateHeap(BaseSrvHeap
,
308 CheckVdmRequest
->CmdLen
);
309 if (CommandInfo
->CmdLine
== NULL
) goto Cleanup
;
311 /* Copy the command line */
312 RtlMoveMemory(CommandInfo
->CmdLine
, CheckVdmRequest
->CmdLine
, CheckVdmRequest
->CmdLen
);
314 /* Allocate memory for the application name */
315 CommandInfo
->AppName
= RtlAllocateHeap(BaseSrvHeap
,
317 CheckVdmRequest
->AppLen
);
318 if (CommandInfo
->AppName
== NULL
) goto Cleanup
;
320 /* Copy the application name */
321 RtlMoveMemory(CommandInfo
->AppName
, CheckVdmRequest
->AppName
, CheckVdmRequest
->AppLen
);
323 /* Allocate memory for the PIF file name */
324 if (CheckVdmRequest
->PifLen
!= 0)
326 CommandInfo
->PifFile
= RtlAllocateHeap(BaseSrvHeap
,
328 CheckVdmRequest
->PifLen
);
329 if (CommandInfo
->PifFile
== NULL
) goto Cleanup
;
331 /* Copy the PIF file name */
332 RtlMoveMemory(CommandInfo
->PifFile
, CheckVdmRequest
->PifFile
, CheckVdmRequest
->PifLen
);
334 else CommandInfo
->PifFile
= NULL
;
336 /* Allocate memory for the current directory */
337 if (CheckVdmRequest
->CurDirectoryLen
!= 0)
339 CommandInfo
->CurDirectory
= RtlAllocateHeap(BaseSrvHeap
,
341 CheckVdmRequest
->CurDirectoryLen
);
342 if (CommandInfo
->CurDirectory
== NULL
) goto Cleanup
;
344 /* Copy the current directory */
345 RtlMoveMemory(CommandInfo
->CurDirectory
,
346 CheckVdmRequest
->CurDirectory
,
347 CheckVdmRequest
->CurDirectoryLen
);
349 else CommandInfo
->CurDirectory
= NULL
;
351 /* Allocate memory for the environment block */
352 CommandInfo
->Env
= RtlAllocateHeap(BaseSrvHeap
,
354 CheckVdmRequest
->EnvLen
);
355 if (CommandInfo
->Env
== NULL
) goto Cleanup
;
357 /* Copy the environment block */
358 RtlMoveMemory(CommandInfo
->Env
, CheckVdmRequest
->Env
, CheckVdmRequest
->EnvLen
);
360 CommandInfo
->EnvLen
= CheckVdmRequest
->EnvLen
;
361 RtlMoveMemory(&CommandInfo
->StartupInfo
,
362 CheckVdmRequest
->StartupInfo
,
363 sizeof(STARTUPINFOA
));
365 /* Allocate memory for the desktop */
366 if (CheckVdmRequest
->DesktopLen
!= 0)
368 CommandInfo
->Desktop
= RtlAllocateHeap(BaseSrvHeap
,
370 CheckVdmRequest
->DesktopLen
);
371 if (CommandInfo
->Desktop
== NULL
) goto Cleanup
;
373 /* Copy the desktop name */
374 RtlMoveMemory(CommandInfo
->Desktop
, CheckVdmRequest
->Desktop
, CheckVdmRequest
->DesktopLen
);
376 else CommandInfo
->Desktop
= NULL
;
378 CommandInfo
->DesktopLen
= CheckVdmRequest
->DesktopLen
;
380 /* Allocate memory for the title */
381 if (CheckVdmRequest
->TitleLen
!= 0)
383 CommandInfo
->Title
= RtlAllocateHeap(BaseSrvHeap
,
385 CheckVdmRequest
->TitleLen
);
386 if (CommandInfo
->Title
== NULL
) goto Cleanup
;
389 RtlMoveMemory(CommandInfo
->Title
, CheckVdmRequest
->Title
, CheckVdmRequest
->TitleLen
);
391 else CommandInfo
->Title
= NULL
;
393 CommandInfo
->TitleLen
= CheckVdmRequest
->TitleLen
;
395 /* Allocate memory for the reserved field */
396 if (CheckVdmRequest
->ReservedLen
!= 0)
398 CommandInfo
->Reserved
= RtlAllocateHeap(BaseSrvHeap
,
400 CheckVdmRequest
->ReservedLen
);
401 if (CommandInfo
->Reserved
== NULL
) goto Cleanup
;
403 /* Copy the reserved field */
404 RtlMoveMemory(CommandInfo
->Reserved
,
405 CheckVdmRequest
->Reserved
,
406 CheckVdmRequest
->ReservedLen
);
408 else CommandInfo
->Reserved
= NULL
;
410 CommandInfo
->ReservedLen
= CheckVdmRequest
->ReservedLen
;
412 CommandInfo
->CmdLen
= CheckVdmRequest
->CmdLen
;
413 CommandInfo
->AppLen
= CheckVdmRequest
->AppLen
;
414 CommandInfo
->PifLen
= CheckVdmRequest
->PifLen
;
415 CommandInfo
->CurDirectoryLen
= CheckVdmRequest
->CurDirectoryLen
;
416 CommandInfo
->VDMState
= DosRecord
->State
;
417 // TODO: Set CommandInfo->CurrentDrive
418 // TODO: Set CommandInfo->ComingFromBat
420 /* Set the DOS record's command structure */
421 DosRecord
->CommandInfo
= CommandInfo
;
423 /* The operation was successful */
427 /* If it wasn't successful, free the memory */
428 if (!Success
) BaseSrvFreeVDMInfo(CommandInfo
);
433 NTSTATUS NTAPI
BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo
,
434 PBASE_GET_NEXT_VDM_COMMAND Message
)
437 Message
->iTask
= CommandInfo
->TaskId
;
438 Message
->StdIn
= CommandInfo
->StdIn
;
439 Message
->StdOut
= CommandInfo
->StdOut
;
440 Message
->StdErr
= CommandInfo
->StdErr
;
441 Message
->CodePage
= CommandInfo
->CodePage
;
442 Message
->dwCreationFlags
= CommandInfo
->CreationFlags
;
443 Message
->ExitCode
= CommandInfo
->ExitCode
;
444 Message
->CurrentDrive
= CommandInfo
->CurrentDrive
;
445 Message
->VDMState
= CommandInfo
->VDMState
;
446 Message
->fComingFromBat
= CommandInfo
->ComingFromBat
;
448 if (CommandInfo
->CmdLen
&& Message
->CmdLen
)
450 if (Message
->CmdLen
< CommandInfo
->CmdLen
) return STATUS_BUFFER_TOO_SMALL
;
452 /* Copy the command line */
453 RtlMoveMemory(Message
->CmdLine
, CommandInfo
->CmdLine
, CommandInfo
->CmdLen
);
454 Message
->CmdLen
= CommandInfo
->CmdLen
;
457 if (CommandInfo
->AppLen
&& Message
->AppLen
)
459 if (Message
->AppLen
< CommandInfo
->CmdLen
) return STATUS_BUFFER_TOO_SMALL
;
461 /* Copy the application name */
462 RtlMoveMemory(Message
->AppName
, CommandInfo
->AppName
, CommandInfo
->AppLen
);
463 Message
->AppLen
= CommandInfo
->AppLen
;
466 if (CommandInfo
->PifLen
&& Message
->PifLen
)
468 if (Message
->PifLen
< CommandInfo
->PifLen
) return STATUS_BUFFER_TOO_SMALL
;
470 /* Copy the PIF file name */
471 RtlMoveMemory(Message
->PifFile
, CommandInfo
->PifFile
, CommandInfo
->PifLen
);
472 Message
->PifLen
= CommandInfo
->PifLen
;
475 if (CommandInfo
->CurDirectoryLen
&& Message
->CurDirectoryLen
)
477 if (Message
->CurDirectoryLen
< CommandInfo
->CurDirectoryLen
) return STATUS_BUFFER_TOO_SMALL
;
479 /* Copy the current directory */
480 RtlMoveMemory(Message
->CurDirectory
, CommandInfo
->CurDirectory
, CommandInfo
->CurDirectoryLen
);
481 Message
->CurDirectoryLen
= CommandInfo
->CurDirectoryLen
;
484 if (CommandInfo
->EnvLen
&& Message
->EnvLen
)
486 if (Message
->EnvLen
< CommandInfo
->EnvLen
) return STATUS_BUFFER_TOO_SMALL
;
488 /* Copy the environment */
489 RtlMoveMemory(Message
->Env
, CommandInfo
->Env
, CommandInfo
->EnvLen
);
490 Message
->EnvLen
= CommandInfo
->EnvLen
;
493 /* Copy the startup info */
494 RtlMoveMemory(Message
->StartupInfo
,
495 &CommandInfo
->StartupInfo
,
496 sizeof(STARTUPINFOA
));
498 if (CommandInfo
->DesktopLen
&& Message
->DesktopLen
)
500 if (Message
->DesktopLen
< CommandInfo
->DesktopLen
) return STATUS_BUFFER_TOO_SMALL
;
502 /* Copy the desktop name */
503 RtlMoveMemory(Message
->Desktop
, CommandInfo
->Desktop
, CommandInfo
->DesktopLen
);
504 Message
->DesktopLen
= CommandInfo
->DesktopLen
;
507 if (CommandInfo
->TitleLen
&& Message
->TitleLen
)
509 if (Message
->TitleLen
< CommandInfo
->TitleLen
) return STATUS_BUFFER_TOO_SMALL
;
512 RtlMoveMemory(Message
->Title
, CommandInfo
->Title
, CommandInfo
->TitleLen
);
513 Message
->TitleLen
= CommandInfo
->TitleLen
;
516 if (CommandInfo
->ReservedLen
&& Message
->ReservedLen
)
518 if (Message
->ReservedLen
< CommandInfo
->ReservedLen
) return STATUS_BUFFER_TOO_SMALL
;
520 /* Copy the reserved parameter */
521 RtlMoveMemory(Message
->Reserved
, CommandInfo
->Reserved
, CommandInfo
->ReservedLen
);
522 Message
->ReservedLen
= CommandInfo
->ReservedLen
;
525 return STATUS_SUCCESS
;
528 VOID NTAPI
BaseInitializeVDM(VOID
)
530 /* Initialize the list head */
531 InitializeListHead(&VDMConsoleListHead
);
533 /* Initialize the critical section */
534 RtlInitializeCriticalSection(&DosCriticalSection
);
535 RtlInitializeCriticalSection(&WowCriticalSection
);
538 /* PUBLIC SERVER APIS *********************************************************/
540 CSR_API(BaseSrvCheckVDM
)
543 PBASE_CHECK_VDM CheckVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CheckVDMRequest
;
544 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
545 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
546 PVDM_DOS_RECORD DosRecord
= NULL
;
547 BOOLEAN NewConsoleRecord
= FALSE
;
549 /* Don't do anything if the VDM has been disabled in the registry */
550 if (!BaseSrvIsVdmAllowed()) return STATUS_ACCESS_DENIED
;
552 /* Validate the message buffers */
553 if (!CsrValidateMessageBuffer(ApiMessage
,
554 (PVOID
*)&CheckVdmRequest
->CmdLine
,
555 CheckVdmRequest
->CmdLen
,
556 sizeof(*CheckVdmRequest
->CmdLine
))
557 || !CsrValidateMessageBuffer(ApiMessage
,
558 (PVOID
*)&CheckVdmRequest
->AppName
,
559 CheckVdmRequest
->AppLen
,
560 sizeof(*CheckVdmRequest
->AppName
))
561 || !CsrValidateMessageBuffer(ApiMessage
,
562 (PVOID
*)&CheckVdmRequest
->PifFile
,
563 CheckVdmRequest
->PifLen
,
564 sizeof(*CheckVdmRequest
->PifFile
))
565 || !CsrValidateMessageBuffer(ApiMessage
,
566 (PVOID
*)&CheckVdmRequest
->CurDirectory
,
567 CheckVdmRequest
->CurDirectoryLen
,
568 sizeof(*CheckVdmRequest
->CurDirectory
))
569 || !CsrValidateMessageBuffer(ApiMessage
,
570 (PVOID
*)&CheckVdmRequest
->Desktop
,
571 CheckVdmRequest
->DesktopLen
,
572 sizeof(*CheckVdmRequest
->Desktop
))
573 || !CsrValidateMessageBuffer(ApiMessage
,
574 (PVOID
*)&CheckVdmRequest
->Title
,
575 CheckVdmRequest
->TitleLen
,
576 sizeof(*CheckVdmRequest
->Title
))
577 || !CsrValidateMessageBuffer(ApiMessage
,
578 (PVOID
*)&CheckVdmRequest
->Reserved
,
579 CheckVdmRequest
->ReservedLen
,
580 sizeof(*CheckVdmRequest
->Reserved
)))
582 return STATUS_INVALID_PARAMETER
;
585 CriticalSection
= (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
586 ? &DosCriticalSection
587 : &WowCriticalSection
;
589 /* Enter the critical section */
590 RtlEnterCriticalSection(CriticalSection
);
592 /* Check if this is a DOS or WOW VDM */
593 if (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
595 /* Get the console record */
596 Status
= BaseSrvGetConsoleRecord(CheckVdmRequest
->ConsoleHandle
,
599 if (!NT_SUCCESS(Status
))
601 /* Allocate a new console record */
602 ConsoleRecord
= (PVDM_CONSOLE_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
604 sizeof(VDM_CONSOLE_RECORD
));
605 if (ConsoleRecord
== NULL
)
607 Status
= STATUS_NO_MEMORY
;
611 /* Remember that the console record was allocated here */
612 NewConsoleRecord
= TRUE
;
614 /* Initialize the console record */
615 ConsoleRecord
->ConsoleHandle
= CheckVdmRequest
->ConsoleHandle
;
616 ConsoleRecord
->ProcessHandle
= CsrGetClientThread()->Process
->ProcessHandle
;
617 ConsoleRecord
->ServerEvent
= ConsoleRecord
->ClientEvent
= NULL
;
618 ConsoleRecord
->ReenterCount
= 0;
619 ConsoleRecord
->CurrentDirs
= NULL
;
620 ConsoleRecord
->CurDirsLength
= 0;
621 ConsoleRecord
->SessionId
= GetNextDosSesId();
622 InitializeListHead(&ConsoleRecord
->DosListHead
);
625 /* Allocate a new DOS record */
626 DosRecord
= (PVDM_DOS_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
628 sizeof(VDM_DOS_RECORD
));
629 if (DosRecord
== NULL
)
631 Status
= STATUS_NO_MEMORY
;
635 /* Initialize the DOS record */
636 DosRecord
->State
= VDM_NOT_LOADED
;
637 DosRecord
->ExitCode
= 0;
639 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
, &DosRecord
->ClientEvent
);
640 if (!NT_SUCCESS(Status
)) goto Cleanup
;
642 /* Return the client event handle */
643 CheckVdmRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
645 /* Translate the input structure into a VDM command structure and set it in the DOS record */
646 if (!BaseSrvCopyCommand(CheckVdmRequest
, DosRecord
))
648 /* The only possibility is that an allocation failure occurred */
649 Status
= STATUS_NO_MEMORY
;
653 /* Add the DOS record */
654 InsertHeadList(&ConsoleRecord
->DosListHead
, &DosRecord
->Entry
);
656 if (ConsoleRecord
->ServerEvent
)
658 /* Signal the session event */
659 NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
662 if (NewConsoleRecord
)
664 /* Add the console record */
665 InsertTailList(&VDMConsoleListHead
, &ConsoleRecord
->Entry
);
668 if (ConsoleRecord
->ConsoleHandle
== NULL
)
670 /* The parent doesn't have a console, so return the session ID */
671 CheckVdmRequest
->iTask
= ConsoleRecord
->SessionId
;
673 else CheckVdmRequest
->iTask
= 0;
675 CheckVdmRequest
->VDMState
= NewConsoleRecord
? VDM_NOT_LOADED
: VDM_READY
;
676 Status
= STATUS_SUCCESS
;
680 // TODO: NOT IMPLEMENTED
682 Status
= STATUS_NOT_IMPLEMENTED
;
686 /* Check if it failed */
687 if (!NT_SUCCESS(Status
))
689 /* Free the DOS record */
690 if (DosRecord
!= NULL
)
692 if (DosRecord
->ServerEvent
) NtClose(DosRecord
->ServerEvent
);
693 if (DosRecord
->ClientEvent
)
695 /* Close the remote handle */
696 NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
697 DosRecord
->ClientEvent
,
702 DUPLICATE_CLOSE_SOURCE
);
705 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
709 /* Free the console record if it was allocated here */
710 if (NewConsoleRecord
)
712 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
713 ConsoleRecord
= NULL
;
717 /* Leave the critical section */
718 RtlLeaveCriticalSection(CriticalSection
);
723 CSR_API(BaseSrvUpdateVDMEntry
)
726 PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.UpdateVDMEntryRequest
;
727 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
728 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
729 PVDM_DOS_RECORD DosRecord
= NULL
;
731 CriticalSection
= (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
732 ? &DosCriticalSection
733 : &WowCriticalSection
;
735 /* Enter the critical section */
736 RtlEnterCriticalSection(CriticalSection
);
738 /* Check if this is a DOS or WOW VDM */
739 if (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
741 if (UpdateVdmEntryRequest
->iTask
!= 0)
743 /* Get the console record using the task ID */
744 Status
= GetConsoleRecordBySessionId(UpdateVdmEntryRequest
->iTask
,
749 /* Get the console record using the console handle */
750 Status
= BaseSrvGetConsoleRecord(UpdateVdmEntryRequest
->ConsoleHandle
,
754 if (!NT_SUCCESS(Status
)) goto Cleanup
;
756 /* Get the primary DOS record */
757 DosRecord
= (PVDM_DOS_RECORD
)CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
761 switch (UpdateVdmEntryRequest
->EntryIndex
)
765 /* Close the server event handle, the client will close the client handle */
766 NtClose(DosRecord
->ServerEvent
);
767 DosRecord
->ServerEvent
= DosRecord
->ClientEvent
= NULL
;
769 if (UpdateVdmEntryRequest
->VDMCreationState
& (VDM_UNDO_PARTIAL
| VDM_UNDO_FULL
))
771 /* Remove the DOS record */
772 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
773 RemoveEntryList(&DosRecord
->Entry
);
774 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
777 * Since this is an undo, if that was the only DOS record the VDM
778 * won't even start, so the console record should be removed too.
780 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
782 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
783 RemoveEntryList(&ConsoleRecord
->Entry
);
784 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
788 /* It was successful */
789 Status
= STATUS_SUCCESS
;
794 case VdmEntryUpdateProcess
:
796 /* Duplicate the VDM process handle */
797 Status
= NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
798 UpdateVdmEntryRequest
->VDMProcessHandle
,
800 &ConsoleRecord
->ProcessHandle
,
803 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
804 if (!NT_SUCCESS(Status
)) goto Cleanup
;
806 /* Create a pair of handles to one event object */
807 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
,
808 &DosRecord
->ClientEvent
);
809 if (!NT_SUCCESS(Status
)) goto Cleanup
;
811 /* Return the client event handle */
812 UpdateVdmEntryRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
817 case VdmEntryUpdateControlCHandler
:
819 // TODO: NOT IMPLEMENTED
820 DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!");
821 Status
= STATUS_NOT_IMPLEMENTED
;
829 Status
= STATUS_INVALID_PARAMETER
;
835 // TODO: NOT IMPLEMENTED
837 Status
= STATUS_NOT_IMPLEMENTED
;
841 /* Leave the critical section */
842 RtlLeaveCriticalSection(CriticalSection
);
847 CSR_API(BaseSrvGetNextVDMCommand
)
850 PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest
=
851 &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetNextVDMCommandRequest
;
852 PRTL_CRITICAL_SECTION CriticalSection
;
853 PLIST_ENTRY i
= NULL
;
854 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
855 PVDM_DOS_RECORD DosRecord
= NULL
;
857 /* Validate the message buffers */
858 if (!CsrValidateMessageBuffer(ApiMessage
,
859 (PVOID
*)&GetNextVdmCommandRequest
->CmdLine
,
860 GetNextVdmCommandRequest
->CmdLen
,
861 sizeof(*GetNextVdmCommandRequest
->CmdLine
))
862 || !CsrValidateMessageBuffer(ApiMessage
,
863 (PVOID
*)&GetNextVdmCommandRequest
->AppName
,
864 GetNextVdmCommandRequest
->AppLen
,
865 sizeof(*GetNextVdmCommandRequest
->AppName
))
866 || !CsrValidateMessageBuffer(ApiMessage
,
867 (PVOID
*)&GetNextVdmCommandRequest
->PifFile
,
868 GetNextVdmCommandRequest
->PifLen
,
869 sizeof(*GetNextVdmCommandRequest
->PifFile
))
870 || !CsrValidateMessageBuffer(ApiMessage
,
871 (PVOID
*)&GetNextVdmCommandRequest
->CurDirectory
,
872 GetNextVdmCommandRequest
->CurDirectoryLen
,
873 sizeof(*GetNextVdmCommandRequest
->CurDirectory
))
874 || !CsrValidateMessageBuffer(ApiMessage
,
875 (PVOID
*)&GetNextVdmCommandRequest
->Env
,
876 GetNextVdmCommandRequest
->EnvLen
,
877 sizeof(*GetNextVdmCommandRequest
->Env
))
878 || !CsrValidateMessageBuffer(ApiMessage
,
879 (PVOID
*)&GetNextVdmCommandRequest
->Desktop
,
880 GetNextVdmCommandRequest
->DesktopLen
,
881 sizeof(*GetNextVdmCommandRequest
->Desktop
))
882 || !CsrValidateMessageBuffer(ApiMessage
,
883 (PVOID
*)&GetNextVdmCommandRequest
->Title
,
884 GetNextVdmCommandRequest
->TitleLen
,
885 sizeof(*GetNextVdmCommandRequest
->Title
))
886 || !CsrValidateMessageBuffer(ApiMessage
,
887 (PVOID
*)&GetNextVdmCommandRequest
->Reserved
,
888 GetNextVdmCommandRequest
->ReservedLen
,
889 sizeof(*GetNextVdmCommandRequest
->Reserved
))
890 || !CsrValidateMessageBuffer(ApiMessage
,
891 (PVOID
*)&GetNextVdmCommandRequest
->StartupInfo
,
893 sizeof(STARTUPINFOA
)))
895 return STATUS_INVALID_PARAMETER
;
898 CriticalSection
= (GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
)
899 ? &WowCriticalSection
900 : &DosCriticalSection
;
902 /* Enter the critical section */
903 RtlEnterCriticalSection(CriticalSection
);
905 if (!(GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
))
907 if (GetNextVdmCommandRequest
->iTask
!= 0)
909 /* Get the console record using the task ID */
910 Status
= GetConsoleRecordBySessionId(GetNextVdmCommandRequest
->iTask
,
915 /* Get the console record using the console handle */
916 Status
= BaseSrvGetConsoleRecord(GetNextVdmCommandRequest
->ConsoleHandle
,
920 /* Make sure we found the console record */
921 if (!NT_SUCCESS(Status
)) goto Cleanup
;
923 /* Return the session ID */
924 GetNextVdmCommandRequest
->iTask
= ConsoleRecord
->SessionId
;
925 GetNextVdmCommandRequest
->WaitObjectForVDM
= NULL
;
927 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_FIRST_COMMAND
)
929 /* Check if the DOS record list is empty */
930 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
932 Status
= STATUS_INVALID_PARAMETER
;
936 /* Get the first DOS record */
937 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
, VDM_DOS_RECORD
, Entry
);
939 /* Make sure its command information is still there */
940 if (DosRecord
->CommandInfo
== NULL
)
942 Status
= STATUS_INVALID_PARAMETER
;
946 /* Fill the command information */
947 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
951 /* Check if we should set the state of a running DOS record to ready */
952 if (!(GetNextVdmCommandRequest
->VDMState
953 & (VDM_FLAG_FIRST_TASK
| VDM_FLAG_RETRY
| VDM_FLAG_NESTED_TASK
)))
955 /* Search for a DOS record that is currently running */
956 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
958 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
959 if (DosRecord
->State
== VDM_NOT_READY
) break;
962 /* Check if we found any */
963 if (i
== &ConsoleRecord
->DosListHead
)
965 Status
= STATUS_INVALID_PARAMETER
;
969 /* Set the exit code */
970 DosRecord
->ExitCode
= GetNextVdmCommandRequest
->ExitCode
;
972 /* Update the VDM state */
973 DosRecord
->State
= VDM_READY
;
975 /* Notify all waiting threads that the task is finished */
976 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
977 NtClose(DosRecord
->ServerEvent
);
978 DosRecord
->ServerEvent
= NULL
;
981 /* Search for a DOS record that isn't loaded yet */
982 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
984 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
985 if (DosRecord
->State
== VDM_NOT_LOADED
) break;
988 if (i
!= &ConsoleRecord
->DosListHead
)
990 /* DOS tasks which haven't been loaded yet should have a command info structure */
991 ASSERT(DosRecord
->CommandInfo
!= NULL
);
993 /* Check if the caller only wants environment data */
994 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_ENVIRONMENT
)
996 if (GetNextVdmCommandRequest
->EnvLen
< DosRecord
->CommandInfo
->EnvLen
)
998 /* Not enough space was reserved */
999 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
1000 Status
= STATUS_BUFFER_OVERFLOW
;
1004 /* Copy the environment data */
1005 RtlMoveMemory(GetNextVdmCommandRequest
->Env
,
1006 DosRecord
->CommandInfo
->Env
,
1007 DosRecord
->CommandInfo
->EnvLen
);
1009 /* Return the actual size to the caller */
1010 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
1014 /* Fill the command information */
1015 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
1017 /* Free the command information, it's no longer needed */
1018 BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1019 DosRecord
->CommandInfo
= NULL
;
1021 /* Update the VDM state */
1022 GetNextVdmCommandRequest
->VDMState
= DosRecord
->State
= VDM_NOT_READY
;
1025 Status
= STATUS_SUCCESS
;
1031 // TODO: WOW SUPPORT NOT IMPLEMENTED
1032 Status
= STATUS_NOT_IMPLEMENTED
;
1036 /* There is no command yet */
1037 if ((GetNextVdmCommandRequest
->VDMState
& (VDM_FLAG_DONT_WAIT
| VDM_FLAG_RETRY
))
1038 != (VDM_FLAG_DONT_WAIT
| VDM_FLAG_RETRY
))
1040 if (ConsoleRecord
->ServerEvent
)
1042 /* Reset the event */
1043 NtResetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1047 /* Create a pair of wait handles */
1048 Status
= BaseSrvCreatePairWaitHandles(&ConsoleRecord
->ServerEvent
,
1049 &ConsoleRecord
->ClientEvent
);
1050 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1053 /* Return the client event handle */
1054 GetNextVdmCommandRequest
->WaitObjectForVDM
= ConsoleRecord
->ClientEvent
;
1058 /* Leave the critical section */
1059 RtlLeaveCriticalSection(CriticalSection
);
1064 CSR_API(BaseSrvExitVDM
)
1067 PBASE_EXIT_VDM ExitVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitVDMRequest
;
1068 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
1069 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1070 PVDM_DOS_RECORD DosRecord
;
1072 CriticalSection
= (ExitVdmRequest
->iWowTask
== 0)
1073 ? &DosCriticalSection
1074 : &WowCriticalSection
;
1076 /* Enter the critical section */
1077 RtlEnterCriticalSection(CriticalSection
);
1079 if (ExitVdmRequest
->iWowTask
== 0)
1081 /* Get the console record */
1082 Status
= BaseSrvGetConsoleRecord(ExitVdmRequest
->ConsoleHandle
, &ConsoleRecord
);
1083 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1085 /* Cleanup the DOS records */
1086 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
1088 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
1092 /* Set the event and close it */
1093 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
1094 NtClose(DosRecord
->ServerEvent
);
1096 /* Remove the DOS entry */
1097 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1098 RemoveEntryList(&DosRecord
->Entry
);
1099 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1102 if (ConsoleRecord
->CurrentDirs
!= NULL
)
1104 /* Free the current directories */
1105 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
1106 ConsoleRecord
->CurrentDirs
= NULL
;
1107 ConsoleRecord
->CurDirsLength
= 0;
1110 /* Close the event handle */
1111 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
1113 /* Remove the console record */
1114 RemoveEntryList(&ConsoleRecord
->Entry
);
1115 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
1119 // TODO: NOT IMPLEMENTED
1121 Status
= STATUS_NOT_IMPLEMENTED
;
1125 /* Leave the critical section */
1126 RtlLeaveCriticalSection(CriticalSection
);
1131 CSR_API(BaseSrvIsFirstVDM
)
1133 PBASE_IS_FIRST_VDM IsFirstVDMRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.IsFirstVDMRequest
;
1135 /* Return the result */
1136 IsFirstVDMRequest
->FirstVDM
= FirstVDM
;
1138 /* Clear the first VDM flag */
1141 return STATUS_SUCCESS
;
1144 CSR_API(BaseSrvGetVDMExitCode
)
1147 PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetVDMExitCodeRequest
;
1148 PLIST_ENTRY i
= NULL
;
1149 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1150 PVDM_DOS_RECORD DosRecord
= NULL
;
1152 /* Enter the critical section */
1153 RtlEnterCriticalSection(&DosCriticalSection
);
1155 /* Get the console record */
1156 Status
= BaseSrvGetConsoleRecord(GetVDMExitCodeRequest
->ConsoleHandle
, &ConsoleRecord
);
1157 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1159 /* Search for a DOS record that has the same parent process handle */
1160 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
1162 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
1163 if (DosRecord
->ClientEvent
== GetVDMExitCodeRequest
->hParent
) break;
1166 /* Check if no DOS record was found */
1167 if (i
== &ConsoleRecord
->DosListHead
)
1169 Status
= STATUS_NOT_FOUND
;
1173 /* Check if this task is still running */
1174 if (DosRecord
->State
== VDM_READY
)
1176 GetVDMExitCodeRequest
->ExitCode
= STATUS_PENDING
;
1180 /* Return the exit code */
1181 GetVDMExitCodeRequest
->ExitCode
= DosRecord
->ExitCode
;
1183 /* Since this is a zombie task record, remove it */
1184 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1185 RemoveEntryList(&DosRecord
->Entry
);
1186 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1189 /* Leave the critical section */
1190 RtlLeaveCriticalSection(&DosCriticalSection
);
1195 CSR_API(BaseSrvSetReenterCount
)
1197 NTSTATUS Status
= STATUS_SUCCESS
;
1198 PBASE_SET_REENTER_COUNT SetReenterCountRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetReenterCountRequest
;
1199 PVDM_CONSOLE_RECORD ConsoleRecord
;
1201 /* Enter the critical section */
1202 RtlEnterCriticalSection(&DosCriticalSection
);
1204 /* Get the console record */
1205 Status
= BaseSrvGetConsoleRecord(SetReenterCountRequest
->ConsoleHandle
, &ConsoleRecord
);
1206 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1208 if (SetReenterCountRequest
->fIncDec
== VDM_INC_REENTER_COUNT
) ConsoleRecord
->ReenterCount
++;
1209 else if (SetReenterCountRequest
->fIncDec
== VDM_DEC_REENTER_COUNT
)
1211 ConsoleRecord
->ReenterCount
--;
1212 if (ConsoleRecord
->ServerEvent
!= NULL
) NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1214 else Status
= STATUS_INVALID_PARAMETER
;
1217 /* Leave the critical section */
1218 RtlLeaveCriticalSection(&DosCriticalSection
);
1223 CSR_API(BaseSrvSetVDMCurDirs
)
1226 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1227 PVDM_CONSOLE_RECORD ConsoleRecord
;
1228 PCHAR Buffer
= NULL
;
1230 /* Validate the input buffer */
1231 if (!CsrValidateMessageBuffer(ApiMessage
,
1232 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1233 VDMCurrentDirsRequest
->cchCurDirs
,
1234 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1236 return STATUS_INVALID_PARAMETER
;
1239 /* Enter the critical section */
1240 RtlEnterCriticalSection(&DosCriticalSection
);
1242 /* Find the console record */
1243 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1244 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1246 if (ConsoleRecord
->CurrentDirs
== NULL
)
1248 /* Allocate memory for the current directory information */
1249 Buffer
= RtlAllocateHeap(BaseSrvHeap
,
1251 VDMCurrentDirsRequest
->cchCurDirs
);
1255 /* Resize the amount of allocated memory */
1256 Buffer
= RtlReAllocateHeap(BaseSrvHeap
,
1258 ConsoleRecord
->CurrentDirs
,
1259 VDMCurrentDirsRequest
->cchCurDirs
);
1264 /* Allocation failed */
1265 Status
= STATUS_NO_MEMORY
;
1269 /* Update the console record */
1270 ConsoleRecord
->CurrentDirs
= Buffer
;
1271 ConsoleRecord
->CurDirsLength
= VDMCurrentDirsRequest
->cchCurDirs
;
1274 RtlMoveMemory(ConsoleRecord
->CurrentDirs
,
1275 VDMCurrentDirsRequest
->lpszzCurDirs
,
1276 VDMCurrentDirsRequest
->cchCurDirs
);
1279 /* Leave the critical section */
1280 RtlLeaveCriticalSection(&DosCriticalSection
);
1285 CSR_API(BaseSrvGetVDMCurDirs
)
1288 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1289 PVDM_CONSOLE_RECORD ConsoleRecord
;
1291 /* Validate the output buffer */
1292 if (!CsrValidateMessageBuffer(ApiMessage
,
1293 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1294 VDMCurrentDirsRequest
->cchCurDirs
,
1295 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1297 return STATUS_INVALID_PARAMETER
;
1300 /* Enter the critical section */
1301 RtlEnterCriticalSection(&DosCriticalSection
);
1303 /* Find the console record */
1304 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1305 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1307 /* Return the actual size of the current directory information */
1308 VDMCurrentDirsRequest
->cchCurDirs
= ConsoleRecord
->CurDirsLength
;
1310 /* Check if the buffer is large enough */
1311 if (VDMCurrentDirsRequest
->cchCurDirs
< ConsoleRecord
->CurDirsLength
)
1313 Status
= STATUS_BUFFER_TOO_SMALL
;
1318 RtlMoveMemory(VDMCurrentDirsRequest
->lpszzCurDirs
,
1319 ConsoleRecord
->CurrentDirs
,
1320 ConsoleRecord
->CurDirsLength
);
1323 /* Leave the critical section */
1324 RtlLeaveCriticalSection(&DosCriticalSection
);
1329 CSR_API(BaseSrvBatNotification
)
1331 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1332 return STATUS_NOT_IMPLEMENTED
;
1335 CSR_API(BaseSrvRegisterWowExec
)
1337 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1338 return STATUS_NOT_IMPLEMENTED
;
1341 CSR_API(BaseSrvRefreshIniFileMapping
)
1343 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1344 return STATUS_NOT_IMPLEMENTED
;