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 ULONG NTAPI
GetNextDosSesId(VOID
)
47 PVDM_CONSOLE_RECORD CurrentRecord
= NULL
;
50 /* Search for an available session ID */
51 for (SessionId
= 1; SessionId
!= 0; SessionId
++)
55 /* Check if the ID is already in use */
56 for (i
= VDMConsoleListHead
.Flink
; i
!= &VDMConsoleListHead
; i
= i
->Flink
)
58 CurrentRecord
= CONTAINING_RECORD(i
, VDM_CONSOLE_RECORD
, Entry
);
59 if (CurrentRecord
->SessionId
== SessionId
) Found
= TRUE
;
62 /* If not, we found one */
66 ASSERT(SessionId
!= 0);
68 /* Return the session ID */
72 BOOLEAN NTAPI
BaseSrvIsVdmAllowed(VOID
)
75 BOOLEAN VdmAllowed
= TRUE
;
76 HANDLE RootKey
, KeyHandle
;
77 UNICODE_STRING KeyName
, ValueName
, MachineKeyName
;
78 OBJECT_ATTRIBUTES Attributes
;
79 UCHAR ValueBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(ULONG
)];
80 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
83 /* Initialize the unicode strings */
84 RtlInitUnicodeString(&MachineKeyName
, L
"\\Registry\\Machine");
85 RtlInitUnicodeString(&KeyName
, VDM_POLICY_KEY_NAME
);
86 RtlInitUnicodeString(&ValueName
, VDM_DISALLOWED_VALUE_NAME
);
88 InitializeObjectAttributes(&Attributes
,
94 /* Open the local machine key */
95 Status
= NtOpenKey(&RootKey
, KEY_READ
, &Attributes
);
96 if (!NT_SUCCESS(Status
)) return FALSE
;
98 InitializeObjectAttributes(&Attributes
,
100 OBJ_CASE_INSENSITIVE
,
104 /* Open the policy key in the local machine hive, if it exists */
105 if (NT_SUCCESS(NtOpenKey(&KeyHandle
, KEY_READ
, &Attributes
)))
107 /* Read the value, if it's set */
108 if (NT_SUCCESS(NtQueryValueKey(KeyHandle
,
110 KeyValuePartialInformation
,
115 if (*((PULONG
)ValueInfo
->Data
))
117 /* The VDM has been disabled in the registry */
125 /* Close the local machine key */
128 /* If it's disabled system-wide, there's no need to check the user key */
129 if (!VdmAllowed
) return FALSE
;
131 /* Open the current user key of the client */
132 if (!CsrImpersonateClient(NULL
)) return VdmAllowed
;
133 Status
= RtlOpenCurrentUser(KEY_READ
, &RootKey
);
136 /* If that fails, return the system-wide setting */
137 if (!NT_SUCCESS(Status
)) return VdmAllowed
;
139 InitializeObjectAttributes(&Attributes
,
141 OBJ_CASE_INSENSITIVE
,
145 /* Open the policy key in the current user hive, if it exists */
146 if (NT_SUCCESS(NtOpenKey(&KeyHandle
, KEY_READ
, &Attributes
)))
148 /* Read the value, if it's set */
149 if (NT_SUCCESS(NtQueryValueKey(KeyHandle
,
151 KeyValuePartialInformation
,
156 if (*((PULONG
)ValueInfo
->Data
))
158 /* The VDM has been disabled in the registry */
169 NTSTATUS NTAPI
BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent
, PHANDLE ClientEvent
)
173 /* Create the event */
174 Status
= NtCreateEvent(ServerEvent
, EVENT_ALL_ACCESS
, NULL
, NotificationEvent
, FALSE
);
175 if (!NT_SUCCESS(Status
)) return Status
;
177 /* Duplicate the event into the client process */
178 Status
= NtDuplicateObject(NtCurrentProcess(),
180 CsrGetClientThread()->Process
->ProcessHandle
,
184 DUPLICATE_SAME_ATTRIBUTES
| DUPLICATE_SAME_ACCESS
);
186 if (!NT_SUCCESS(Status
)) NtClose(*ServerEvent
);
190 VOID
BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo
)
192 /* Free the allocated structure members */
193 if (CommandInfo
->CmdLine
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->CmdLine
);
194 if (CommandInfo
->AppName
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->AppName
);
195 if (CommandInfo
->PifFile
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->PifFile
);
196 if (CommandInfo
->CurDirectory
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->CurDirectory
);
197 if (CommandInfo
->Env
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Env
);
198 if (CommandInfo
->Desktop
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Desktop
);
199 if (CommandInfo
->Title
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Title
);
200 if (CommandInfo
->Reserved
!= NULL
) RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
->Reserved
);
202 /* Free the structure itself */
203 RtlFreeHeap(BaseSrvHeap
, 0, CommandInfo
);
206 BOOLEAN NTAPI
BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest
, PVDM_DOS_RECORD DosRecord
)
208 BOOLEAN Success
= FALSE
;
209 PVDM_COMMAND_INFO CommandInfo
= NULL
;
211 /* Allocate the command information structure */
212 CommandInfo
= (PVDM_COMMAND_INFO
)RtlAllocateHeap(BaseSrvHeap
,
214 sizeof(VDM_COMMAND_INFO
));
215 if (CommandInfo
== NULL
) return FALSE
;
217 /* Fill the structure */
218 CommandInfo
->TaskId
= CheckVdmRequest
->iTask
;
219 CommandInfo
->ExitCode
= DosRecord
->ExitCode
;
220 CommandInfo
->CodePage
= CheckVdmRequest
->CodePage
;
221 CommandInfo
->StdIn
= CheckVdmRequest
->StdIn
;
222 CommandInfo
->StdOut
= CheckVdmRequest
->StdOut
;
223 CommandInfo
->StdErr
= CheckVdmRequest
->StdErr
;
225 /* Allocate memory for the command line */
226 CommandInfo
->CmdLine
= RtlAllocateHeap(BaseSrvHeap
,
228 CheckVdmRequest
->CmdLen
);
229 if (CommandInfo
->CmdLine
== NULL
) goto Cleanup
;
231 /* Copy the command line */
232 RtlMoveMemory(CommandInfo
->CmdLine
, CheckVdmRequest
->CmdLine
, CheckVdmRequest
->CmdLen
);
234 /* Allocate memory for the application name */
235 CommandInfo
->AppName
= RtlAllocateHeap(BaseSrvHeap
,
237 CheckVdmRequest
->AppLen
);
238 if (CommandInfo
->AppName
== NULL
) goto Cleanup
;
240 /* Copy the application name */
241 RtlMoveMemory(CommandInfo
->AppName
, CheckVdmRequest
->AppName
, CheckVdmRequest
->AppLen
);
243 /* Allocate memory for the PIF file name */
244 if (CheckVdmRequest
->PifLen
!= 0)
246 CommandInfo
->PifFile
= RtlAllocateHeap(BaseSrvHeap
,
248 CheckVdmRequest
->PifLen
);
249 if (CommandInfo
->PifFile
== NULL
) goto Cleanup
;
251 /* Copy the PIF file name */
252 RtlMoveMemory(CommandInfo
->PifFile
, CheckVdmRequest
->PifFile
, CheckVdmRequest
->PifLen
);
254 else CommandInfo
->PifFile
= NULL
;
256 /* Allocate memory for the current directory */
257 if (CheckVdmRequest
->CurDirectoryLen
!= 0)
259 CommandInfo
->CurDirectory
= RtlAllocateHeap(BaseSrvHeap
,
261 CheckVdmRequest
->CurDirectoryLen
);
262 if (CommandInfo
->CurDirectory
== NULL
) goto Cleanup
;
264 /* Copy the current directory */
265 RtlMoveMemory(CommandInfo
->CurDirectory
,
266 CheckVdmRequest
->CurDirectory
,
267 CheckVdmRequest
->CurDirectoryLen
);
269 else CommandInfo
->CurDirectory
= NULL
;
271 /* Allocate memory for the environment block */
272 CommandInfo
->Env
= RtlAllocateHeap(BaseSrvHeap
,
274 CheckVdmRequest
->EnvLen
);
275 if (CommandInfo
->Env
== NULL
) goto Cleanup
;
277 /* Copy the environment block */
278 RtlMoveMemory(CommandInfo
->Env
, CheckVdmRequest
->Env
, CheckVdmRequest
->EnvLen
);
280 CommandInfo
->EnvLen
= CheckVdmRequest
->EnvLen
;
281 RtlMoveMemory(&CommandInfo
->StartupInfo
,
282 CheckVdmRequest
->StartupInfo
,
283 sizeof(STARTUPINFOA
));
285 /* Allocate memory for the desktop */
286 if (CheckVdmRequest
->DesktopLen
!= 0)
288 CommandInfo
->Desktop
= RtlAllocateHeap(BaseSrvHeap
,
290 CheckVdmRequest
->DesktopLen
);
291 if (CommandInfo
->Desktop
== NULL
) goto Cleanup
;
293 /* Copy the desktop name */
294 RtlMoveMemory(CommandInfo
->Desktop
, CheckVdmRequest
->Desktop
, CheckVdmRequest
->DesktopLen
);
296 else CommandInfo
->Desktop
= NULL
;
298 CommandInfo
->DesktopLen
= CheckVdmRequest
->DesktopLen
;
300 /* Allocate memory for the title */
301 if (CheckVdmRequest
->TitleLen
!= 0)
303 CommandInfo
->Title
= RtlAllocateHeap(BaseSrvHeap
,
305 CheckVdmRequest
->TitleLen
);
306 if (CommandInfo
->Title
== NULL
) goto Cleanup
;
309 RtlMoveMemory(CommandInfo
->Title
, CheckVdmRequest
->Title
, CheckVdmRequest
->TitleLen
);
311 else CommandInfo
->Title
= NULL
;
313 CommandInfo
->TitleLen
= CheckVdmRequest
->TitleLen
;
315 /* Allocate memory for the reserved field */
316 if (CheckVdmRequest
->ReservedLen
!= 0)
318 CommandInfo
->Reserved
= RtlAllocateHeap(BaseSrvHeap
,
320 CheckVdmRequest
->ReservedLen
);
321 if (CommandInfo
->Reserved
== NULL
) goto Cleanup
;
323 /* Copy the reserved field */
324 RtlMoveMemory(CommandInfo
->Reserved
,
325 CheckVdmRequest
->Reserved
,
326 CheckVdmRequest
->ReservedLen
);
328 else CommandInfo
->Reserved
= NULL
;
330 CommandInfo
->ReservedLen
= CheckVdmRequest
->ReservedLen
;
332 CommandInfo
->CmdLen
= CheckVdmRequest
->CmdLen
;
333 CommandInfo
->AppLen
= CheckVdmRequest
->AppLen
;
334 CommandInfo
->PifLen
= CheckVdmRequest
->PifLen
;
335 CommandInfo
->CurDirectoryLen
= CheckVdmRequest
->CurDirectoryLen
;
336 CommandInfo
->VDMState
= DosRecord
->State
;
337 // TODO: Set CommandInfo->CurrentDrive
338 // TODO: Set CommandInfo->ComingFromBat
340 /* Set the DOS record's command structure */
341 DosRecord
->CommandInfo
= CommandInfo
;
343 /* The operation was successful */
347 /* If it wasn't successful, free the memory */
348 if (!Success
) BaseSrvFreeVDMInfo(CommandInfo
);
353 VOID NTAPI
BaseInitializeVDM(VOID
)
355 /* Initialize the list head */
356 InitializeListHead(&VDMConsoleListHead
);
358 /* Initialize the critical section */
359 RtlInitializeCriticalSection(&DosCriticalSection
);
360 RtlInitializeCriticalSection(&WowCriticalSection
);
363 /* PUBLIC SERVER APIS *********************************************************/
365 CSR_API(BaseSrvCheckVDM
)
368 PBASE_CHECK_VDM CheckVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CheckVDMRequest
;
369 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
370 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
371 PVDM_DOS_RECORD DosRecord
= NULL
;
372 BOOLEAN NewConsoleRecord
= FALSE
;
374 /* Don't do anything if the VDM has been disabled in the registry */
375 if (!BaseSrvIsVdmAllowed()) return STATUS_ACCESS_DENIED
;
377 /* Validate the message buffers */
378 if (!CsrValidateMessageBuffer(ApiMessage
,
379 (PVOID
*)&CheckVdmRequest
->CmdLine
,
380 CheckVdmRequest
->CmdLen
,
381 sizeof(*CheckVdmRequest
->CmdLine
))
382 || !CsrValidateMessageBuffer(ApiMessage
,
383 (PVOID
*)&CheckVdmRequest
->AppName
,
384 CheckVdmRequest
->AppLen
,
385 sizeof(*CheckVdmRequest
->AppName
))
386 || !CsrValidateMessageBuffer(ApiMessage
,
387 (PVOID
*)&CheckVdmRequest
->PifFile
,
388 CheckVdmRequest
->PifLen
,
389 sizeof(*CheckVdmRequest
->PifFile
))
390 || !CsrValidateMessageBuffer(ApiMessage
,
391 (PVOID
*)&CheckVdmRequest
->CurDirectory
,
392 CheckVdmRequest
->CurDirectoryLen
,
393 sizeof(*CheckVdmRequest
->CurDirectory
))
394 || !CsrValidateMessageBuffer(ApiMessage
,
395 (PVOID
*)&CheckVdmRequest
->Desktop
,
396 CheckVdmRequest
->DesktopLen
,
397 sizeof(*CheckVdmRequest
->Desktop
))
398 || !CsrValidateMessageBuffer(ApiMessage
,
399 (PVOID
*)&CheckVdmRequest
->Title
,
400 CheckVdmRequest
->TitleLen
,
401 sizeof(*CheckVdmRequest
->Title
))
402 || !CsrValidateMessageBuffer(ApiMessage
,
403 (PVOID
*)&CheckVdmRequest
->Reserved
,
404 CheckVdmRequest
->ReservedLen
,
405 sizeof(*CheckVdmRequest
->Reserved
)))
407 return STATUS_INVALID_PARAMETER
;
410 CriticalSection
= (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
411 ? &DosCriticalSection
412 : &WowCriticalSection
;
414 /* Enter the critical section */
415 RtlEnterCriticalSection(CriticalSection
);
417 /* Check if this is a DOS or WOW VDM */
418 if (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
420 /* Get the console record */
421 Status
= BaseSrvGetConsoleRecord(CheckVdmRequest
->ConsoleHandle
,
424 if (!NT_SUCCESS(Status
))
426 /* Allocate a new console record */
427 ConsoleRecord
= (PVDM_CONSOLE_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
429 sizeof(VDM_CONSOLE_RECORD
));
430 if (ConsoleRecord
== NULL
)
432 Status
= STATUS_NO_MEMORY
;
436 /* Initialize the console record */
437 ConsoleRecord
->ConsoleHandle
= CheckVdmRequest
->ConsoleHandle
;
438 ConsoleRecord
->CurrentDirs
= NULL
;
439 ConsoleRecord
->CurDirsLength
= 0;
440 ConsoleRecord
->SessionId
= GetNextDosSesId();
441 InitializeListHead(&ConsoleRecord
->DosListHead
);
442 // TODO: The console record structure is incomplete
444 /* Remember that the console record was allocated here */
445 NewConsoleRecord
= TRUE
;
448 /* Allocate a new DOS record */
449 DosRecord
= (PVDM_DOS_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
451 sizeof(VDM_DOS_RECORD
));
452 if (DosRecord
== NULL
)
454 Status
= STATUS_NO_MEMORY
;
458 /* Initialize the DOS record */
459 DosRecord
->State
= NewConsoleRecord
? VDM_NOT_LOADED
: VDM_READY
;
460 DosRecord
->ExitCode
= 0;
461 // TODO: The DOS record structure is incomplete
463 Status
= BaseSrvCreatePairWaitHandles(&DosRecord
->ServerEvent
, &DosRecord
->ClientEvent
);
464 if (!NT_SUCCESS(Status
)) goto Cleanup
;
466 /* Translate the input structure into a VDM command structure and set it in the DOS record */
467 if (!BaseSrvCopyCommand(CheckVdmRequest
, DosRecord
))
469 /* The only possibility is that an allocation failure occurred */
470 Status
= STATUS_NO_MEMORY
;
474 /* Add the DOS record */
475 InsertHeadList(&ConsoleRecord
->DosListHead
, &DosRecord
->Entry
);
477 if (NewConsoleRecord
)
479 /* Add the console record */
480 InsertTailList(&VDMConsoleListHead
, &ConsoleRecord
->Entry
);
483 CheckVdmRequest
->VDMState
= DosRecord
->State
;
484 Status
= STATUS_SUCCESS
;
488 // TODO: NOT IMPLEMENTED
490 return STATUS_NOT_IMPLEMENTED
;
494 /* Check if it failed */
495 if (!NT_SUCCESS(Status
))
497 /* Free the DOS record */
498 if (DosRecord
!= NULL
)
500 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
504 /* Free the console record if it was allocated here */
505 if (NewConsoleRecord
)
507 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
508 ConsoleRecord
= NULL
;
512 /* Leave the critical section */
513 RtlLeaveCriticalSection(CriticalSection
);
518 CSR_API(BaseSrvUpdateVDMEntry
)
520 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
521 return STATUS_NOT_IMPLEMENTED
;
524 CSR_API(BaseSrvGetNextVDMCommand
)
526 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
527 return STATUS_NOT_IMPLEMENTED
;
530 CSR_API(BaseSrvExitVDM
)
533 PBASE_EXIT_VDM ExitVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitVDMRequest
;
534 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
535 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
536 PVDM_DOS_RECORD DosRecord
;
538 CriticalSection
= (ExitVdmRequest
->iWowTask
== 0)
539 ? &DosCriticalSection
540 : &WowCriticalSection
;
542 /* Enter the critical section */
543 RtlEnterCriticalSection(CriticalSection
);
545 if (ExitVdmRequest
->iWowTask
== 0)
547 /* Get the console record */
548 Status
= BaseSrvGetConsoleRecord(ExitVdmRequest
->ConsoleHandle
, &ConsoleRecord
);
549 if (!NT_SUCCESS(Status
)) goto Cleanup
;
551 /* Cleanup the DOS records */
552 while (ConsoleRecord
->DosListHead
.Flink
!= &ConsoleRecord
->DosListHead
)
554 DosRecord
= CONTAINING_RECORD(ConsoleRecord
->DosListHead
.Flink
,
558 /* Remove the DOS entry */
559 RemoveEntryList(&DosRecord
->Entry
);
560 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
563 if (ConsoleRecord
->CurrentDirs
!= NULL
)
565 /* Free the current directories */
566 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
->CurrentDirs
);
567 ConsoleRecord
->CurrentDirs
= NULL
;
568 ConsoleRecord
->CurDirsLength
= 0;
571 /* Remove the console record */
572 RemoveEntryList(&ConsoleRecord
->Entry
);
573 RtlFreeHeap(BaseSrvHeap
, 0, ConsoleRecord
);
577 // TODO: NOT IMPLEMENTED
579 return STATUS_NOT_IMPLEMENTED
;
583 /* Leave the critical section */
584 RtlLeaveCriticalSection(CriticalSection
);
589 CSR_API(BaseSrvIsFirstVDM
)
591 PBASE_IS_FIRST_VDM IsFirstVDMRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.IsFirstVDMRequest
;
593 /* Return the result */
594 IsFirstVDMRequest
->FirstVDM
= FirstVDM
;
596 /* Clear the first VDM flag */
599 return STATUS_SUCCESS
;
602 CSR_API(BaseSrvGetVDMExitCode
)
605 PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetVDMExitCodeRequest
;
606 PLIST_ENTRY i
= NULL
;
607 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
608 PVDM_DOS_RECORD DosRecord
= NULL
;
610 /* Enter the critical section */
611 RtlEnterCriticalSection(&DosCriticalSection
);
613 /* Get the console record */
614 Status
= BaseSrvGetConsoleRecord(GetVDMExitCodeRequest
->ConsoleHandle
, &ConsoleRecord
);
615 if (!NT_SUCCESS(Status
)) goto Cleanup
;
617 /* Search for a DOS record that has the same parent process handle */
618 for (i
= ConsoleRecord
->DosListHead
.Flink
; i
!= &ConsoleRecord
->DosListHead
; i
= i
->Flink
)
620 DosRecord
= CONTAINING_RECORD(i
, VDM_DOS_RECORD
, Entry
);
621 if (DosRecord
->ClientEvent
== GetVDMExitCodeRequest
->hParent
) break;
624 /* Check if no DOS record was found */
625 if (i
== &ConsoleRecord
->DosListHead
)
627 Status
= STATUS_NOT_FOUND
;
631 /* Check if this task is still running */
632 if (DosRecord
->State
== VDM_READY
)
634 GetVDMExitCodeRequest
->ExitCode
= STATUS_PENDING
;
638 /* Return the exit code */
639 GetVDMExitCodeRequest
->ExitCode
= DosRecord
->ExitCode
;
641 /* Since this is a zombie task record, remove it */
642 RemoveEntryList(&DosRecord
->Entry
);
643 RtlFreeHeap(BaseSrvHeap
, 0, DosRecord
);
646 /* Leave the critical section */
647 RtlLeaveCriticalSection(&DosCriticalSection
);
652 CSR_API(BaseSrvSetReenterCount
)
654 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
655 return STATUS_NOT_IMPLEMENTED
;
658 CSR_API(BaseSrvSetVDMCurDirs
)
661 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
662 PVDM_CONSOLE_RECORD ConsoleRecord
;
665 /* Validate the input buffer */
666 if (!CsrValidateMessageBuffer(ApiMessage
,
667 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
668 VDMCurrentDirsRequest
->cchCurDirs
,
669 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
671 return STATUS_INVALID_PARAMETER
;
674 /* Enter the critical section */
675 RtlEnterCriticalSection(&DosCriticalSection
);
677 /* Find the console record */
678 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
679 if (!NT_SUCCESS(Status
)) goto Cleanup
;
681 if (ConsoleRecord
->CurrentDirs
== NULL
)
683 /* Allocate memory for the current directory information */
684 Buffer
= RtlAllocateHeap(BaseSrvHeap
,
686 VDMCurrentDirsRequest
->cchCurDirs
);
690 /* Resize the amount of allocated memory */
691 Buffer
= RtlReAllocateHeap(BaseSrvHeap
,
693 ConsoleRecord
->CurrentDirs
,
694 VDMCurrentDirsRequest
->cchCurDirs
);
699 /* Allocation failed */
700 Status
= STATUS_NO_MEMORY
;
704 /* Update the console record */
705 ConsoleRecord
->CurrentDirs
= Buffer
;
706 ConsoleRecord
->CurDirsLength
= VDMCurrentDirsRequest
->cchCurDirs
;
709 RtlMoveMemory(ConsoleRecord
->CurrentDirs
,
710 VDMCurrentDirsRequest
->lpszzCurDirs
,
711 VDMCurrentDirsRequest
->cchCurDirs
);
714 /* Leave the critical section */
715 RtlLeaveCriticalSection(&DosCriticalSection
);
720 CSR_API(BaseSrvGetVDMCurDirs
)
723 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
724 PVDM_CONSOLE_RECORD ConsoleRecord
;
726 /* Validate the output buffer */
727 if (!CsrValidateMessageBuffer(ApiMessage
,
728 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
729 VDMCurrentDirsRequest
->cchCurDirs
,
730 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
732 return STATUS_INVALID_PARAMETER
;
735 /* Enter the critical section */
736 RtlEnterCriticalSection(&DosCriticalSection
);
738 /* Find the console record */
739 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
740 if (!NT_SUCCESS(Status
)) goto Cleanup
;
742 /* Return the actual size of the current directory information */
743 VDMCurrentDirsRequest
->cchCurDirs
= ConsoleRecord
->CurDirsLength
;
745 /* Check if the buffer is large enough */
746 if (VDMCurrentDirsRequest
->cchCurDirs
< ConsoleRecord
->CurDirsLength
)
748 Status
= STATUS_BUFFER_TOO_SMALL
;
753 RtlMoveMemory(VDMCurrentDirsRequest
->lpszzCurDirs
,
754 ConsoleRecord
->CurrentDirs
,
755 ConsoleRecord
->CurDirsLength
);
758 /* Leave the critical section */
759 RtlLeaveCriticalSection(&DosCriticalSection
);
764 CSR_API(BaseSrvBatNotification
)
766 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
767 return STATUS_NOT_IMPLEMENTED
;
770 CSR_API(BaseSrvRegisterWowExec
)
772 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
773 return STATUS_NOT_IMPLEMENTED
;
776 CSR_API(BaseSrvRefreshIniFileMapping
)
778 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
779 return STATUS_NOT_IMPLEMENTED
;