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 /* Search for a record that has the same console handle */
33 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
35 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
36 if (CurrentRecord
->ConsoleHandle
== ConsoleHandle
) break;
39 *Record
= CurrentRecord
;
40 return CurrentRecord
? STATUS_SUCCESS
: STATUS_NOT_FOUND
;
43 NTSTATUS NTAPI
GetConsoleRecordBySessionId(ULONG TaskId
, PVDM_CONSOLE_RECORD
*Record
)
46 PVDM_CONSOLE_RECORD CurrentRecord
= NULL
;
48 /* Search for a record that has the same console handle */
49 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
51 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
52 if (CurrentRecord
->SessionId
== TaskId
) break;
55 *Record
= CurrentRecord
;
56 return CurrentRecord
? STATUS_SUCCESS
: STATUS_NOT_FOUND
;
59 ULONG NTAPI
GetNextDosSesId(VOID
)
63 PVDM_CONSOLE_RECORD CurrentRecord
= NULL
;
66 /* Search for an available session ID */
67 for (SessionId
= 1; SessionId
!= 0; SessionId
++)
71 /* Check if the ID is already in use */
72 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
74 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
75 if (CurrentRecord
->SessionId
== SessionId
) Found
= TRUE
;
78 /* If not, we found one */
82 ASSERT(SessionId
!= 0);
84 /* Return the session ID */
88 BOOLEAN NTAPI
BaseSrvIsVdmAllowed(VOID
)
91 BOOLEAN VdmAllowed
= TRUE
;
92 HANDLE RootKey
, KeyHandle
;
93 UNICODE_STRING KeyName
, ValueName
, MachineKeyName
;
94 OBJECT_ATTRIBUTES Attributes
;
95 UCHAR ValueBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
96 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
99 /* Initialize the unicode strings */
100 RtlInitUnicodeString(&MachineKeyName
, L
"\\Registry\\Machine");
101 RtlInitUnicodeString(&KeyName
, VDM_POLICY_KEY_NAME
);
102 RtlInitUnicodeString(&ValueName
, VDM_DISALLOWED_VALUE_NAME
);
104 InitializeObjectAttributes(&Attributes
,
106 OBJ_CASE_INSENSITIVE
,
110 /* Open the local machine key */
111 Status
= NtOpenKey(&RootKey
, KEY_READ
, &Attributes
);
112 if (!NT_SUCCESS(Status
)) return FALSE
;
114 InitializeObjectAttributes(&Attributes
,
116 OBJ_CASE_INSENSITIVE
,
120 /* Open the policy key in the local machine hive, if it exists */
121 if (NT_SUCCESS(NtOpenKey(&KeyHandle
, KEY_READ
, &Attributes
)))
123 /* Read the value, if it's set */
124 if (NT_SUCCESS(NtQueryValueKey(KeyHandle
,
126 KeyValuePartialInformation
,
131 if (*((PULONG
)ValueInfo
->Data
))
133 /* The VDM has been disabled in the registry */
141 /* Close the local machine key */
144 /* If it's disabled system-wide, there's no need to check the user key */
145 if (!VdmAllowed
) return FALSE
;
147 /* Open the current user key of the client */
148 if (!CsrImpersonateClient(NULL
)) return VdmAllowed
;
149 Status
= RtlOpenCurrentUser(KEY_READ
, &RootKey
);
152 /* If that fails, return the system-wide setting */
153 if (!NT_SUCCESS(Status
)) return VdmAllowed
;
155 InitializeObjectAttributes(&Attributes
,
157 OBJ_CASE_INSENSITIVE
,
161 /* Open the policy key in the current user hive, if it exists */
162 if (NT_SUCCESS(NtOpenKey(&KeyHandle
, KEY_READ
, &Attributes
)))
164 /* Read the value, if it's set */
165 if (NT_SUCCESS(NtQueryValueKey(KeyHandle
,
167 KeyValuePartialInformation
,
172 if (*((PULONG
)ValueInfo
->Data
))
174 /* The VDM has been disabled in the registry */
185 NTSTATUS NTAPI
BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent
, PHANDLE ClientEvent
)
189 /* Create the event */
190 Status
= NtCreateEvent(ServerEvent
, EVENT_ALL_ACCESS
, NULL
, NotificationEvent
, FALSE
);
191 if (!NT_SUCCESS(Status
)) return Status
;
193 /* Duplicate the event into the client process */
194 Status
= NtDuplicateObject(NtCurrentProcess(),
196 CsrGetClientThread()->Process
->ProcessHandle
,
200 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
202 if (!NT_SUCCESS(Status
)) NtClose(*ServerEvent
);
206 VOID NTAPI
BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo
)
208 /* Free the allocated structure members */
209 if (CommandInfo
->CmdLine
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->CmdLine
);
210 if (CommandInfo
->AppName
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->AppName
);
211 if (CommandInfo
->PifFile
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->PifFile
);
212 if (CommandInfo
->CurDirectory
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->CurDirectory
);
213 if (CommandInfo
->Env
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Env
);
214 if (CommandInfo
->Desktop
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Desktop
);
215 if (CommandInfo
->Title
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Title
);
216 if (CommandInfo
->Reserved
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Reserved
);
218 /* Free the structure itself */
219 RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
);
222 VOID NTAPI
BaseSrvCleanupVdmRecords(ULONG ProcessId
)
225 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
226 PVDM_DOS_RECORD DosRecord
;
228 /* Enter the critical section */
229 RtlEnterCriticalSection(&DosCriticalSection
);
231 /* Search for a record that has the same process handle */
232 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
234 ConsoleRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
236 if (ConsoleRecord
->ProcessId
== ProcessId
)
238 /* Cleanup the DOS records */
239 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
241 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
245 /* Set the event and close it */
246 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
247 NtClose(DosRecord
->ServerEvent
);
249 /* Remove the DOS entry */
250 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
251 RemoveEntryList(&DosRecord
->Entry
);
252 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
255 if (ConsoleRecord
->CurrentDirs
!= NULL
)
257 /* Free the current directories */
258 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
259 ConsoleRecord
->CurrentDirs
= NULL
;
260 ConsoleRecord
->CurDirsLength
= 0;
263 /* Close the event handle */
264 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
266 /* Remove the console record */
268 RemoveEntryList(&ConsoleRecord
->Entry
);
269 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
273 /* Leave the critical section */
274 RtlLeaveCriticalSection(&DosCriticalSection
);
277 BOOLEAN NTAPI
BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest
, PVDM_DOS_RECORD DosRecord
)
279 BOOLEAN Success
= FALSE
;
280 PVDM_COMMAND_INFO CommandInfo
= NULL
;
282 /* Allocate the command information structure */
283 CommandInfo
= (PVDM_COMMAND_INFO
)RtlAllocateHeap(BaseSrvHeap
,
285 sizeof(VDM_COMMAND_INFO
));
286 if (CommandInfo
== NULL
) return FALSE
;
288 /* Fill the structure */
289 CommandInfo
->TaskId
= CheckVdmRequest
->iTask
;
290 CommandInfo
->ExitCode
= DosRecord
->ExitCode
;
291 CommandInfo
->CodePage
= CheckVdmRequest
->CodePage
;
292 CommandInfo
->StdIn
= CheckVdmRequest
->StdIn
;
293 CommandInfo
->StdOut
= CheckVdmRequest
->StdOut
;
294 CommandInfo
->StdErr
= CheckVdmRequest
->StdErr
;
296 /* Allocate memory for the command line */
297 CommandInfo
->CmdLine
= RtlAllocateHeap(BaseSrvHeap
,
299 CheckVdmRequest
->CmdLen
);
300 if (CommandInfo
->CmdLine
== NULL
) goto Cleanup
;
302 /* Copy the command line */
303 RtlMoveMemory(CommandInfo
->CmdLine
, CheckVdmRequest
->CmdLine
, CheckVdmRequest
->CmdLen
);
305 /* Allocate memory for the application name */
306 CommandInfo
->AppName
= RtlAllocateHeap(BaseSrvHeap
,
308 CheckVdmRequest
->AppLen
);
309 if (CommandInfo
->AppName
== NULL
) goto Cleanup
;
311 /* Copy the application name */
312 RtlMoveMemory(CommandInfo
->AppName
, CheckVdmRequest
->AppName
, CheckVdmRequest
->AppLen
);
314 /* Allocate memory for the PIF file name */
315 if (CheckVdmRequest
->PifLen
!= 0)
317 CommandInfo
->PifFile
= RtlAllocateHeap(BaseSrvHeap
,
319 CheckVdmRequest
->PifLen
);
320 if (CommandInfo
->PifFile
== NULL
) goto Cleanup
;
322 /* Copy the PIF file name */
323 RtlMoveMemory(CommandInfo
->PifFile
, CheckVdmRequest
->PifFile
, CheckVdmRequest
->PifLen
);
325 else CommandInfo
->PifFile
= NULL
;
327 /* Allocate memory for the current directory */
328 if (CheckVdmRequest
->CurDirectoryLen
!= 0)
330 CommandInfo
->CurDirectory
= RtlAllocateHeap(BaseSrvHeap
,
332 CheckVdmRequest
->CurDirectoryLen
);
333 if (CommandInfo
->CurDirectory
== NULL
) goto Cleanup
;
335 /* Copy the current directory */
336 RtlMoveMemory(CommandInfo
->CurDirectory
,
337 CheckVdmRequest
->CurDirectory
,
338 CheckVdmRequest
->CurDirectoryLen
);
340 else CommandInfo
->CurDirectory
= NULL
;
342 /* Allocate memory for the environment block */
343 CommandInfo
->Env
= RtlAllocateHeap(BaseSrvHeap
,
345 CheckVdmRequest
->EnvLen
);
346 if (CommandInfo
->Env
== NULL
) goto Cleanup
;
348 /* Copy the environment block */
349 RtlMoveMemory(CommandInfo
->Env
, CheckVdmRequest
->Env
, CheckVdmRequest
->EnvLen
);
351 CommandInfo
->EnvLen
= CheckVdmRequest
->EnvLen
;
352 RtlMoveMemory(&CommandInfo
->StartupInfo
,
353 CheckVdmRequest
->StartupInfo
,
354 sizeof(STARTUPINFOA
));
356 /* Allocate memory for the desktop */
357 if (CheckVdmRequest
->DesktopLen
!= 0)
359 CommandInfo
->Desktop
= RtlAllocateHeap(BaseSrvHeap
,
361 CheckVdmRequest
->DesktopLen
);
362 if (CommandInfo
->Desktop
== NULL
) goto Cleanup
;
364 /* Copy the desktop name */
365 RtlMoveMemory(CommandInfo
->Desktop
, CheckVdmRequest
->Desktop
, CheckVdmRequest
->DesktopLen
);
367 else CommandInfo
->Desktop
= NULL
;
369 CommandInfo
->DesktopLen
= CheckVdmRequest
->DesktopLen
;
371 /* Allocate memory for the title */
372 if (CheckVdmRequest
->TitleLen
!= 0)
374 CommandInfo
->Title
= RtlAllocateHeap(BaseSrvHeap
,
376 CheckVdmRequest
->TitleLen
);
377 if (CommandInfo
->Title
== NULL
) goto Cleanup
;
380 RtlMoveMemory(CommandInfo
->Title
, CheckVdmRequest
->Title
, CheckVdmRequest
->TitleLen
);
382 else CommandInfo
->Title
= NULL
;
384 CommandInfo
->TitleLen
= CheckVdmRequest
->TitleLen
;
386 /* Allocate memory for the reserved field */
387 if (CheckVdmRequest
->ReservedLen
!= 0)
389 CommandInfo
->Reserved
= RtlAllocateHeap(BaseSrvHeap
,
391 CheckVdmRequest
->ReservedLen
);
392 if (CommandInfo
->Reserved
== NULL
) goto Cleanup
;
394 /* Copy the reserved field */
395 RtlMoveMemory(CommandInfo
->Reserved
,
396 CheckVdmRequest
->Reserved
,
397 CheckVdmRequest
->ReservedLen
);
399 else CommandInfo
->Reserved
= NULL
;
401 CommandInfo
->ReservedLen
= CheckVdmRequest
->ReservedLen
;
403 CommandInfo
->CmdLen
= CheckVdmRequest
->CmdLen
;
404 CommandInfo
->AppLen
= CheckVdmRequest
->AppLen
;
405 CommandInfo
->PifLen
= CheckVdmRequest
->PifLen
;
406 CommandInfo
->CurDirectoryLen
= CheckVdmRequest
->CurDirectoryLen
;
407 CommandInfo
->VDMState
= DosRecord
->State
;
408 // TODO: Set CommandInfo->CurrentDrive
409 // TODO: Set CommandInfo->ComingFromBat
411 /* Set the DOS record's command structure */
412 DosRecord
->CommandInfo
= CommandInfo
;
414 /* The operation was successful */
418 /* If it wasn't successful, free the memory */
419 if (!Success
) BaseSrvFreeVDMInfo(CommandInfo
);
424 NTSTATUS NTAPI
BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo
,
425 PBASE_GET_NEXT_VDM_COMMAND Message
)
428 Message
->iTask
= CommandInfo
->TaskId
;
429 Message
->StdIn
= CommandInfo
->StdIn
;
430 Message
->StdOut
= CommandInfo
->StdOut
;
431 Message
->StdErr
= CommandInfo
->StdErr
;
432 Message
->CodePage
= CommandInfo
->CodePage
;
433 Message
->dwCreationFlags
= CommandInfo
->CreationFlags
;
434 Message
->ExitCode
= CommandInfo
->ExitCode
;
435 Message
->CurrentDrive
= CommandInfo
->CurrentDrive
;
436 Message
->VDMState
= CommandInfo
->VDMState
;
437 Message
->fComingFromBat
= CommandInfo
->ComingFromBat
;
439 if (CommandInfo
->CmdLen
&& Message
->CmdLen
)
441 if (Message
->CmdLen
< CommandInfo
->CmdLen
) return STATUS_BUFFER_TOO_SMALL
;
443 /* Copy the command line */
444 RtlMoveMemory(Message
->CmdLine
, CommandInfo
->CmdLine
, CommandInfo
->CmdLen
);
445 Message
->CmdLen
= CommandInfo
->CmdLen
;
448 if (CommandInfo
->AppLen
&& Message
->AppLen
)
450 if (Message
->AppLen
< CommandInfo
->CmdLen
) return STATUS_BUFFER_TOO_SMALL
;
452 /* Copy the application name */
453 RtlMoveMemory(Message
->AppName
, CommandInfo
->AppName
, CommandInfo
->AppLen
);
454 Message
->AppLen
= CommandInfo
->AppLen
;
457 if (CommandInfo
->PifLen
&& Message
->PifLen
)
459 if (Message
->PifLen
< CommandInfo
->PifLen
) return STATUS_BUFFER_TOO_SMALL
;
461 /* Copy the PIF file name */
462 RtlMoveMemory(Message
->PifFile
, CommandInfo
->PifFile
, CommandInfo
->PifLen
);
463 Message
->PifLen
= CommandInfo
->PifLen
;
466 if (CommandInfo
->CurDirectoryLen
&& Message
->CurDirectoryLen
)
468 if (Message
->CurDirectoryLen
< CommandInfo
->CurDirectoryLen
) return STATUS_BUFFER_TOO_SMALL
;
470 /* Copy the current directory */
471 RtlMoveMemory(Message
->CurDirectory
, CommandInfo
->CurDirectory
, CommandInfo
->CurDirectoryLen
);
472 Message
->CurDirectoryLen
= CommandInfo
->CurDirectoryLen
;
475 if (CommandInfo
->EnvLen
&& Message
->EnvLen
)
477 if (Message
->EnvLen
< CommandInfo
->EnvLen
) return STATUS_BUFFER_TOO_SMALL
;
479 /* Copy the environment */
480 RtlMoveMemory(Message
->Env
, CommandInfo
->Env
, CommandInfo
->EnvLen
);
481 Message
->EnvLen
= CommandInfo
->EnvLen
;
484 /* Copy the startup info */
485 RtlMoveMemory(Message
->StartupInfo
,
486 &CommandInfo
->StartupInfo
,
487 sizeof(STARTUPINFOA
));
489 if (CommandInfo
->DesktopLen
&& Message
->DesktopLen
)
491 if (Message
->DesktopLen
< CommandInfo
->DesktopLen
) return STATUS_BUFFER_TOO_SMALL
;
493 /* Copy the desktop name */
494 RtlMoveMemory(Message
->Desktop
, CommandInfo
->Desktop
, CommandInfo
->DesktopLen
);
495 Message
->DesktopLen
= CommandInfo
->DesktopLen
;
498 if (CommandInfo
->TitleLen
&& Message
->TitleLen
)
500 if (Message
->TitleLen
< CommandInfo
->TitleLen
) return STATUS_BUFFER_TOO_SMALL
;
503 RtlMoveMemory(Message
->Title
, CommandInfo
->Title
, CommandInfo
->TitleLen
);
504 Message
->TitleLen
= CommandInfo
->TitleLen
;
507 if (CommandInfo
->ReservedLen
&& Message
->ReservedLen
)
509 if (Message
->ReservedLen
< CommandInfo
->ReservedLen
) return STATUS_BUFFER_TOO_SMALL
;
511 /* Copy the reserved parameter */
512 RtlMoveMemory(Message
->Reserved
, CommandInfo
->Reserved
, CommandInfo
->ReservedLen
);
513 Message
->ReservedLen
= CommandInfo
->ReservedLen
;
516 return STATUS_SUCCESS
;
519 VOID NTAPI
BaseInitializeVDM(VOID
)
521 /* Initialize the list head */
522 InitializeListHead(&VDMConsoleListHead
);
524 /* Initialize the critical section */
525 RtlInitializeCriticalSection(&DosCriticalSection
);
526 RtlInitializeCriticalSection(&WowCriticalSection
);
529 /* PUBLIC SERVER APIS *********************************************************/
531 CSR_API(BaseSrvCheckVDM
)
534 PBASE_CHECK_VDM CheckVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CheckVDMRequest
;
535 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
536 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
537 PVDM_DOS_RECORD DosRecord
= NULL
;
538 BOOLEAN NewConsoleRecord
= FALSE
;
540 /* Don't do anything if the VDM has been disabled in the registry */
541 if (!BaseSrvIsVdmAllowed()) return STATUS_ACCESS_DENIED
;
543 /* Validate the message buffers */
544 if (!CsrValidateMessageBuffer(ApiMessage
,
545 (PVOID
*)&CheckVdmRequest
->CmdLine
,
546 CheckVdmRequest
->CmdLen
,
547 sizeof(*CheckVdmRequest
->CmdLine
))
548 || !CsrValidateMessageBuffer(ApiMessage
,
549 (PVOID
*)&CheckVdmRequest
->AppName
,
550 CheckVdmRequest
->AppLen
,
551 sizeof(*CheckVdmRequest
->AppName
))
552 || !CsrValidateMessageBuffer(ApiMessage
,
553 (PVOID
*)&CheckVdmRequest
->PifFile
,
554 CheckVdmRequest
->PifLen
,
555 sizeof(*CheckVdmRequest
->PifFile
))
556 || !CsrValidateMessageBuffer(ApiMessage
,
557 (PVOID
*)&CheckVdmRequest
->CurDirectory
,
558 CheckVdmRequest
->CurDirectoryLen
,
559 sizeof(*CheckVdmRequest
->CurDirectory
))
560 || !CsrValidateMessageBuffer(ApiMessage
,
561 (PVOID
*)&CheckVdmRequest
->Desktop
,
562 CheckVdmRequest
->DesktopLen
,
563 sizeof(*CheckVdmRequest
->Desktop
))
564 || !CsrValidateMessageBuffer(ApiMessage
,
565 (PVOID
*)&CheckVdmRequest
->Title
,
566 CheckVdmRequest
->TitleLen
,
567 sizeof(*CheckVdmRequest
->Title
))
568 || !CsrValidateMessageBuffer(ApiMessage
,
569 (PVOID
*)&CheckVdmRequest
->Reserved
,
570 CheckVdmRequest
->ReservedLen
,
571 sizeof(*CheckVdmRequest
->Reserved
)))
573 return STATUS_INVALID_PARAMETER
;
576 CriticalSection
= (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
577 ? &DosCriticalSection
578 : &WowCriticalSection
;
580 /* Enter the critical section */
581 RtlEnterCriticalSection(CriticalSection
);
583 /* Check if this is a DOS or WOW VDM */
584 if (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
586 /* Get the console record */
587 Status
= BaseSrvGetConsoleRecord(CheckVdmRequest
->ConsoleHandle
,
590 if (!NT_SUCCESS(Status
))
592 /* Allocate a new console record */
593 ConsoleRecord
= (PVDM_CONSOLE_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
595 sizeof(VDM_CONSOLE_RECORD
));
596 if (ConsoleRecord
== NULL
)
598 Status
= STATUS_NO_MEMORY
;
602 /* Remember that the console record was allocated here */
603 NewConsoleRecord
= TRUE
;
605 /* Initialize the console record */
606 ConsoleRecord
->ConsoleHandle
= CheckVdmRequest
->ConsoleHandle
;
607 ConsoleRecord
->ProcessHandle
= CsrGetClientThread()->Process
->ProcessHandle
;
608 ConsoleRecord
->ServerEvent
= ConsoleRecord
->ClientEvent
= NULL
;
609 ConsoleRecord
->ReenterCount
= 0;
610 ConsoleRecord
->CurrentDirs
= NULL
;
611 ConsoleRecord
->CurDirsLength
= 0;
612 ConsoleRecord
->SessionId
= GetNextDosSesId();
613 InitializeListHead(&ConsoleRecord
->DosListHead
);
616 /* Allocate a new DOS record */
617 DosRecord
= (PVDM_DOS_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
619 sizeof(VDM_DOS_RECORD
));
620 if (DosRecord
== NULL
)
622 Status
= STATUS_NO_MEMORY
;
626 /* Initialize the DOS record */
627 DosRecord
->State
= VDM_NOT_LOADED
;
628 DosRecord
->ExitCode
= 0;
630 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
, &DosRecord
->ClientEvent
);
631 if (!NT_SUCCESS(Status
)) goto Cleanup
;
633 /* Return the client event handle */
634 CheckVdmRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
636 /* Translate the input structure into a VDM command structure and set it in the DOS record */
637 if (!BaseSrvCopyCommand(CheckVdmRequest
, DosRecord
))
639 /* The only possibility is that an allocation failure occurred */
640 Status
= STATUS_NO_MEMORY
;
644 /* Add the DOS record */
645 InsertHeadList(&ConsoleRecord
->DosListHead
, &DosRecord
->Entry
);
647 if (ConsoleRecord
->ServerEvent
)
649 /* Signal the session event */
650 NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
653 if (NewConsoleRecord
)
655 /* Add the console record */
656 InsertTailList(&VDMConsoleListHead
, &ConsoleRecord
->Entry
);
659 CheckVdmRequest
->VDMState
= NewConsoleRecord
? VDM_NOT_LOADED
: VDM_READY
;
660 Status
= STATUS_SUCCESS
;
664 // TODO: NOT IMPLEMENTED
666 Status
= STATUS_NOT_IMPLEMENTED
;
670 /* Check if it failed */
671 if (!NT_SUCCESS(Status
))
673 /* Free the DOS record */
674 if (DosRecord
!= NULL
)
676 if (DosRecord
->ServerEvent
) NtClose(DosRecord
->ServerEvent
);
677 if (DosRecord
->ClientEvent
)
679 /* Close the remote handle */
680 NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
681 DosRecord
->ClientEvent
,
686 DUPLICATE_CLOSE_SOURCE
);
689 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
693 /* Free the console record if it was allocated here */
694 if (NewConsoleRecord
)
696 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
697 ConsoleRecord
= NULL
;
701 /* Leave the critical section */
702 RtlLeaveCriticalSection(CriticalSection
);
707 CSR_API(BaseSrvUpdateVDMEntry
)
710 PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.UpdateVDMEntryRequest
;
711 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
712 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
713 PVDM_DOS_RECORD DosRecord
= NULL
;
715 CriticalSection
= (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
716 ? &DosCriticalSection
717 : &WowCriticalSection
;
719 /* Enter the critical section */
720 RtlEnterCriticalSection(CriticalSection
);
722 /* Check if this is a DOS or WOW VDM */
723 if (UpdateVdmEntryRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
725 if (UpdateVdmEntryRequest
->iTask
!= 0)
727 /* Get the console record using the task ID */
728 Status
= GetConsoleRecordBySessionId(UpdateVdmEntryRequest
->iTask
,
733 /* Get the console record using the console handle */
734 Status
= BaseSrvGetConsoleRecord(UpdateVdmEntryRequest
->ConsoleHandle
,
738 if (!NT_SUCCESS(Status
)) goto Cleanup
;
740 /* Get the primary DOS record */
741 DosRecord
= (PVDM_DOS_RECORD
)CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
745 switch (UpdateVdmEntryRequest
->EntryIndex
)
749 /* Close the server event handle, the client will close the client handle */
750 NtClose(DosRecord
->ServerEvent
);
751 DosRecord
->ServerEvent
= DosRecord
->ClientEvent
= NULL
;
753 if (UpdateVdmEntryRequest
->VDMCreationState
& (VDM_UNDO_PARTIAL
| VDM_UNDO_FULL
))
755 /* Remove the DOS record */
756 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
757 RemoveEntryList(&DosRecord
->Entry
);
758 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
761 * Since this is an undo, if that was the only DOS record the VDM
762 * won't even start, so the console record should be removed too.
764 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
766 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
767 RemoveEntryList(&ConsoleRecord
->Entry
);
768 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
772 /* It was successful */
773 Status
= STATUS_SUCCESS
;
778 case VdmEntryUpdateProcess
:
780 /* Duplicate the VDM process handle */
781 Status
= NtDuplicateObject(CsrGetClientThread()->Process
->ProcessHandle
,
782 UpdateVdmEntryRequest
->VDMProcessHandle
,
784 &ConsoleRecord
->ProcessHandle
,
787 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
788 if (!NT_SUCCESS(Status
)) goto Cleanup
;
790 /* Create a pair of handles to one event object */
791 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
,
792 &DosRecord
->ClientEvent
);
793 if (!NT_SUCCESS(Status
)) goto Cleanup
;
795 /* Return the client event handle */
796 UpdateVdmEntryRequest
->WaitObjectForParent
= DosRecord
->ClientEvent
;
801 case VdmEntryUpdateControlCHandler
:
803 // TODO: NOT IMPLEMENTED
804 DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!");
805 Status
= STATUS_NOT_IMPLEMENTED
;
813 Status
= STATUS_INVALID_PARAMETER
;
819 // TODO: NOT IMPLEMENTED
821 Status
= STATUS_NOT_IMPLEMENTED
;
825 /* Leave the critical section */
826 RtlLeaveCriticalSection(CriticalSection
);
831 CSR_API(BaseSrvGetNextVDMCommand
)
834 PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest
=
835 &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetNextVDMCommandRequest
;
836 PRTL_CRITICAL_SECTION CriticalSection
;
837 PLIST_ENTRY i
= NULL
;
838 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
839 PVDM_DOS_RECORD DosRecord
= NULL
;
841 /* Validate the message buffers */
842 if (!CsrValidateMessageBuffer(ApiMessage
,
843 (PVOID
*)&GetNextVdmCommandRequest
->CmdLine
,
844 GetNextVdmCommandRequest
->CmdLen
,
845 sizeof(*GetNextVdmCommandRequest
->CmdLine
))
846 || !CsrValidateMessageBuffer(ApiMessage
,
847 (PVOID
*)&GetNextVdmCommandRequest
->AppName
,
848 GetNextVdmCommandRequest
->AppLen
,
849 sizeof(*GetNextVdmCommandRequest
->AppName
))
850 || !CsrValidateMessageBuffer(ApiMessage
,
851 (PVOID
*)&GetNextVdmCommandRequest
->PifFile
,
852 GetNextVdmCommandRequest
->PifLen
,
853 sizeof(*GetNextVdmCommandRequest
->PifFile
))
854 || !CsrValidateMessageBuffer(ApiMessage
,
855 (PVOID
*)&GetNextVdmCommandRequest
->CurDirectory
,
856 GetNextVdmCommandRequest
->CurDirectoryLen
,
857 sizeof(*GetNextVdmCommandRequest
->CurDirectory
))
858 || !CsrValidateMessageBuffer(ApiMessage
,
859 (PVOID
*)&GetNextVdmCommandRequest
->Env
,
860 GetNextVdmCommandRequest
->EnvLen
,
861 sizeof(*GetNextVdmCommandRequest
->Env
))
862 || !CsrValidateMessageBuffer(ApiMessage
,
863 (PVOID
*)&GetNextVdmCommandRequest
->Desktop
,
864 GetNextVdmCommandRequest
->DesktopLen
,
865 sizeof(*GetNextVdmCommandRequest
->Desktop
))
866 || !CsrValidateMessageBuffer(ApiMessage
,
867 (PVOID
*)&GetNextVdmCommandRequest
->Title
,
868 GetNextVdmCommandRequest
->TitleLen
,
869 sizeof(*GetNextVdmCommandRequest
->Title
))
870 || !CsrValidateMessageBuffer(ApiMessage
,
871 (PVOID
*)&GetNextVdmCommandRequest
->Reserved
,
872 GetNextVdmCommandRequest
->ReservedLen
,
873 sizeof(*GetNextVdmCommandRequest
->Reserved
))
874 || !CsrValidateMessageBuffer(ApiMessage
,
875 (PVOID
*)&GetNextVdmCommandRequest
->StartupInfo
,
877 sizeof(STARTUPINFOA
)))
879 return STATUS_INVALID_PARAMETER
;
882 CriticalSection
= (GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
)
883 ? &WowCriticalSection
884 : &DosCriticalSection
;
886 /* Enter the critical section */
887 RtlEnterCriticalSection(CriticalSection
);
889 if (!(GetNextVdmCommandRequest
->VDMState
& VDM_FLAG_WOW
))
891 if (GetNextVdmCommandRequest
->iTask
!= 0)
893 /* Get the console record using the task ID */
894 Status
= GetConsoleRecordBySessionId(GetNextVdmCommandRequest
->iTask
,
899 /* Get the console record using the console handle */
900 Status
= BaseSrvGetConsoleRecord(GetNextVdmCommandRequest
->ConsoleHandle
,
904 /* Make sure we found the console record */
905 if (!NT_SUCCESS(Status
)) goto Cleanup
;
907 /* Return the session ID */
908 GetNextVdmCommandRequest
->iTask
= ConsoleRecord
->SessionId
;
909 GetNextVdmCommandRequest
->WaitObjectForVDM
= NULL
;
911 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_FIRST_COMMAND
)
913 /* Check if the DOS record list is empty */
914 if (ConsoleRecord
->DosListHead
.Flink
== &ConsoleRecord
->DosListHead
)
916 Status
= STATUS_INVALID_PARAMETER
;
920 /* Get the first DOS record */
921 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
, VDM_DOS_RECORD
, Entry
);
923 /* Make sure its command information is still there */
924 if (DosRecord
->CommandInfo
== NULL
)
926 Status
= STATUS_INVALID_PARAMETER
;
930 /* Fill the command information */
931 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
935 /* Check if we should set the state of a running DOS record to ready */
936 if (!(GetNextVdmCommandRequest
->VDMState
937 & (VDM_FLAG_FIRST_TASK
| VDM_FLAG_RETRY
| VDM_FLAG_NESTED_TASK
)))
939 /* Search for a DOS record that is currently running */
940 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
942 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
943 if (DosRecord
->State
== VDM_NOT_READY
) break;
946 /* Check if we found any */
947 if (i
== &ConsoleRecord
->DosListHead
)
949 Status
= STATUS_INVALID_PARAMETER
;
953 /* Set the exit code */
954 DosRecord
->ExitCode
= GetNextVdmCommandRequest
->ExitCode
;
956 /* Update the VDM state */
957 DosRecord
->State
= VDM_READY
;
959 /* Notify all waiting threads that the task is finished */
960 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
961 NtClose(DosRecord
->ServerEvent
);
962 DosRecord
->ServerEvent
= NULL
;
965 /* Search for a DOS record that isn't loaded yet */
966 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
968 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
969 if (DosRecord
->State
== VDM_NOT_LOADED
) break;
972 if (i
!= &ConsoleRecord
->DosListHead
)
974 /* DOS tasks which haven't been loaded yet should have a command info structure */
975 ASSERT(DosRecord
->CommandInfo
!= NULL
);
977 /* Check if the caller only wants environment data */
978 if (GetNextVdmCommandRequest
->VDMState
& VDM_GET_ENVIRONMENT
)
980 if (GetNextVdmCommandRequest
->EnvLen
< DosRecord
->CommandInfo
->EnvLen
)
982 /* Not enough space was reserved */
983 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
984 Status
= STATUS_BUFFER_OVERFLOW
;
988 /* Copy the environment data */
989 RtlMoveMemory(GetNextVdmCommandRequest
->Env
,
990 DosRecord
->CommandInfo
->Env
,
991 DosRecord
->CommandInfo
->EnvLen
);
993 /* Return the actual size to the caller */
994 GetNextVdmCommandRequest
->EnvLen
= DosRecord
->CommandInfo
->EnvLen
;
998 /* Fill the command information */
999 Status
= BaseSrvFillCommandInfo(DosRecord
->CommandInfo
, GetNextVdmCommandRequest
);
1001 /* Free the command information, it's no longer needed */
1002 BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1003 DosRecord
->CommandInfo
= NULL
;
1005 /* Update the VDM state */
1006 GetNextVdmCommandRequest
->VDMState
= DosRecord
->State
= VDM_NOT_READY
;
1009 Status
= STATUS_SUCCESS
;
1015 // TODO: WOW SUPPORT NOT IMPLEMENTED
1016 Status
= STATUS_NOT_IMPLEMENTED
;
1020 /* There is no command yet */
1021 if ((GetNextVdmCommandRequest
->VDMState
& (VDM_FLAG_DONT_WAIT
| VDM_FLAG_RETRY
))
1022 != (VDM_FLAG_DONT_WAIT
| VDM_FLAG_RETRY
))
1024 if (ConsoleRecord
->ServerEvent
)
1026 /* Reset the event */
1027 NtResetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1031 /* Create a pair of wait handles */
1032 Status
= BaseSrvCreatePairWaitHandles(&ConsoleRecord
->ServerEvent
,
1033 &ConsoleRecord
->ClientEvent
);
1034 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1037 /* Return the client event handle */
1038 GetNextVdmCommandRequest
->WaitObjectForVDM
= ConsoleRecord
->ClientEvent
;
1042 /* Leave the critical section */
1043 RtlLeaveCriticalSection(CriticalSection
);
1048 CSR_API(BaseSrvExitVDM
)
1051 PBASE_EXIT_VDM ExitVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitVDMRequest
;
1052 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
1053 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1054 PVDM_DOS_RECORD DosRecord
;
1056 CriticalSection
= (ExitVdmRequest
->iWowTask
== 0)
1057 ? &DosCriticalSection
1058 : &WowCriticalSection
;
1060 /* Enter the critical section */
1061 RtlEnterCriticalSection(CriticalSection
);
1063 if (ExitVdmRequest
->iWowTask
== 0)
1065 /* Get the console record */
1066 Status
= BaseSrvGetConsoleRecord(ExitVdmRequest
->ConsoleHandle
, &ConsoleRecord
);
1067 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1069 /* Cleanup the DOS records */
1070 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
1072 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
1076 /* Set the event and close it */
1077 NtSetEvent(DosRecord
->ServerEvent
, NULL
);
1078 NtClose(DosRecord
->ServerEvent
);
1080 /* Remove the DOS entry */
1081 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1082 RemoveEntryList(&DosRecord
->Entry
);
1083 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1086 if (ConsoleRecord
->CurrentDirs
!= NULL
)
1088 /* Free the current directories */
1089 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
1090 ConsoleRecord
->CurrentDirs
= NULL
;
1091 ConsoleRecord
->CurDirsLength
= 0;
1094 /* Close the event handle */
1095 if (ConsoleRecord
->ServerEvent
) NtClose(ConsoleRecord
->ServerEvent
);
1097 /* Remove the console record */
1098 RemoveEntryList(&ConsoleRecord
->Entry
);
1099 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
1103 // TODO: NOT IMPLEMENTED
1105 Status
= STATUS_NOT_IMPLEMENTED
;
1109 /* Leave the critical section */
1110 RtlLeaveCriticalSection(CriticalSection
);
1115 CSR_API(BaseSrvIsFirstVDM
)
1117 PBASE_IS_FIRST_VDM IsFirstVDMRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.IsFirstVDMRequest
;
1119 /* Return the result */
1120 IsFirstVDMRequest
->FirstVDM
= FirstVDM
;
1122 /* Clear the first VDM flag */
1125 return STATUS_SUCCESS
;
1128 CSR_API(BaseSrvGetVDMExitCode
)
1131 PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetVDMExitCodeRequest
;
1132 PLIST_ENTRY i
= NULL
;
1133 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
1134 PVDM_DOS_RECORD DosRecord
= NULL
;
1136 /* Enter the critical section */
1137 RtlEnterCriticalSection(&DosCriticalSection
);
1139 /* Get the console record */
1140 Status
= BaseSrvGetConsoleRecord(GetVDMExitCodeRequest
->ConsoleHandle
, &ConsoleRecord
);
1141 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1143 /* Search for a DOS record that has the same parent process handle */
1144 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
1146 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
1147 if (DosRecord
->ClientEvent
== GetVDMExitCodeRequest
->hParent
) break;
1150 /* Check if no DOS record was found */
1151 if (i
== &ConsoleRecord
->DosListHead
)
1153 Status
= STATUS_NOT_FOUND
;
1157 /* Check if this task is still running */
1158 if (DosRecord
->State
== VDM_READY
)
1160 GetVDMExitCodeRequest
->ExitCode
= STATUS_PENDING
;
1164 /* Return the exit code */
1165 GetVDMExitCodeRequest
->ExitCode
= DosRecord
->ExitCode
;
1167 /* Since this is a zombie task record, remove it */
1168 if (DosRecord
->CommandInfo
) BaseSrvFreeVDMInfo(DosRecord
->CommandInfo
);
1169 RemoveEntryList(&DosRecord
->Entry
);
1170 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
1173 /* Leave the critical section */
1174 RtlLeaveCriticalSection(&DosCriticalSection
);
1179 CSR_API(BaseSrvSetReenterCount
)
1181 NTSTATUS Status
= STATUS_SUCCESS
;
1182 PBASE_SET_REENTER_COUNT SetReenterCountRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetReenterCountRequest
;
1183 PVDM_CONSOLE_RECORD ConsoleRecord
;
1185 /* Enter the critical section */
1186 RtlEnterCriticalSection(&DosCriticalSection
);
1188 /* Get the console record */
1189 Status
= BaseSrvGetConsoleRecord(SetReenterCountRequest
->ConsoleHandle
, &ConsoleRecord
);
1190 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1192 if (SetReenterCountRequest
->fIncDec
== VDM_INC_REENTER_COUNT
) ConsoleRecord
->ReenterCount
++;
1193 else if (SetReenterCountRequest
->fIncDec
== VDM_DEC_REENTER_COUNT
)
1195 ConsoleRecord
->ReenterCount
--;
1196 if (ConsoleRecord
->ServerEvent
!= NULL
) NtSetEvent(ConsoleRecord
->ServerEvent
, NULL
);
1198 else Status
= STATUS_INVALID_PARAMETER
;
1201 /* Leave the critical section */
1202 RtlLeaveCriticalSection(&DosCriticalSection
);
1207 CSR_API(BaseSrvSetVDMCurDirs
)
1210 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1211 PVDM_CONSOLE_RECORD ConsoleRecord
;
1212 PCHAR Buffer
= NULL
;
1214 /* Validate the input buffer */
1215 if (!CsrValidateMessageBuffer(ApiMessage
,
1216 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1217 VDMCurrentDirsRequest
->cchCurDirs
,
1218 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1220 return STATUS_INVALID_PARAMETER
;
1223 /* Enter the critical section */
1224 RtlEnterCriticalSection(&DosCriticalSection
);
1226 /* Find the console record */
1227 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1228 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1230 if (ConsoleRecord
->CurrentDirs
== NULL
)
1232 /* Allocate memory for the current directory information */
1233 Buffer
= RtlAllocateHeap(BaseSrvHeap
,
1235 VDMCurrentDirsRequest
->cchCurDirs
);
1239 /* Resize the amount of allocated memory */
1240 Buffer
= RtlReAllocateHeap(BaseSrvHeap
,
1242 ConsoleRecord
->CurrentDirs
,
1243 VDMCurrentDirsRequest
->cchCurDirs
);
1248 /* Allocation failed */
1249 Status
= STATUS_NO_MEMORY
;
1253 /* Update the console record */
1254 ConsoleRecord
->CurrentDirs
= Buffer
;
1255 ConsoleRecord
->CurDirsLength
= VDMCurrentDirsRequest
->cchCurDirs
;
1258 RtlMoveMemory(ConsoleRecord
->CurrentDirs
,
1259 VDMCurrentDirsRequest
->lpszzCurDirs
,
1260 VDMCurrentDirsRequest
->cchCurDirs
);
1263 /* Leave the critical section */
1264 RtlLeaveCriticalSection(&DosCriticalSection
);
1269 CSR_API(BaseSrvGetVDMCurDirs
)
1272 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
1273 PVDM_CONSOLE_RECORD ConsoleRecord
;
1275 /* Validate the output buffer */
1276 if (!CsrValidateMessageBuffer(ApiMessage
,
1277 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
1278 VDMCurrentDirsRequest
->cchCurDirs
,
1279 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
1281 return STATUS_INVALID_PARAMETER
;
1284 /* Enter the critical section */
1285 RtlEnterCriticalSection(&DosCriticalSection
);
1287 /* Find the console record */
1288 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
1289 if (!NT_SUCCESS(Status
)) goto Cleanup
;
1291 /* Return the actual size of the current directory information */
1292 VDMCurrentDirsRequest
->cchCurDirs
= ConsoleRecord
->CurDirsLength
;
1294 /* Check if the buffer is large enough */
1295 if (VDMCurrentDirsRequest
->cchCurDirs
< ConsoleRecord
->CurDirsLength
)
1297 Status
= STATUS_BUFFER_TOO_SMALL
;
1302 RtlMoveMemory(VDMCurrentDirsRequest
->lpszzCurDirs
,
1303 ConsoleRecord
->CurrentDirs
,
1304 ConsoleRecord
->CurDirsLength
);
1307 /* Leave the critical section */
1308 RtlLeaveCriticalSection(&DosCriticalSection
);
1313 CSR_API(BaseSrvBatNotification
)
1315 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1316 return STATUS_NOT_IMPLEMENTED
;
1319 CSR_API(BaseSrvRegisterWowExec
)
1321 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1322 return STATUS_NOT_IMPLEMENTED
;
1325 CSR_API(BaseSrvRefreshIniFileMapping
)
1327 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
1328 return STATUS_NOT_IMPLEMENTED
;