xref: /reactos/subsystems/win/basesrv/vdm.c (revision f7d612f3)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS Base API Server DLL
4c2c66affSColin Finck  * FILE:            subsystems/win/basesrv/vdm.c
5c2c66affSColin Finck  * PURPOSE:         Virtual DOS Machines (VDM) Support
6c2c66affSColin Finck  * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7c2c66affSColin Finck  *                  Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck /* INCLUDES *******************************************************************/
11c2c66affSColin Finck 
12c2c66affSColin Finck #include "basesrv.h"
13c2c66affSColin Finck #include "vdm.h"
14c2c66affSColin Finck 
15c2c66affSColin Finck #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck 
18c2c66affSColin Finck /* GLOBALS ********************************************************************/
19c2c66affSColin Finck 
20c2c66affSColin Finck BOOLEAN FirstVDM = TRUE;
21c2c66affSColin Finck LIST_ENTRY VDMConsoleListHead;
22c2c66affSColin Finck RTL_CRITICAL_SECTION DosCriticalSection;
23c2c66affSColin Finck RTL_CRITICAL_SECTION WowCriticalSection;
24c2c66affSColin Finck 
25c2c66affSColin Finck /* HELPER FUNCTIONS ***********************************************************/
26c2c66affSColin Finck 
BaseSrvCreateConsoleRecord(VOID)27c2c66affSColin Finck PVDM_CONSOLE_RECORD BaseSrvCreateConsoleRecord(VOID)
28c2c66affSColin Finck {
29c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord;
30c2c66affSColin Finck 
31c2c66affSColin Finck     ConsoleRecord = RtlAllocateHeap(BaseSrvHeap, HEAP_ZERO_MEMORY,
32c2c66affSColin Finck                                     sizeof(VDM_CONSOLE_RECORD));
33c2c66affSColin Finck     if (ConsoleRecord == NULL)
34c2c66affSColin Finck         return NULL;
35c2c66affSColin Finck 
36c2c66affSColin Finck     /* Initialize the console record */
37c2c66affSColin Finck     ConsoleRecord->ConsoleHandle = NULL;
38c2c66affSColin Finck     ConsoleRecord->ProcessHandle = NULL;
39c2c66affSColin Finck     ConsoleRecord->ServerEvent = ConsoleRecord->ClientEvent = NULL;
40c2c66affSColin Finck     ConsoleRecord->ReenterCount = 0;
41c2c66affSColin Finck     ConsoleRecord->CurrentDirs = NULL;
42c2c66affSColin Finck     ConsoleRecord->CurDirsLength = 0;
43c2c66affSColin Finck     ConsoleRecord->SessionId = 0;
44c2c66affSColin Finck     InitializeListHead(&ConsoleRecord->DosListHead);
45c2c66affSColin Finck 
46c2c66affSColin Finck     return ConsoleRecord;
47c2c66affSColin Finck }
48c2c66affSColin Finck 
BaseSrvGetConsoleRecord(HANDLE ConsoleHandle,PVDM_CONSOLE_RECORD * Record)49c2c66affSColin Finck NTSTATUS BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record)
50c2c66affSColin Finck {
51c2c66affSColin Finck     PLIST_ENTRY i;
52c2c66affSColin Finck     PVDM_CONSOLE_RECORD CurrentRecord = NULL;
53c2c66affSColin Finck 
54c2c66affSColin Finck     /* NULL is not a valid console handle */
55c2c66affSColin Finck     if (ConsoleHandle == NULL) return STATUS_INVALID_PARAMETER;
56c2c66affSColin Finck 
57c2c66affSColin Finck     /* Search for a record that has the same console handle */
58c2c66affSColin Finck     for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
59c2c66affSColin Finck     {
60c2c66affSColin Finck         CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
61c2c66affSColin Finck         if (CurrentRecord->ConsoleHandle == ConsoleHandle) break;
62c2c66affSColin Finck     }
63c2c66affSColin Finck 
64c2c66affSColin Finck     /* Check if nothing was found */
65c2c66affSColin Finck     if (i == &VDMConsoleListHead) CurrentRecord = NULL;
66c2c66affSColin Finck 
67c2c66affSColin Finck     *Record = CurrentRecord;
68c2c66affSColin Finck     return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND;
69c2c66affSColin Finck }
70c2c66affSColin Finck 
BaseSrvDestroyConsoleRecord(PVDM_CONSOLE_RECORD ConsoleRecord)71c2c66affSColin Finck VOID BaseSrvDestroyConsoleRecord(PVDM_CONSOLE_RECORD ConsoleRecord)
72c2c66affSColin Finck {
73c2c66affSColin Finck     if (ConsoleRecord->CurrentDirs != NULL)
74c2c66affSColin Finck     {
75c2c66affSColin Finck         /* Free the current directories */
76c2c66affSColin Finck         RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs);
77c2c66affSColin Finck         ConsoleRecord->CurrentDirs = NULL;
78c2c66affSColin Finck         ConsoleRecord->CurDirsLength = 0;
79c2c66affSColin Finck     }
80c2c66affSColin Finck 
81c2c66affSColin Finck     /* Close the process handle */
82c2c66affSColin Finck     if (ConsoleRecord->ProcessHandle)
83c2c66affSColin Finck         NtClose(ConsoleRecord->ProcessHandle);
84c2c66affSColin Finck 
85c2c66affSColin Finck     /* Close the event handle */
86c2c66affSColin Finck     if (ConsoleRecord->ServerEvent)
87c2c66affSColin Finck         NtClose(ConsoleRecord->ServerEvent);
88c2c66affSColin Finck 
89c2c66affSColin Finck     /* Remove the console record */
90c2c66affSColin Finck     // RemoveEntryList(&ConsoleRecord->Entry);
91c2c66affSColin Finck     RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord);
92c2c66affSColin Finck }
93c2c66affSColin Finck 
GetConsoleRecordBySessionId(ULONG TaskId,PVDM_CONSOLE_RECORD * Record)94c2c66affSColin Finck NTSTATUS GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record)
95c2c66affSColin Finck {
96c2c66affSColin Finck     PLIST_ENTRY i;
97c2c66affSColin Finck     PVDM_CONSOLE_RECORD CurrentRecord = NULL;
98c2c66affSColin Finck 
99c2c66affSColin Finck     /* Search for a record that has the same console handle */
100c2c66affSColin Finck     for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
101c2c66affSColin Finck     {
102c2c66affSColin Finck         CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
103c2c66affSColin Finck         if (CurrentRecord->SessionId == TaskId) break;
104c2c66affSColin Finck     }
105c2c66affSColin Finck 
106c2c66affSColin Finck     /* Check if nothing was found */
107c2c66affSColin Finck     if (i == &VDMConsoleListHead) CurrentRecord = NULL;
108c2c66affSColin Finck 
109c2c66affSColin Finck     *Record = CurrentRecord;
110c2c66affSColin Finck     return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND;
111c2c66affSColin Finck }
112c2c66affSColin Finck 
GetNextDosSesId(VOID)113c2c66affSColin Finck ULONG GetNextDosSesId(VOID)
114c2c66affSColin Finck {
115c2c66affSColin Finck     ULONG SessionId;
116c2c66affSColin Finck     PLIST_ENTRY i;
117c2c66affSColin Finck     PVDM_CONSOLE_RECORD CurrentRecord = NULL;
118c2c66affSColin Finck     BOOLEAN Found;
119c2c66affSColin Finck 
120c2c66affSColin Finck     /* Search for an available session ID */
121c2c66affSColin Finck     for (SessionId = 1; SessionId != 0; SessionId++)
122c2c66affSColin Finck     {
123c2c66affSColin Finck         Found = FALSE;
124c2c66affSColin Finck 
125c2c66affSColin Finck         /* Check if the ID is already in use */
126c2c66affSColin Finck         for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink)
127c2c66affSColin Finck         {
128c2c66affSColin Finck             CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
129c2c66affSColin Finck             if (CurrentRecord->SessionId == SessionId) Found = TRUE;
130c2c66affSColin Finck         }
131c2c66affSColin Finck 
132c2c66affSColin Finck         /* If not, we found one */
133c2c66affSColin Finck         if (!Found) break;
134c2c66affSColin Finck     }
135c2c66affSColin Finck 
136c2c66affSColin Finck     ASSERT(SessionId != 0);
137c2c66affSColin Finck 
138c2c66affSColin Finck     /* Return the session ID */
139c2c66affSColin Finck     return SessionId;
140c2c66affSColin Finck }
141c2c66affSColin Finck 
BaseSrvIsVdmAllowed(VOID)142c2c66affSColin Finck BOOLEAN BaseSrvIsVdmAllowed(VOID)
143c2c66affSColin Finck {
144c2c66affSColin Finck     NTSTATUS Status;
145c2c66affSColin Finck     BOOLEAN VdmAllowed = TRUE;
146c2c66affSColin Finck     HANDLE RootKey, KeyHandle;
147c2c66affSColin Finck     UNICODE_STRING KeyName, ValueName, MachineKeyName;
148c2c66affSColin Finck     OBJECT_ATTRIBUTES Attributes;
149c2c66affSColin Finck     UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
150c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
151c2c66affSColin Finck     ULONG ActualSize;
152c2c66affSColin Finck 
153c2c66affSColin Finck     /* Initialize the unicode strings */
154c2c66affSColin Finck     RtlInitUnicodeString(&MachineKeyName, L"\\Registry\\Machine");
155c2c66affSColin Finck     RtlInitUnicodeString(&KeyName, VDM_POLICY_KEY_NAME);
156c2c66affSColin Finck     RtlInitUnicodeString(&ValueName, VDM_DISALLOWED_VALUE_NAME);
157c2c66affSColin Finck 
158c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
159c2c66affSColin Finck                                &MachineKeyName,
160c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
161c2c66affSColin Finck                                NULL,
162c2c66affSColin Finck                                NULL);
163c2c66affSColin Finck 
164c2c66affSColin Finck     /* Open the local machine key */
165c2c66affSColin Finck     Status = NtOpenKey(&RootKey, KEY_READ, &Attributes);
166c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return FALSE;
167c2c66affSColin Finck 
168c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
169c2c66affSColin Finck                                &KeyName,
170c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
171c2c66affSColin Finck                                RootKey,
172c2c66affSColin Finck                                NULL);
173c2c66affSColin Finck 
174c2c66affSColin Finck     /* Open the policy key in the local machine hive, if it exists */
175c2c66affSColin Finck     if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes)))
176c2c66affSColin Finck     {
177c2c66affSColin Finck         /* Read the value, if it's set */
178c2c66affSColin Finck         if (NT_SUCCESS(NtQueryValueKey(KeyHandle,
179c2c66affSColin Finck                                        &ValueName,
180c2c66affSColin Finck                                        KeyValuePartialInformation,
181c2c66affSColin Finck                                        ValueInfo,
182c2c66affSColin Finck                                        sizeof(ValueBuffer),
183c2c66affSColin Finck                                        &ActualSize)))
184c2c66affSColin Finck         {
185c2c66affSColin Finck             if (*((PULONG)ValueInfo->Data))
186c2c66affSColin Finck             {
187c2c66affSColin Finck                 /* The VDM has been disabled in the registry */
188c2c66affSColin Finck                 VdmAllowed = FALSE;
189c2c66affSColin Finck             }
190c2c66affSColin Finck         }
191c2c66affSColin Finck 
192c2c66affSColin Finck         NtClose(KeyHandle);
193c2c66affSColin Finck     }
194c2c66affSColin Finck 
195c2c66affSColin Finck     /* Close the local machine key */
196c2c66affSColin Finck     NtClose(RootKey);
197c2c66affSColin Finck 
198c2c66affSColin Finck     /* If it's disabled system-wide, there's no need to check the user key */
199c2c66affSColin Finck     if (!VdmAllowed) return FALSE;
200c2c66affSColin Finck 
201c2c66affSColin Finck     /* Open the current user key of the client */
202c2c66affSColin Finck     if (!CsrImpersonateClient(NULL)) return VdmAllowed;
203c2c66affSColin Finck     Status = RtlOpenCurrentUser(KEY_READ, &RootKey);
204c2c66affSColin Finck     CsrRevertToSelf();
205c2c66affSColin Finck 
206c2c66affSColin Finck     /* If that fails, return the system-wide setting */
207c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return VdmAllowed;
208c2c66affSColin Finck 
209c2c66affSColin Finck     InitializeObjectAttributes(&Attributes,
210c2c66affSColin Finck                                &KeyName,
211c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
212c2c66affSColin Finck                                RootKey,
213c2c66affSColin Finck                                NULL);
214c2c66affSColin Finck 
215c2c66affSColin Finck     /* Open the policy key in the current user hive, if it exists */
216c2c66affSColin Finck     if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes)))
217c2c66affSColin Finck     {
218c2c66affSColin Finck         /* Read the value, if it's set */
219c2c66affSColin Finck         if (NT_SUCCESS(NtQueryValueKey(KeyHandle,
220c2c66affSColin Finck                                        &ValueName,
221c2c66affSColin Finck                                        KeyValuePartialInformation,
222c2c66affSColin Finck                                        ValueInfo,
223c2c66affSColin Finck                                        sizeof(ValueBuffer),
224c2c66affSColin Finck                                        &ActualSize)))
225c2c66affSColin Finck         {
226c2c66affSColin Finck             if (*((PULONG)ValueInfo->Data))
227c2c66affSColin Finck             {
228c2c66affSColin Finck                 /* The VDM has been disabled in the registry */
229c2c66affSColin Finck                 VdmAllowed = FALSE;
230c2c66affSColin Finck             }
231c2c66affSColin Finck         }
232c2c66affSColin Finck 
233c2c66affSColin Finck         NtClose(KeyHandle);
234c2c66affSColin Finck     }
235c2c66affSColin Finck 
236c2c66affSColin Finck     return VdmAllowed;
237c2c66affSColin Finck }
238c2c66affSColin Finck 
BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent,PHANDLE ClientEvent)239c2c66affSColin Finck NTSTATUS BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent)
240c2c66affSColin Finck {
241c2c66affSColin Finck     NTSTATUS Status;
242c2c66affSColin Finck 
243c2c66affSColin Finck     /* Create the event */
244c2c66affSColin Finck     Status = NtCreateEvent(ServerEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
245c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
246c2c66affSColin Finck 
247c2c66affSColin Finck     /* Duplicate the event into the client process */
248c2c66affSColin Finck     Status = NtDuplicateObject(NtCurrentProcess(),
249c2c66affSColin Finck                                *ServerEvent,
250c2c66affSColin Finck                                CsrGetClientThread()->Process->ProcessHandle,
251c2c66affSColin Finck                                ClientEvent,
252c2c66affSColin Finck                                0,
253c2c66affSColin Finck                                0,
254c2c66affSColin Finck                                DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
255c2c66affSColin Finck 
256c2c66affSColin Finck     if (!NT_SUCCESS(Status)) NtClose(*ServerEvent);
257c2c66affSColin Finck     return Status;
258c2c66affSColin Finck }
259c2c66affSColin Finck 
BaseSrvDestroyPairWaitHandles(HANDLE ServerEvent,HANDLE ClientEvent)260c2c66affSColin Finck VOID BaseSrvDestroyPairWaitHandles(HANDLE ServerEvent, HANDLE ClientEvent)
261c2c66affSColin Finck {
262c2c66affSColin Finck     if (ServerEvent) NtClose(ServerEvent);
263c2c66affSColin Finck     if (ClientEvent)
264c2c66affSColin Finck     {
265c2c66affSColin Finck         /* Close the remote handle */
266c2c66affSColin Finck         NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle,
267c2c66affSColin Finck                           ClientEvent,
268c2c66affSColin Finck                           NULL,
269c2c66affSColin Finck                           NULL,
270c2c66affSColin Finck                           0,
271c2c66affSColin Finck                           0,
272c2c66affSColin Finck                           DUPLICATE_CLOSE_SOURCE);
273c2c66affSColin Finck     }
274c2c66affSColin Finck }
275c2c66affSColin Finck 
276c2c66affSColin Finck /* WOW SUPPORT FUNCTIONS ******************************************************/
277c2c66affSColin Finck 
278c2c66affSColin Finck /* DOS SUPPORT FUNCTIONS ******************************************************/
279c2c66affSColin Finck 
BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo)280c2c66affSColin Finck VOID BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo)
281c2c66affSColin Finck {
282c2c66affSColin Finck     /* Free the allocated structure members */
283c2c66affSColin Finck     if (CommandInfo->CmdLine != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CmdLine);
284c2c66affSColin Finck     if (CommandInfo->AppName != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->AppName);
285c2c66affSColin Finck     if (CommandInfo->PifFile != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->PifFile);
286c2c66affSColin Finck     if (CommandInfo->CurDirectory != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CurDirectory);
287c2c66affSColin Finck     if (CommandInfo->Env != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Env);
288c2c66affSColin Finck     if (CommandInfo->Desktop != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Desktop);
289c2c66affSColin Finck     if (CommandInfo->Title != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Title);
290c2c66affSColin Finck     if (CommandInfo->Reserved != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Reserved);
291c2c66affSColin Finck 
292c2c66affSColin Finck     /* Free the structure itself */
293c2c66affSColin Finck     RtlFreeHeap(BaseSrvHeap, 0, CommandInfo);
294c2c66affSColin Finck }
295c2c66affSColin Finck 
BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess)296c2c66affSColin Finck VOID BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess)
297c2c66affSColin Finck {
298c2c66affSColin Finck     ULONG ProcessId = HandleToUlong(CsrProcess->ClientId.UniqueProcess);
299c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
300c2c66affSColin Finck     PVDM_DOS_RECORD DosRecord;
301c2c66affSColin Finck     PLIST_ENTRY i;
302c2c66affSColin Finck 
303c2c66affSColin Finck     /* Enter the critical section */
304c2c66affSColin Finck     RtlEnterCriticalSection(&DosCriticalSection);
305c2c66affSColin Finck 
306c2c66affSColin Finck     /* Search for a record that has the same process handle */
307c2c66affSColin Finck     i = VDMConsoleListHead.Flink;
308c2c66affSColin Finck     while (i != &VDMConsoleListHead)
309c2c66affSColin Finck     {
310c2c66affSColin Finck         ConsoleRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry);
311c2c66affSColin Finck         i = i->Flink;
312c2c66affSColin Finck 
313c2c66affSColin Finck         if (ConsoleRecord->ProcessId == ProcessId)
314c2c66affSColin Finck         {
315c2c66affSColin Finck             if (ConsoleRecord->ServerEvent)
316c2c66affSColin Finck             {
317c2c66affSColin Finck                 NtClose(ConsoleRecord->ServerEvent);
318c2c66affSColin Finck                 ConsoleRecord->ServerEvent = NULL;
319c2c66affSColin Finck             }
320c2c66affSColin Finck 
321c2c66affSColin Finck             /* Cleanup the DOS records */
322c2c66affSColin Finck             while (!IsListEmpty(&ConsoleRecord->DosListHead))
323c2c66affSColin Finck             {
324c2c66affSColin Finck                 DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
325c2c66affSColin Finck                                               VDM_DOS_RECORD, Entry);
326c2c66affSColin Finck 
327c2c66affSColin Finck                 /* Set the event and close it */
328c2c66affSColin Finck                 if (DosRecord->ServerEvent)
329c2c66affSColin Finck                 {
330c2c66affSColin Finck                     NtSetEvent(DosRecord->ServerEvent, NULL);
331c2c66affSColin Finck                     NtClose(DosRecord->ServerEvent);
332c2c66affSColin Finck                     DosRecord->ServerEvent = NULL;
333c2c66affSColin Finck                 }
334c2c66affSColin Finck 
335c2c66affSColin Finck                 /* Remove the DOS entry */
336c2c66affSColin Finck                 if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
337c2c66affSColin Finck                 RemoveEntryList(&DosRecord->Entry);
338c2c66affSColin Finck                 RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
339c2c66affSColin Finck             }
340c2c66affSColin Finck 
341c2c66affSColin Finck             /* Remove the console record */
342c2c66affSColin Finck             RemoveEntryList(&ConsoleRecord->Entry);
343c2c66affSColin Finck             BaseSrvDestroyConsoleRecord(ConsoleRecord);
344c2c66affSColin Finck         }
345c2c66affSColin Finck     }
346c2c66affSColin Finck 
347c2c66affSColin Finck     /* Leave the critical section */
348c2c66affSColin Finck     RtlLeaveCriticalSection(&DosCriticalSection);
349c2c66affSColin Finck }
350c2c66affSColin Finck 
BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest,PVDM_DOS_RECORD DosRecord)351c2c66affSColin Finck BOOLEAN BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord)
352c2c66affSColin Finck {
353c2c66affSColin Finck     BOOLEAN Success = FALSE;
354c2c66affSColin Finck     PVDM_COMMAND_INFO CommandInfo = NULL;
355c2c66affSColin Finck 
356c2c66affSColin Finck     /* Allocate the command information structure */
357c2c66affSColin Finck     CommandInfo = (PVDM_COMMAND_INFO)RtlAllocateHeap(BaseSrvHeap,
358c2c66affSColin Finck                                                      HEAP_ZERO_MEMORY,
359c2c66affSColin Finck                                                      sizeof(VDM_COMMAND_INFO));
360c2c66affSColin Finck     if (CommandInfo == NULL) return FALSE;
361c2c66affSColin Finck 
362c2c66affSColin Finck     /* Fill the structure */
363c2c66affSColin Finck     CommandInfo->TaskId = CheckVdmRequest->iTask;
364c2c66affSColin Finck     CommandInfo->ExitCode = DosRecord->ExitCode;
365c2c66affSColin Finck     CommandInfo->CodePage = CheckVdmRequest->CodePage;
366c2c66affSColin Finck     CommandInfo->StdIn = CheckVdmRequest->StdIn;
367c2c66affSColin Finck     CommandInfo->StdOut = CheckVdmRequest->StdOut;
368c2c66affSColin Finck     CommandInfo->StdErr = CheckVdmRequest->StdErr;
369c2c66affSColin Finck 
370c2c66affSColin Finck     /* Allocate memory for the command line */
371c2c66affSColin Finck     CommandInfo->CmdLine = RtlAllocateHeap(BaseSrvHeap,
372c2c66affSColin Finck                                            HEAP_ZERO_MEMORY,
373c2c66affSColin Finck                                            CheckVdmRequest->CmdLen);
374c2c66affSColin Finck     if (CommandInfo->CmdLine == NULL) goto Cleanup;
375c2c66affSColin Finck 
376c2c66affSColin Finck     /* Copy the command line */
377c2c66affSColin Finck     RtlMoveMemory(CommandInfo->CmdLine, CheckVdmRequest->CmdLine, CheckVdmRequest->CmdLen);
378c2c66affSColin Finck 
379c2c66affSColin Finck     /* Allocate memory for the application name */
380c2c66affSColin Finck     CommandInfo->AppName = RtlAllocateHeap(BaseSrvHeap,
381c2c66affSColin Finck                                            HEAP_ZERO_MEMORY,
382c2c66affSColin Finck                                            CheckVdmRequest->AppLen);
383c2c66affSColin Finck     if (CommandInfo->AppName == NULL) goto Cleanup;
384c2c66affSColin Finck 
385c2c66affSColin Finck     /* Copy the application name */
386c2c66affSColin Finck     RtlMoveMemory(CommandInfo->AppName, CheckVdmRequest->AppName, CheckVdmRequest->AppLen);
387c2c66affSColin Finck 
388c2c66affSColin Finck     /* Allocate memory for the PIF file name */
389c2c66affSColin Finck     if (CheckVdmRequest->PifLen != 0)
390c2c66affSColin Finck     {
391c2c66affSColin Finck         CommandInfo->PifFile = RtlAllocateHeap(BaseSrvHeap,
392c2c66affSColin Finck                                                HEAP_ZERO_MEMORY,
393c2c66affSColin Finck                                                CheckVdmRequest->PifLen);
394c2c66affSColin Finck         if (CommandInfo->PifFile == NULL) goto Cleanup;
395c2c66affSColin Finck 
396c2c66affSColin Finck         /* Copy the PIF file name */
397c2c66affSColin Finck         RtlMoveMemory(CommandInfo->PifFile, CheckVdmRequest->PifFile, CheckVdmRequest->PifLen);
398c2c66affSColin Finck     }
399c2c66affSColin Finck     else CommandInfo->PifFile = NULL;
400c2c66affSColin Finck 
401c2c66affSColin Finck     /* Allocate memory for the current directory */
402c2c66affSColin Finck     if (CheckVdmRequest->CurDirectoryLen != 0)
403c2c66affSColin Finck     {
404c2c66affSColin Finck         CommandInfo->CurDirectory = RtlAllocateHeap(BaseSrvHeap,
405c2c66affSColin Finck                                                     HEAP_ZERO_MEMORY,
406c2c66affSColin Finck                                                     CheckVdmRequest->CurDirectoryLen);
407c2c66affSColin Finck         if (CommandInfo->CurDirectory == NULL) goto Cleanup;
408c2c66affSColin Finck 
409c2c66affSColin Finck         /* Copy the current directory */
410c2c66affSColin Finck         RtlMoveMemory(CommandInfo->CurDirectory,
411c2c66affSColin Finck                       CheckVdmRequest->CurDirectory,
412c2c66affSColin Finck                       CheckVdmRequest->CurDirectoryLen);
413c2c66affSColin Finck     }
414c2c66affSColin Finck     else CommandInfo->CurDirectory = NULL;
415c2c66affSColin Finck 
416c2c66affSColin Finck     /* Allocate memory for the environment block */
417c2c66affSColin Finck     CommandInfo->Env = RtlAllocateHeap(BaseSrvHeap,
418c2c66affSColin Finck                                        HEAP_ZERO_MEMORY,
419c2c66affSColin Finck                                        CheckVdmRequest->EnvLen);
420c2c66affSColin Finck     if (CommandInfo->Env == NULL) goto Cleanup;
421c2c66affSColin Finck 
422c2c66affSColin Finck     /* Copy the environment block */
423c2c66affSColin Finck     RtlMoveMemory(CommandInfo->Env, CheckVdmRequest->Env, CheckVdmRequest->EnvLen);
424c2c66affSColin Finck 
425c2c66affSColin Finck     CommandInfo->EnvLen = CheckVdmRequest->EnvLen;
426c2c66affSColin Finck     RtlMoveMemory(&CommandInfo->StartupInfo,
427c2c66affSColin Finck                   CheckVdmRequest->StartupInfo,
428c2c66affSColin Finck                   sizeof(STARTUPINFOA));
429c2c66affSColin Finck 
430c2c66affSColin Finck     /* Allocate memory for the desktop */
431c2c66affSColin Finck     if (CheckVdmRequest->DesktopLen != 0)
432c2c66affSColin Finck     {
433c2c66affSColin Finck         CommandInfo->Desktop = RtlAllocateHeap(BaseSrvHeap,
434c2c66affSColin Finck                                                HEAP_ZERO_MEMORY,
435c2c66affSColin Finck                                                CheckVdmRequest->DesktopLen);
436c2c66affSColin Finck         if (CommandInfo->Desktop == NULL) goto Cleanup;
437c2c66affSColin Finck 
438c2c66affSColin Finck         /* Copy the desktop name */
439c2c66affSColin Finck         RtlMoveMemory(CommandInfo->Desktop, CheckVdmRequest->Desktop, CheckVdmRequest->DesktopLen);
440c2c66affSColin Finck     }
441c2c66affSColin Finck     else CommandInfo->Desktop = NULL;
442c2c66affSColin Finck 
443c2c66affSColin Finck     CommandInfo->DesktopLen = CheckVdmRequest->DesktopLen;
444c2c66affSColin Finck 
445c2c66affSColin Finck     /* Allocate memory for the title */
446c2c66affSColin Finck     if (CheckVdmRequest->TitleLen != 0)
447c2c66affSColin Finck     {
448c2c66affSColin Finck         CommandInfo->Title = RtlAllocateHeap(BaseSrvHeap,
449c2c66affSColin Finck                                              HEAP_ZERO_MEMORY,
450c2c66affSColin Finck                                              CheckVdmRequest->TitleLen);
451c2c66affSColin Finck         if (CommandInfo->Title == NULL) goto Cleanup;
452c2c66affSColin Finck 
453c2c66affSColin Finck         /* Copy the title */
454c2c66affSColin Finck         RtlMoveMemory(CommandInfo->Title, CheckVdmRequest->Title, CheckVdmRequest->TitleLen);
455c2c66affSColin Finck     }
456c2c66affSColin Finck     else CommandInfo->Title = NULL;
457c2c66affSColin Finck 
458c2c66affSColin Finck     CommandInfo->TitleLen = CheckVdmRequest->TitleLen;
459c2c66affSColin Finck 
460c2c66affSColin Finck     /* Allocate memory for the reserved field */
461c2c66affSColin Finck     if (CheckVdmRequest->ReservedLen != 0)
462c2c66affSColin Finck     {
463c2c66affSColin Finck         CommandInfo->Reserved = RtlAllocateHeap(BaseSrvHeap,
464c2c66affSColin Finck                                                 HEAP_ZERO_MEMORY,
465c2c66affSColin Finck                                                 CheckVdmRequest->ReservedLen);
466c2c66affSColin Finck         if (CommandInfo->Reserved == NULL) goto Cleanup;
467c2c66affSColin Finck 
468c2c66affSColin Finck         /* Copy the reserved field */
469c2c66affSColin Finck         RtlMoveMemory(CommandInfo->Reserved,
470c2c66affSColin Finck                       CheckVdmRequest->Reserved,
471c2c66affSColin Finck                       CheckVdmRequest->ReservedLen);
472c2c66affSColin Finck     }
473c2c66affSColin Finck     else CommandInfo->Reserved = NULL;
474c2c66affSColin Finck 
475c2c66affSColin Finck     CommandInfo->ReservedLen = CheckVdmRequest->ReservedLen;
476c2c66affSColin Finck 
477c2c66affSColin Finck     CommandInfo->CmdLen = CheckVdmRequest->CmdLen;
478c2c66affSColin Finck     CommandInfo->AppLen = CheckVdmRequest->AppLen;
479c2c66affSColin Finck     CommandInfo->PifLen = CheckVdmRequest->PifLen;
480c2c66affSColin Finck     CommandInfo->CurDirectoryLen = CheckVdmRequest->CurDirectoryLen;
481c2c66affSColin Finck     CommandInfo->VDMState = DosRecord->State;
482c2c66affSColin Finck     // TODO: Set CommandInfo->CurrentDrive
483c2c66affSColin Finck     // TODO: Set CommandInfo->ComingFromBat
484c2c66affSColin Finck 
485c2c66affSColin Finck     /* Set the DOS record's command structure */
486c2c66affSColin Finck     DosRecord->CommandInfo = CommandInfo;
487c2c66affSColin Finck 
488c2c66affSColin Finck     /* The operation was successful */
489c2c66affSColin Finck     Success = TRUE;
490c2c66affSColin Finck 
491c2c66affSColin Finck Cleanup:
492c2c66affSColin Finck     /* If it wasn't successful, free the memory */
493c2c66affSColin Finck     if (!Success) BaseSrvFreeVDMInfo(CommandInfo);
494c2c66affSColin Finck 
495c2c66affSColin Finck     return Success;
496c2c66affSColin Finck }
497c2c66affSColin Finck 
BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo,PBASE_GET_NEXT_VDM_COMMAND Message)498c2c66affSColin Finck NTSTATUS BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo,
499c2c66affSColin Finck                                 PBASE_GET_NEXT_VDM_COMMAND Message)
500c2c66affSColin Finck {
501c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
502c2c66affSColin Finck 
503c2c66affSColin Finck     /* Copy the data */
504c2c66affSColin Finck     Message->iTask = CommandInfo->TaskId;
505c2c66affSColin Finck     Message->StdIn = CommandInfo->StdIn;
506c2c66affSColin Finck     Message->StdOut = CommandInfo->StdOut;
507c2c66affSColin Finck     Message->StdErr = CommandInfo->StdErr;
508c2c66affSColin Finck     Message->CodePage = CommandInfo->CodePage;
509c2c66affSColin Finck     Message->dwCreationFlags = CommandInfo->CreationFlags;
510c2c66affSColin Finck     Message->ExitCode = CommandInfo->ExitCode;
511c2c66affSColin Finck     Message->CurrentDrive = CommandInfo->CurrentDrive;
512c2c66affSColin Finck     Message->VDMState = CommandInfo->VDMState;
513c2c66affSColin Finck     Message->fComingFromBat = CommandInfo->ComingFromBat;
514c2c66affSColin Finck 
515c2c66affSColin Finck     if (Message->CmdLen >= CommandInfo->CmdLen)
516c2c66affSColin Finck     {
517c2c66affSColin Finck         /* Copy the command line */
518c2c66affSColin Finck         RtlMoveMemory(Message->CmdLine, CommandInfo->CmdLine, CommandInfo->CmdLen);
519c2c66affSColin Finck     }
520c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
521c2c66affSColin Finck     Message->CmdLen = CommandInfo->CmdLen;
522c2c66affSColin Finck 
523c2c66affSColin Finck     if (Message->AppLen >= CommandInfo->AppLen)
524c2c66affSColin Finck     {
525c2c66affSColin Finck         /* Copy the application name */
526c2c66affSColin Finck         RtlMoveMemory(Message->AppName, CommandInfo->AppName, CommandInfo->AppLen);
527c2c66affSColin Finck     }
528c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
529c2c66affSColin Finck     Message->AppLen = CommandInfo->AppLen;
530c2c66affSColin Finck 
531c2c66affSColin Finck     if (Message->PifLen >= CommandInfo->PifLen)
532c2c66affSColin Finck     {
533c2c66affSColin Finck         /* Copy the PIF file name */
534c2c66affSColin Finck         RtlMoveMemory(Message->PifFile, CommandInfo->PifFile, CommandInfo->PifLen);
535c2c66affSColin Finck     }
536c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
537c2c66affSColin Finck     Message->PifLen = CommandInfo->PifLen;
538c2c66affSColin Finck 
539c2c66affSColin Finck     if (Message->CurDirectoryLen >= CommandInfo->CurDirectoryLen)
540c2c66affSColin Finck     {
541c2c66affSColin Finck         /* Copy the current directory */
542c2c66affSColin Finck         RtlMoveMemory(Message->CurDirectory, CommandInfo->CurDirectory, CommandInfo->CurDirectoryLen);
543c2c66affSColin Finck     }
544c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
545c2c66affSColin Finck     Message->CurDirectoryLen = CommandInfo->CurDirectoryLen;
546c2c66affSColin Finck 
547c2c66affSColin Finck     if (Message->EnvLen >= CommandInfo->EnvLen)
548c2c66affSColin Finck     {
549c2c66affSColin Finck         /* Copy the environment */
550c2c66affSColin Finck         RtlMoveMemory(Message->Env, CommandInfo->Env, CommandInfo->EnvLen);
551c2c66affSColin Finck     }
552c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
553c2c66affSColin Finck     Message->EnvLen = CommandInfo->EnvLen;
554c2c66affSColin Finck 
555c2c66affSColin Finck     /* Copy the startup info */
556c2c66affSColin Finck     RtlMoveMemory(Message->StartupInfo,
557c2c66affSColin Finck                   &CommandInfo->StartupInfo,
558c2c66affSColin Finck                   sizeof(STARTUPINFOA));
559c2c66affSColin Finck 
560c2c66affSColin Finck     if (Message->DesktopLen >= CommandInfo->DesktopLen)
561c2c66affSColin Finck     {
562c2c66affSColin Finck         /* Copy the desktop name */
563c2c66affSColin Finck         RtlMoveMemory(Message->Desktop, CommandInfo->Desktop, CommandInfo->DesktopLen);
564c2c66affSColin Finck     }
565c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
566c2c66affSColin Finck     Message->DesktopLen = CommandInfo->DesktopLen;
567c2c66affSColin Finck 
568c2c66affSColin Finck     if (Message->TitleLen >= CommandInfo->TitleLen)
569c2c66affSColin Finck     {
570c2c66affSColin Finck         /* Copy the title */
571c2c66affSColin Finck         RtlMoveMemory(Message->Title, CommandInfo->Title, CommandInfo->TitleLen);
572c2c66affSColin Finck     }
573c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
574c2c66affSColin Finck     Message->TitleLen = CommandInfo->TitleLen;
575c2c66affSColin Finck 
576c2c66affSColin Finck     if (Message->ReservedLen >= CommandInfo->ReservedLen)
577c2c66affSColin Finck     {
578c2c66affSColin Finck         /* Copy the reserved parameter */
579c2c66affSColin Finck         RtlMoveMemory(Message->Reserved, CommandInfo->Reserved, CommandInfo->ReservedLen);
580c2c66affSColin Finck     }
581c2c66affSColin Finck     else Status = STATUS_INVALID_PARAMETER;
582c2c66affSColin Finck     Message->ReservedLen = CommandInfo->ReservedLen;
583c2c66affSColin Finck 
584c2c66affSColin Finck     return Status;
585c2c66affSColin Finck }
586c2c66affSColin Finck 
BaseInitializeVDM(VOID)587c2c66affSColin Finck VOID BaseInitializeVDM(VOID)
588c2c66affSColin Finck {
589c2c66affSColin Finck     /* Initialize the list head */
590c2c66affSColin Finck     InitializeListHead(&VDMConsoleListHead);
591c2c66affSColin Finck 
592c2c66affSColin Finck     /* Initialize the critical sections */
593c2c66affSColin Finck     RtlInitializeCriticalSection(&DosCriticalSection);
594c2c66affSColin Finck     RtlInitializeCriticalSection(&WowCriticalSection);
595c2c66affSColin Finck }
596c2c66affSColin Finck 
597c2c66affSColin Finck /* PUBLIC SERVER APIS *********************************************************/
598c2c66affSColin Finck 
CSR_API(BaseSrvCheckVDM)599c2c66affSColin Finck CSR_API(BaseSrvCheckVDM)
600c2c66affSColin Finck {
601c2c66affSColin Finck     NTSTATUS Status;
602c2c66affSColin Finck     PBASE_CHECK_VDM CheckVdmRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CheckVDMRequest;
603c2c66affSColin Finck     PRTL_CRITICAL_SECTION CriticalSection = NULL;
604c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
605c2c66affSColin Finck     PVDM_DOS_RECORD DosRecord = NULL;
606c2c66affSColin Finck     BOOLEAN NewConsoleRecord = FALSE;
607c2c66affSColin Finck     BOOLEAN NewDosRecord = FALSE;
608c2c66affSColin Finck 
609c2c66affSColin Finck     /* Don't do anything if the VDM has been disabled in the registry */
610c2c66affSColin Finck     if (!BaseSrvIsVdmAllowed()) return STATUS_VDM_DISALLOWED;
611c2c66affSColin Finck 
612c2c66affSColin Finck     /* Validate the message buffers */
613c2c66affSColin Finck     if (!CsrValidateMessageBuffer(ApiMessage,
614c2c66affSColin Finck                                   (PVOID*)&CheckVdmRequest->CmdLine,
615c2c66affSColin Finck                                   CheckVdmRequest->CmdLen,
616c2c66affSColin Finck                                   sizeof(*CheckVdmRequest->CmdLine))
617c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
618c2c66affSColin Finck                                      (PVOID*)&CheckVdmRequest->AppName,
619c2c66affSColin Finck                                      CheckVdmRequest->AppLen,
620c2c66affSColin Finck                                      sizeof(*CheckVdmRequest->AppName))
621c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
622c2c66affSColin Finck                                      (PVOID*)&CheckVdmRequest->PifFile,
623c2c66affSColin Finck                                      CheckVdmRequest->PifLen,
624c2c66affSColin Finck                                      sizeof(*CheckVdmRequest->PifFile))
625c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
626c2c66affSColin Finck                                      (PVOID*)&CheckVdmRequest->CurDirectory,
627c2c66affSColin Finck                                      CheckVdmRequest->CurDirectoryLen,
628c2c66affSColin Finck                                      sizeof(*CheckVdmRequest->CurDirectory))
629c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
630c2c66affSColin Finck                                      (PVOID*)&CheckVdmRequest->Desktop,
631c2c66affSColin Finck                                      CheckVdmRequest->DesktopLen,
632c2c66affSColin Finck                                      sizeof(*CheckVdmRequest->Desktop))
633c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
634c2c66affSColin Finck                                      (PVOID*)&CheckVdmRequest->Title,
635c2c66affSColin Finck                                      CheckVdmRequest->TitleLen,
636c2c66affSColin Finck                                      sizeof(*CheckVdmRequest->Title))
637c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
638c2c66affSColin Finck                                      (PVOID*)&CheckVdmRequest->Reserved,
639c2c66affSColin Finck                                      CheckVdmRequest->ReservedLen,
640c2c66affSColin Finck                                      sizeof(*CheckVdmRequest->Reserved)))
641c2c66affSColin Finck     {
642c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
643c2c66affSColin Finck     }
644c2c66affSColin Finck 
645c2c66affSColin Finck     CriticalSection = (CheckVdmRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
646c2c66affSColin Finck                       ? &DosCriticalSection
647c2c66affSColin Finck                       : &WowCriticalSection;
648c2c66affSColin Finck 
649c2c66affSColin Finck     /* Enter the critical section */
650c2c66affSColin Finck     RtlEnterCriticalSection(CriticalSection);
651c2c66affSColin Finck 
652c2c66affSColin Finck     /* Check if this is a DOS or WOW VDM */
653c2c66affSColin Finck     if (CheckVdmRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
654c2c66affSColin Finck     {
655c2c66affSColin Finck         /* Get the console record */
656c2c66affSColin Finck         Status = BaseSrvGetConsoleRecord(CheckVdmRequest->ConsoleHandle,
657c2c66affSColin Finck                                          &ConsoleRecord);
658c2c66affSColin Finck         if (!NT_SUCCESS(Status))
659c2c66affSColin Finck         {
660c2c66affSColin Finck             /* Allocate a new console record */
661c2c66affSColin Finck             ConsoleRecord = BaseSrvCreateConsoleRecord();
662c2c66affSColin Finck             if (ConsoleRecord == NULL)
663c2c66affSColin Finck             {
664c2c66affSColin Finck                 Status = STATUS_NO_MEMORY;
665c2c66affSColin Finck                 goto Cleanup;
666c2c66affSColin Finck             }
667c2c66affSColin Finck 
668c2c66affSColin Finck             /* Initialize the console record */
669c2c66affSColin Finck             ConsoleRecord->ConsoleHandle = CheckVdmRequest->ConsoleHandle;
670c2c66affSColin Finck             if (ConsoleRecord->ConsoleHandle == NULL)
671c2c66affSColin Finck             {
672c2c66affSColin Finck                 /* The parent doesn't have a console, get a new session ID */
673c2c66affSColin Finck                 ConsoleRecord->SessionId = GetNextDosSesId();
674c2c66affSColin Finck             }
675c2c66affSColin Finck             else
676c2c66affSColin Finck             {
677c2c66affSColin Finck                 /* No session ID is needed */
678c2c66affSColin Finck                 ConsoleRecord->SessionId = 0;
679c2c66affSColin Finck             }
680c2c66affSColin Finck 
681c2c66affSColin Finck             /* Remember that the console record was allocated here */
682c2c66affSColin Finck             NewConsoleRecord = TRUE;
683c2c66affSColin Finck         }
684c2c66affSColin Finck 
685c2c66affSColin Finck         if (!NewConsoleRecord)
686c2c66affSColin Finck         {
687c2c66affSColin Finck             /* Get the primary DOS record */
688c2c66affSColin Finck             DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
689c2c66affSColin Finck                                                            VDM_DOS_RECORD, Entry);
690c2c66affSColin Finck 
691c2c66affSColin Finck             if (DosRecord->State != VDM_READY) // == VDM_NOT_READY
692c2c66affSColin Finck             {
693c2c66affSColin Finck                 /* Allocate a new DOS record */
694c2c66affSColin Finck                 DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap,
695c2c66affSColin Finck                                                              HEAP_ZERO_MEMORY,
696c2c66affSColin Finck                                                              sizeof(VDM_DOS_RECORD));
697c2c66affSColin Finck                 if (DosRecord == NULL)
698c2c66affSColin Finck                 {
699c2c66affSColin Finck                     Status = STATUS_NO_MEMORY;
700c2c66affSColin Finck                     goto Cleanup;
701c2c66affSColin Finck                 }
702c2c66affSColin Finck 
703c2c66affSColin Finck                 /* Remember that the DOS record was allocated here */
704c2c66affSColin Finck                 NewDosRecord = TRUE;
705c2c66affSColin Finck             }
706c2c66affSColin Finck         }
707c2c66affSColin Finck         else
708c2c66affSColin Finck         {
709c2c66affSColin Finck             /* Allocate a new DOS record */
710c2c66affSColin Finck             DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap,
711c2c66affSColin Finck                                                          HEAP_ZERO_MEMORY,
712c2c66affSColin Finck                                                          sizeof(VDM_DOS_RECORD));
713c2c66affSColin Finck             if (DosRecord == NULL)
714c2c66affSColin Finck             {
715c2c66affSColin Finck                 Status = STATUS_NO_MEMORY;
716c2c66affSColin Finck                 goto Cleanup;
717c2c66affSColin Finck             }
718c2c66affSColin Finck 
719c2c66affSColin Finck             /* Remember that the DOS record was allocated here */
720c2c66affSColin Finck             NewDosRecord = TRUE;
721c2c66affSColin Finck         }
722c2c66affSColin Finck 
723c2c66affSColin Finck         /* Initialize the DOS record */
724c2c66affSColin Finck         DosRecord->State = VDM_NOT_READY;
725c2c66affSColin Finck         DosRecord->ExitCode = 0;
726c2c66affSColin Finck 
727c2c66affSColin Finck         /* Translate the input structure into a VDM command structure and set it in the DOS record */
728c2c66affSColin Finck         if (!BaseSrvCopyCommand(CheckVdmRequest, DosRecord))
729c2c66affSColin Finck         {
730c2c66affSColin Finck             /* The only possibility is that an allocation failure occurred */
731c2c66affSColin Finck             Status = STATUS_NO_MEMORY;
732c2c66affSColin Finck             goto Cleanup;
733c2c66affSColin Finck         }
734c2c66affSColin Finck 
735c2c66affSColin Finck         if (NewDosRecord)
736c2c66affSColin Finck         {
737c2c66affSColin Finck             /* Add the DOS record */
738c2c66affSColin Finck             InsertHeadList(&ConsoleRecord->DosListHead, &DosRecord->Entry);
739c2c66affSColin Finck         }
740c2c66affSColin Finck 
741c2c66affSColin Finck         if (!NewConsoleRecord)
742c2c66affSColin Finck         {
743c2c66affSColin Finck             Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent);
744c2c66affSColin Finck             if (!NT_SUCCESS(Status)) goto Cleanup;
745c2c66affSColin Finck 
746c2c66affSColin Finck             /* Return the client event handle */
747c2c66affSColin Finck             CheckVdmRequest->WaitObjectForParent = DosRecord->ClientEvent;
748c2c66affSColin Finck         }
749c2c66affSColin Finck 
750c2c66affSColin Finck         // FIXME: We may notify ONLY if ConsoleRecord->nReEntrancy is > 0
751c2c66affSColin Finck         // in case NewConsoleRecord == FALSE AND NewDosRecord == TRUE.
752c2c66affSColin Finck         if (ConsoleRecord->ServerEvent)
753c2c66affSColin Finck         {
754c2c66affSColin Finck             /* Signal the session event */
755c2c66affSColin Finck             NtSetEvent(ConsoleRecord->ServerEvent, NULL);
756c2c66affSColin Finck         }
757c2c66affSColin Finck 
758c2c66affSColin Finck         if (NewConsoleRecord)
759c2c66affSColin Finck         {
760c2c66affSColin Finck             /* Add the console record */
761c2c66affSColin Finck             InsertTailList(&VDMConsoleListHead, &ConsoleRecord->Entry);
762c2c66affSColin Finck         }
763c2c66affSColin Finck 
764c2c66affSColin Finck         CheckVdmRequest->iTask = ConsoleRecord->SessionId;
765c2c66affSColin Finck         CheckVdmRequest->VDMState = NewConsoleRecord ? VDM_NOT_LOADED : VDM_READY;
766c2c66affSColin Finck         Status = STATUS_SUCCESS;
767c2c66affSColin Finck     }
768c2c66affSColin Finck     else
769c2c66affSColin Finck     {
770c2c66affSColin Finck         // TODO: NOT IMPLEMENTED
771c2c66affSColin Finck         UNIMPLEMENTED;
772c2c66affSColin Finck         Status = STATUS_NOT_IMPLEMENTED;
773c2c66affSColin Finck     }
774c2c66affSColin Finck 
775c2c66affSColin Finck Cleanup:
776c2c66affSColin Finck     /* Check if it failed */
777c2c66affSColin Finck     if (!NT_SUCCESS(Status))
778c2c66affSColin Finck     {
779c2c66affSColin Finck         /* Free the DOS record if it was allocated here */
780c2c66affSColin Finck         if (NewDosRecord)
781c2c66affSColin Finck         {
782c2c66affSColin Finck             ASSERT(DosRecord != NULL);
783c2c66affSColin Finck 
784c2c66affSColin Finck             BaseSrvDestroyPairWaitHandles(DosRecord->ServerEvent,
785c2c66affSColin Finck                                           DosRecord->ClientEvent);
786c2c66affSColin Finck 
787c2c66affSColin Finck             RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
788c2c66affSColin Finck             DosRecord = NULL;
789c2c66affSColin Finck         }
790c2c66affSColin Finck 
791c2c66affSColin Finck         /* Free the console record if it was allocated here */
792c2c66affSColin Finck         if (NewConsoleRecord)
793c2c66affSColin Finck         {
794c2c66affSColin Finck             ASSERT(ConsoleRecord != NULL);
795c2c66affSColin Finck 
796c2c66affSColin Finck             RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord);
797c2c66affSColin Finck             ConsoleRecord = NULL;
798c2c66affSColin Finck         }
799c2c66affSColin Finck     }
800c2c66affSColin Finck 
801c2c66affSColin Finck     /* Leave the critical section */
802c2c66affSColin Finck     RtlLeaveCriticalSection(CriticalSection);
803c2c66affSColin Finck 
804c2c66affSColin Finck     return Status;
805c2c66affSColin Finck }
806c2c66affSColin Finck 
CSR_API(BaseSrvUpdateVDMEntry)807c2c66affSColin Finck CSR_API(BaseSrvUpdateVDMEntry)
808c2c66affSColin Finck {
809c2c66affSColin Finck     NTSTATUS Status;
810c2c66affSColin Finck     PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.UpdateVDMEntryRequest;
811c2c66affSColin Finck     PRTL_CRITICAL_SECTION CriticalSection = NULL;
812c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
813c2c66affSColin Finck     PVDM_DOS_RECORD DosRecord = NULL;
814c2c66affSColin Finck 
815c2c66affSColin Finck     CriticalSection = (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
816c2c66affSColin Finck                       ? &DosCriticalSection
817c2c66affSColin Finck                       : &WowCriticalSection;
818c2c66affSColin Finck 
819c2c66affSColin Finck     /* Enter the critical section */
820c2c66affSColin Finck     RtlEnterCriticalSection(CriticalSection);
821c2c66affSColin Finck 
822c2c66affSColin Finck     /* Check if this is a DOS or WOW VDM */
823c2c66affSColin Finck     if (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW)
824c2c66affSColin Finck     {
825c2c66affSColin Finck         if (UpdateVdmEntryRequest->iTask != 0)
826c2c66affSColin Finck         {
827c2c66affSColin Finck             /* Get the console record using the task ID */
828c2c66affSColin Finck             Status = GetConsoleRecordBySessionId(UpdateVdmEntryRequest->iTask,
829c2c66affSColin Finck                                                  &ConsoleRecord);
830c2c66affSColin Finck         }
831c2c66affSColin Finck         else
832c2c66affSColin Finck         {
833c2c66affSColin Finck             /* Get the console record using the console handle */
834c2c66affSColin Finck             Status = BaseSrvGetConsoleRecord(UpdateVdmEntryRequest->ConsoleHandle,
835c2c66affSColin Finck                                              &ConsoleRecord);
836c2c66affSColin Finck         }
837c2c66affSColin Finck 
838c2c66affSColin Finck         if (!NT_SUCCESS(Status)) goto Cleanup;
839c2c66affSColin Finck 
840c2c66affSColin Finck         /* Get the primary DOS record */
841c2c66affSColin Finck         DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
842c2c66affSColin Finck                                                        VDM_DOS_RECORD, Entry);
843c2c66affSColin Finck 
844c2c66affSColin Finck         switch (UpdateVdmEntryRequest->EntryIndex)
845c2c66affSColin Finck         {
846c2c66affSColin Finck             case VdmEntryUndo:
847c2c66affSColin Finck             {
848c2c66affSColin Finck                 /* Close the server event handle, the client will close the client handle */
849c2c66affSColin Finck                 NtClose(DosRecord->ServerEvent);
850c2c66affSColin Finck                 DosRecord->ServerEvent = DosRecord->ClientEvent = NULL;
851c2c66affSColin Finck 
852c2c66affSColin Finck                 if (UpdateVdmEntryRequest->VDMCreationState & (VDM_UNDO_PARTIAL | VDM_UNDO_FULL))
853c2c66affSColin Finck                 {
854c2c66affSColin Finck                     /* Remove the DOS record */
855c2c66affSColin Finck                     if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
856c2c66affSColin Finck                     RemoveEntryList(&DosRecord->Entry);
857c2c66affSColin Finck                     RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
858c2c66affSColin Finck 
859c2c66affSColin Finck                     /*
860c2c66affSColin Finck                      * Since this is an undo, if that was the only DOS record the VDM
861c2c66affSColin Finck                      * won't even start, so the console record should be removed too.
862c2c66affSColin Finck                      */
863c2c66affSColin Finck                     if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead)
864c2c66affSColin Finck                     {
865c2c66affSColin Finck                         RemoveEntryList(&ConsoleRecord->Entry);
866c2c66affSColin Finck                         BaseSrvDestroyConsoleRecord(ConsoleRecord);
867c2c66affSColin Finck                     }
868c2c66affSColin Finck                 }
869c2c66affSColin Finck 
870c2c66affSColin Finck                 /* It was successful */
871c2c66affSColin Finck                 Status = STATUS_SUCCESS;
872c2c66affSColin Finck 
873c2c66affSColin Finck                 break;
874c2c66affSColin Finck             }
875c2c66affSColin Finck 
876c2c66affSColin Finck             case VdmEntryUpdateProcess:
877c2c66affSColin Finck             {
878c2c66affSColin Finck                 /* Duplicate the VDM process handle */
879c2c66affSColin Finck                 Status = NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle,
880c2c66affSColin Finck                                            UpdateVdmEntryRequest->VDMProcessHandle,
881c2c66affSColin Finck                                            NtCurrentProcess(),
882c2c66affSColin Finck                                            &ConsoleRecord->ProcessHandle,
883c2c66affSColin Finck                                            0,
884c2c66affSColin Finck                                            0,
885c2c66affSColin Finck                                            DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
886c2c66affSColin Finck                 if (!NT_SUCCESS(Status)) goto Cleanup;
887c2c66affSColin Finck 
888c2c66affSColin Finck                 //
889c2c66affSColin Finck                 // FIXME! Should we always do the following??
890c2c66affSColin Finck                 //
891c2c66affSColin Finck 
892c2c66affSColin Finck                 /* Create a pair of handles to one event object */
893c2c66affSColin Finck                 Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent,
894c2c66affSColin Finck                                                       &DosRecord->ClientEvent);
895c2c66affSColin Finck                 if (!NT_SUCCESS(Status)) goto Cleanup;
896c2c66affSColin Finck 
897c2c66affSColin Finck                 /* Return the client event handle */
898c2c66affSColin Finck                 UpdateVdmEntryRequest->WaitObjectForParent = DosRecord->ClientEvent;
899c2c66affSColin Finck 
900c2c66affSColin Finck                 break;
901c2c66affSColin Finck             }
902c2c66affSColin Finck 
903c2c66affSColin Finck             case VdmEntryUpdateControlCHandler:
904c2c66affSColin Finck             {
905c2c66affSColin Finck                 // TODO: NOT IMPLEMENTED
906*f7d612f3SSerge Gautherie                 DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented\n");
907c2c66affSColin Finck                 Status = STATUS_NOT_IMPLEMENTED;
908c2c66affSColin Finck 
909c2c66affSColin Finck                 break;
910c2c66affSColin Finck             }
911c2c66affSColin Finck 
912c2c66affSColin Finck             default:
913c2c66affSColin Finck             {
914c2c66affSColin Finck                 /* Invalid */
915c2c66affSColin Finck                 Status = STATUS_INVALID_PARAMETER;
916c2c66affSColin Finck             }
917c2c66affSColin Finck         }
918c2c66affSColin Finck     }
919c2c66affSColin Finck     else
920c2c66affSColin Finck     {
921c2c66affSColin Finck         // TODO: NOT IMPLEMENTED
922c2c66affSColin Finck         UNIMPLEMENTED;
923c2c66affSColin Finck         Status = STATUS_NOT_IMPLEMENTED;
924c2c66affSColin Finck     }
925c2c66affSColin Finck 
926c2c66affSColin Finck Cleanup:
927c2c66affSColin Finck     /* Leave the critical section */
928c2c66affSColin Finck     RtlLeaveCriticalSection(CriticalSection);
929c2c66affSColin Finck 
930c2c66affSColin Finck     return Status;
931c2c66affSColin Finck }
932c2c66affSColin Finck 
CSR_API(BaseSrvGetNextVDMCommand)933c2c66affSColin Finck CSR_API(BaseSrvGetNextVDMCommand)
934c2c66affSColin Finck {
935c2c66affSColin Finck     NTSTATUS Status;
936c2c66affSColin Finck     PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest =
937c2c66affSColin Finck         &((PBASE_API_MESSAGE)ApiMessage)->Data.GetNextVDMCommandRequest;
938c2c66affSColin Finck     PRTL_CRITICAL_SECTION CriticalSection;
939c2c66affSColin Finck     PLIST_ENTRY i = NULL;
940c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
941c2c66affSColin Finck     PVDM_DOS_RECORD DosRecord = NULL;
942c2c66affSColin Finck 
943c2c66affSColin Finck     /* Validate the message buffers */
944c2c66affSColin Finck     if (!CsrValidateMessageBuffer(ApiMessage,
945c2c66affSColin Finck                                   (PVOID*)&GetNextVdmCommandRequest->CmdLine,
946c2c66affSColin Finck                                   GetNextVdmCommandRequest->CmdLen,
947c2c66affSColin Finck                                   sizeof(*GetNextVdmCommandRequest->CmdLine))
948c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
949c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->AppName,
950c2c66affSColin Finck                                      GetNextVdmCommandRequest->AppLen,
951c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->AppName))
952c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
953c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->PifFile,
954c2c66affSColin Finck                                      GetNextVdmCommandRequest->PifLen,
955c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->PifFile))
956c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
957c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->CurDirectory,
958c2c66affSColin Finck                                      GetNextVdmCommandRequest->CurDirectoryLen,
959c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->CurDirectory))
960c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
961c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->Env,
962c2c66affSColin Finck                                      GetNextVdmCommandRequest->EnvLen,
963c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->Env))
964c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
965c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->Desktop,
966c2c66affSColin Finck                                      GetNextVdmCommandRequest->DesktopLen,
967c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->Desktop))
968c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
969c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->Title,
970c2c66affSColin Finck                                      GetNextVdmCommandRequest->TitleLen,
971c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->Title))
972c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
973c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->Reserved,
974c2c66affSColin Finck                                      GetNextVdmCommandRequest->ReservedLen,
975c2c66affSColin Finck                                      sizeof(*GetNextVdmCommandRequest->Reserved))
976c2c66affSColin Finck         || !CsrValidateMessageBuffer(ApiMessage,
977c2c66affSColin Finck                                      (PVOID*)&GetNextVdmCommandRequest->StartupInfo,
978c2c66affSColin Finck                                      1,
979c2c66affSColin Finck                                      sizeof(STARTUPINFOA)))
980c2c66affSColin Finck     {
981c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
982c2c66affSColin Finck     }
983c2c66affSColin Finck 
984c2c66affSColin Finck     CriticalSection = (GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW)
985c2c66affSColin Finck                       ? &WowCriticalSection
986c2c66affSColin Finck                       : &DosCriticalSection;
987c2c66affSColin Finck 
988c2c66affSColin Finck     /* Enter the critical section */
989c2c66affSColin Finck     RtlEnterCriticalSection(CriticalSection);
990c2c66affSColin Finck 
991c2c66affSColin Finck     if (GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW)
992c2c66affSColin Finck     {
993c2c66affSColin Finck         // TODO: WOW SUPPORT NOT IMPLEMENTED
994c2c66affSColin Finck         UNIMPLEMENTED;
995c2c66affSColin Finck         Status = STATUS_NOT_IMPLEMENTED;
996c2c66affSColin Finck         goto Cleanup;
997c2c66affSColin Finck     }
998c2c66affSColin Finck     // else if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW))
999c2c66affSColin Finck     {
1000c2c66affSColin Finck         if (GetNextVdmCommandRequest->iTask != 0)
1001c2c66affSColin Finck         {
1002c2c66affSColin Finck             /* Get the console record using the task ID */
1003c2c66affSColin Finck             Status = GetConsoleRecordBySessionId(GetNextVdmCommandRequest->iTask,
1004c2c66affSColin Finck                                                  &ConsoleRecord);
1005c2c66affSColin Finck         }
1006c2c66affSColin Finck         else
1007c2c66affSColin Finck         {
1008c2c66affSColin Finck             /* Get the console record using the console handle */
1009c2c66affSColin Finck             Status = BaseSrvGetConsoleRecord(GetNextVdmCommandRequest->ConsoleHandle,
1010c2c66affSColin Finck                                              &ConsoleRecord);
1011c2c66affSColin Finck         }
1012c2c66affSColin Finck 
1013c2c66affSColin Finck         /* Make sure we found the console record */
1014c2c66affSColin Finck         if (!NT_SUCCESS(Status)) goto Cleanup;
1015c2c66affSColin Finck 
1016c2c66affSColin Finck         /* Return the session ID */
1017c2c66affSColin Finck         GetNextVdmCommandRequest->iTask = ConsoleRecord->SessionId;
1018c2c66affSColin Finck         GetNextVdmCommandRequest->WaitObjectForVDM = NULL;
1019c2c66affSColin Finck 
1020c2c66affSColin Finck         if (GetNextVdmCommandRequest->VDMState & VDM_GET_FIRST_COMMAND)
1021c2c66affSColin Finck         {
1022c2c66affSColin Finck             /* Check if the DOS record list is empty */
1023c2c66affSColin Finck             if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead)
1024c2c66affSColin Finck             {
1025c2c66affSColin Finck                 Status = STATUS_INVALID_PARAMETER;
1026c2c66affSColin Finck                 goto Cleanup;
1027c2c66affSColin Finck             }
1028c2c66affSColin Finck 
1029c2c66affSColin Finck             /* Get the first DOS record */
1030c2c66affSColin Finck             DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, VDM_DOS_RECORD, Entry);
1031c2c66affSColin Finck 
1032c2c66affSColin Finck             /* Make sure its command information is still there */
1033c2c66affSColin Finck             if (DosRecord->CommandInfo == NULL)
1034c2c66affSColin Finck             {
1035c2c66affSColin Finck                 Status = STATUS_INVALID_PARAMETER;
1036c2c66affSColin Finck                 goto Cleanup;
1037c2c66affSColin Finck             }
1038c2c66affSColin Finck 
1039c2c66affSColin Finck             /* Check if the console handle hasn't been set yet */
1040c2c66affSColin Finck             if (ConsoleRecord->ConsoleHandle == NULL)
1041c2c66affSColin Finck             {
1042c2c66affSColin Finck                 /* Set it now */
1043c2c66affSColin Finck                 ConsoleRecord->ConsoleHandle = GetNextVdmCommandRequest->ConsoleHandle;
1044c2c66affSColin Finck             }
1045c2c66affSColin Finck 
1046c2c66affSColin Finck             /* Fill the command information */
1047c2c66affSColin Finck             Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest);
1048c2c66affSColin Finck             goto Cleanup;
1049c2c66affSColin Finck         }
1050c2c66affSColin Finck 
1051c2c66affSColin Finck         /* Check if we should set the state of a running DOS record to ready */
1052c2c66affSColin Finck         if (!(GetNextVdmCommandRequest->VDMState
1053c2c66affSColin Finck             & (VDM_FLAG_FIRST_TASK | VDM_FLAG_RETRY | VDM_FLAG_NESTED_TASK)))
1054c2c66affSColin Finck         {
1055c2c66affSColin Finck             /* Search for a DOS record that is currently running */
1056c2c66affSColin Finck             for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink)
1057c2c66affSColin Finck             {
1058c2c66affSColin Finck                 DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
1059c2c66affSColin Finck                 if (DosRecord->State == VDM_NOT_READY) break;
1060c2c66affSColin Finck             }
1061c2c66affSColin Finck 
1062c2c66affSColin Finck             /* Check if we found any */
1063c2c66affSColin Finck             if (i == &ConsoleRecord->DosListHead)
1064c2c66affSColin Finck             {
1065c2c66affSColin Finck                 Status = STATUS_INVALID_PARAMETER;
1066c2c66affSColin Finck                 goto Cleanup;
1067c2c66affSColin Finck             }
1068c2c66affSColin Finck 
1069c2c66affSColin Finck             /* Set the exit code */
1070c2c66affSColin Finck             DosRecord->ExitCode = GetNextVdmCommandRequest->ExitCode;
1071c2c66affSColin Finck 
1072c2c66affSColin Finck             /* Update the VDM state */
1073c2c66affSColin Finck             DosRecord->State = VDM_READY;
1074c2c66affSColin Finck 
1075c2c66affSColin Finck             /* Notify all waiting threads that the task is finished */
1076c2c66affSColin Finck             NtSetEvent(DosRecord->ServerEvent, NULL);
1077c2c66affSColin Finck             NtClose(DosRecord->ServerEvent);
1078c2c66affSColin Finck             DosRecord->ServerEvent = NULL;
1079c2c66affSColin Finck         }
1080c2c66affSColin Finck 
1081c2c66affSColin Finck         /* Search for a DOS record that is currently running and has command information */
1082c2c66affSColin Finck         for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink)
1083c2c66affSColin Finck         {
1084c2c66affSColin Finck             DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
1085c2c66affSColin Finck             if ((DosRecord->State == VDM_NOT_READY) && (DosRecord->CommandInfo != NULL)) break;
1086c2c66affSColin Finck         }
1087c2c66affSColin Finck 
1088c2c66affSColin Finck         /* Check if we found any */
1089c2c66affSColin Finck         if (i != &ConsoleRecord->DosListHead)
1090c2c66affSColin Finck         {
1091c2c66affSColin Finck             ASSERT(DosRecord->CommandInfo != NULL);
1092c2c66affSColin Finck 
1093c2c66affSColin Finck             /* Check if the caller only wants environment data */
1094c2c66affSColin Finck             if (GetNextVdmCommandRequest->VDMState & VDM_GET_ENVIRONMENT)
1095c2c66affSColin Finck             {
1096c2c66affSColin Finck                 if (GetNextVdmCommandRequest->EnvLen < DosRecord->CommandInfo->EnvLen)
1097c2c66affSColin Finck                 {
1098c2c66affSColin Finck                     /* Not enough space was reserved */
1099c2c66affSColin Finck                     GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen;
1100c2c66affSColin Finck                     Status = STATUS_BUFFER_OVERFLOW;
1101c2c66affSColin Finck                     goto Cleanup;
1102c2c66affSColin Finck                 }
1103c2c66affSColin Finck 
1104c2c66affSColin Finck                 /* Copy the environment data */
1105c2c66affSColin Finck                 RtlMoveMemory(GetNextVdmCommandRequest->Env,
1106c2c66affSColin Finck                               DosRecord->CommandInfo->Env,
1107c2c66affSColin Finck                               DosRecord->CommandInfo->EnvLen);
1108c2c66affSColin Finck 
1109c2c66affSColin Finck                 /* Return the actual size to the caller */
1110c2c66affSColin Finck                 GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen;
1111c2c66affSColin Finck             }
1112c2c66affSColin Finck             else
1113c2c66affSColin Finck             {
1114c2c66affSColin Finck                 /* Fill the command information */
1115c2c66affSColin Finck                 Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest);
1116c2c66affSColin Finck                 if (!NT_SUCCESS(Status)) goto Cleanup;
1117c2c66affSColin Finck 
1118c2c66affSColin Finck                 /* Free the command information, it's no longer needed */
1119c2c66affSColin Finck                 BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
1120c2c66affSColin Finck                 DosRecord->CommandInfo = NULL;
1121c2c66affSColin Finck 
1122c2c66affSColin Finck                 /* Update the VDM state */
1123c2c66affSColin Finck                 DosRecord->State = VDM_NOT_READY;
1124c2c66affSColin Finck             }
1125c2c66affSColin Finck 
1126c2c66affSColin Finck             Status = STATUS_SUCCESS;
1127c2c66affSColin Finck             goto Cleanup;
1128c2c66affSColin Finck         }
1129c2c66affSColin Finck     }
1130c2c66affSColin Finck 
1131c2c66affSColin Finck     GetNextVdmCommandRequest->WaitObjectForVDM = NULL;
1132c2c66affSColin Finck 
1133c2c66affSColin Finck     /*
1134c2c66affSColin Finck      * There is no command yet. Prepare for waiting if we asked so,
1135c2c66affSColin Finck      * and if we were not retrying a request.
1136c2c66affSColin Finck      */
1137c2c66affSColin Finck     if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_DONT_WAIT) ||
1138c2c66affSColin Finck         !(GetNextVdmCommandRequest->VDMState & VDM_FLAG_RETRY))
1139c2c66affSColin Finck     {
1140c2c66affSColin Finck         if (ConsoleRecord->ServerEvent)
1141c2c66affSColin Finck         {
1142c2c66affSColin Finck             /* Reset the event */
1143c2c66affSColin Finck             NtResetEvent(ConsoleRecord->ServerEvent, NULL);
1144c2c66affSColin Finck         }
1145c2c66affSColin Finck         else
1146c2c66affSColin Finck         {
1147c2c66affSColin Finck             /* Create a pair of wait handles */
1148c2c66affSColin Finck             Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent,
1149c2c66affSColin Finck                                                   &ConsoleRecord->ClientEvent);
1150c2c66affSColin Finck             if (!NT_SUCCESS(Status)) goto Cleanup;
1151c2c66affSColin Finck         }
1152c2c66affSColin Finck 
1153c2c66affSColin Finck         /* Return the client event handle */
1154c2c66affSColin Finck         GetNextVdmCommandRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent;
1155c2c66affSColin Finck     }
1156c2c66affSColin Finck 
1157c2c66affSColin Finck Cleanup:
1158c2c66affSColin Finck     /* Leave the critical section */
1159c2c66affSColin Finck     RtlLeaveCriticalSection(CriticalSection);
1160c2c66affSColin Finck 
1161c2c66affSColin Finck     return Status;
1162c2c66affSColin Finck }
1163c2c66affSColin Finck 
CSR_API(BaseSrvExitVDM)1164c2c66affSColin Finck CSR_API(BaseSrvExitVDM)
1165c2c66affSColin Finck {
1166c2c66affSColin Finck     NTSTATUS Status;
1167c2c66affSColin Finck     PBASE_EXIT_VDM ExitVdmRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ExitVDMRequest;
1168c2c66affSColin Finck     PRTL_CRITICAL_SECTION CriticalSection = NULL;
1169c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
1170c2c66affSColin Finck     PVDM_DOS_RECORD DosRecord;
1171c2c66affSColin Finck 
1172c2c66affSColin Finck     CriticalSection = (ExitVdmRequest->iWowTask == 0)
1173c2c66affSColin Finck                       ? &DosCriticalSection
1174c2c66affSColin Finck                       : &WowCriticalSection;
1175c2c66affSColin Finck 
1176c2c66affSColin Finck     /* Enter the critical section */
1177c2c66affSColin Finck     RtlEnterCriticalSection(CriticalSection);
1178c2c66affSColin Finck 
1179c2c66affSColin Finck     if (ExitVdmRequest->iWowTask == 0)
1180c2c66affSColin Finck     {
1181c2c66affSColin Finck         /* Get the console record */
1182c2c66affSColin Finck         Status = BaseSrvGetConsoleRecord(ExitVdmRequest->ConsoleHandle, &ConsoleRecord);
1183c2c66affSColin Finck         if (!NT_SUCCESS(Status)) goto Cleanup;
1184c2c66affSColin Finck 
1185c2c66affSColin Finck         if (ConsoleRecord->ServerEvent)
1186c2c66affSColin Finck             ExitVdmRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent;
1187c2c66affSColin Finck 
1188c2c66affSColin Finck         // NOTE: The following is the same as in BaseSrvCleanupVDMResources.
1189c2c66affSColin Finck 
1190c2c66affSColin Finck         if (ConsoleRecord->ServerEvent)
1191c2c66affSColin Finck         {
1192c2c66affSColin Finck             NtClose(ConsoleRecord->ServerEvent);
1193c2c66affSColin Finck             ConsoleRecord->ServerEvent = NULL;
1194c2c66affSColin Finck         }
1195c2c66affSColin Finck 
1196c2c66affSColin Finck         /* Cleanup the DOS records */
1197c2c66affSColin Finck         while (!IsListEmpty(&ConsoleRecord->DosListHead))
1198c2c66affSColin Finck         {
1199c2c66affSColin Finck             DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink,
1200c2c66affSColin Finck                                           VDM_DOS_RECORD, Entry);
1201c2c66affSColin Finck 
1202c2c66affSColin Finck             /* Set the event and close it */
1203c2c66affSColin Finck             if (DosRecord->ServerEvent)
1204c2c66affSColin Finck             {
1205c2c66affSColin Finck                 NtSetEvent(DosRecord->ServerEvent, NULL);
1206c2c66affSColin Finck                 NtClose(DosRecord->ServerEvent);
1207c2c66affSColin Finck                 DosRecord->ServerEvent = NULL;
1208c2c66affSColin Finck             }
1209c2c66affSColin Finck 
1210c2c66affSColin Finck             /* Remove the DOS entry */
1211c2c66affSColin Finck             if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
1212c2c66affSColin Finck             RemoveEntryList(&DosRecord->Entry);
1213c2c66affSColin Finck             RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
1214c2c66affSColin Finck         }
1215c2c66affSColin Finck 
1216c2c66affSColin Finck         /* Remove the console record */
1217c2c66affSColin Finck         RemoveEntryList(&ConsoleRecord->Entry);
1218c2c66affSColin Finck         BaseSrvDestroyConsoleRecord(ConsoleRecord);
1219c2c66affSColin Finck     }
1220c2c66affSColin Finck     else
1221c2c66affSColin Finck     {
1222c2c66affSColin Finck         // TODO: NOT IMPLEMENTED
1223c2c66affSColin Finck         UNIMPLEMENTED;
1224c2c66affSColin Finck         Status = STATUS_NOT_IMPLEMENTED;
1225c2c66affSColin Finck     }
1226c2c66affSColin Finck 
1227c2c66affSColin Finck Cleanup:
1228c2c66affSColin Finck     /* Leave the critical section */
1229c2c66affSColin Finck     RtlLeaveCriticalSection(CriticalSection);
1230c2c66affSColin Finck 
1231c2c66affSColin Finck     return Status;
1232c2c66affSColin Finck }
1233c2c66affSColin Finck 
CSR_API(BaseSrvIsFirstVDM)1234c2c66affSColin Finck CSR_API(BaseSrvIsFirstVDM)
1235c2c66affSColin Finck {
1236c2c66affSColin Finck     PBASE_IS_FIRST_VDM IsFirstVDMRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.IsFirstVDMRequest;
1237c2c66affSColin Finck 
1238c2c66affSColin Finck     /* Return the result */
1239c2c66affSColin Finck     IsFirstVDMRequest->FirstVDM = FirstVDM;
1240c2c66affSColin Finck 
1241c2c66affSColin Finck     /* Clear the first VDM flag */
1242c2c66affSColin Finck     FirstVDM = FALSE;
1243c2c66affSColin Finck 
1244c2c66affSColin Finck     return STATUS_SUCCESS;
1245c2c66affSColin Finck }
1246c2c66affSColin Finck 
CSR_API(BaseSrvGetVDMExitCode)1247c2c66affSColin Finck CSR_API(BaseSrvGetVDMExitCode)
1248c2c66affSColin Finck {
1249c2c66affSColin Finck     NTSTATUS Status;
1250c2c66affSColin Finck     PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetVDMExitCodeRequest;
1251c2c66affSColin Finck     PLIST_ENTRY i = NULL;
1252c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord = NULL;
1253c2c66affSColin Finck     PVDM_DOS_RECORD DosRecord = NULL;
1254c2c66affSColin Finck 
1255c2c66affSColin Finck     /* Enter the critical section */
1256c2c66affSColin Finck     RtlEnterCriticalSection(&DosCriticalSection);
1257c2c66affSColin Finck 
1258c2c66affSColin Finck     /* Get the console record */
1259c2c66affSColin Finck     Status = BaseSrvGetConsoleRecord(GetVDMExitCodeRequest->ConsoleHandle, &ConsoleRecord);
1260c2c66affSColin Finck     if (!NT_SUCCESS(Status)) goto Cleanup;
1261c2c66affSColin Finck 
1262c2c66affSColin Finck     /* Search for a DOS record that has the same parent process handle */
1263c2c66affSColin Finck     for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink)
1264c2c66affSColin Finck     {
1265c2c66affSColin Finck         DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
1266c2c66affSColin Finck         if (DosRecord->ClientEvent == GetVDMExitCodeRequest->hParent) break;
1267c2c66affSColin Finck     }
1268c2c66affSColin Finck 
1269c2c66affSColin Finck     /* Check if no DOS record was found */
1270c2c66affSColin Finck     if (i == &ConsoleRecord->DosListHead)
1271c2c66affSColin Finck     {
1272c2c66affSColin Finck         Status = STATUS_NOT_FOUND;
1273c2c66affSColin Finck         goto Cleanup;
1274c2c66affSColin Finck     }
1275c2c66affSColin Finck 
1276c2c66affSColin Finck     /* Check if this task is still running */
1277c2c66affSColin Finck     if (DosRecord->State != VDM_READY)
1278c2c66affSColin Finck     {
1279c2c66affSColin Finck         GetVDMExitCodeRequest->ExitCode = STATUS_PENDING;
1280c2c66affSColin Finck         goto Cleanup;
1281c2c66affSColin Finck     }
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     /* Return the exit code */
1284c2c66affSColin Finck     GetVDMExitCodeRequest->ExitCode = DosRecord->ExitCode;
1285c2c66affSColin Finck 
1286c2c66affSColin Finck     // FIXME: We may just change DosRecord->State to VDM_READY in some cases...
1287c2c66affSColin Finck 
1288c2c66affSColin Finck     /* Since this is a zombie task record, remove it */
1289c2c66affSColin Finck     if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
1290c2c66affSColin Finck     RemoveEntryList(&DosRecord->Entry);
1291c2c66affSColin Finck     RtlFreeHeap(BaseSrvHeap, 0, DosRecord);
1292c2c66affSColin Finck 
1293c2c66affSColin Finck Cleanup:
1294c2c66affSColin Finck     /* Leave the critical section */
1295c2c66affSColin Finck     RtlLeaveCriticalSection(&DosCriticalSection);
1296c2c66affSColin Finck 
1297c2c66affSColin Finck     return Status;
1298c2c66affSColin Finck }
1299c2c66affSColin Finck 
CSR_API(BaseSrvSetReenterCount)1300c2c66affSColin Finck CSR_API(BaseSrvSetReenterCount)
1301c2c66affSColin Finck {
1302c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
1303c2c66affSColin Finck     PBASE_SET_REENTER_COUNT SetReenterCountRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.SetReenterCountRequest;
1304c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord;
1305c2c66affSColin Finck 
1306c2c66affSColin Finck     /* Enter the critical section */
1307c2c66affSColin Finck     RtlEnterCriticalSection(&DosCriticalSection);
1308c2c66affSColin Finck 
1309c2c66affSColin Finck     /* Get the console record */
1310c2c66affSColin Finck     Status = BaseSrvGetConsoleRecord(SetReenterCountRequest->ConsoleHandle, &ConsoleRecord);
1311c2c66affSColin Finck     if (!NT_SUCCESS(Status)) goto Cleanup;
1312c2c66affSColin Finck 
1313c2c66affSColin Finck     if (SetReenterCountRequest->fIncDec == VDM_INC_REENTER_COUNT)
1314c2c66affSColin Finck     {
1315c2c66affSColin Finck         ConsoleRecord->ReenterCount++;
1316c2c66affSColin Finck     }
1317c2c66affSColin Finck     else if (SetReenterCountRequest->fIncDec == VDM_DEC_REENTER_COUNT)
1318c2c66affSColin Finck     {
1319c2c66affSColin Finck         ConsoleRecord->ReenterCount--;
1320c2c66affSColin Finck         if (ConsoleRecord->ServerEvent)
1321c2c66affSColin Finck             NtSetEvent(ConsoleRecord->ServerEvent, NULL);
1322c2c66affSColin Finck     }
1323c2c66affSColin Finck     else
1324c2c66affSColin Finck     {
1325c2c66affSColin Finck         Status = STATUS_INVALID_PARAMETER;
1326c2c66affSColin Finck     }
1327c2c66affSColin Finck 
1328c2c66affSColin Finck Cleanup:
1329c2c66affSColin Finck     /* Leave the critical section */
1330c2c66affSColin Finck     RtlLeaveCriticalSection(&DosCriticalSection);
1331c2c66affSColin Finck 
1332c2c66affSColin Finck     return Status;
1333c2c66affSColin Finck }
1334c2c66affSColin Finck 
CSR_API(BaseSrvSetVDMCurDirs)1335c2c66affSColin Finck CSR_API(BaseSrvSetVDMCurDirs)
1336c2c66affSColin Finck {
1337c2c66affSColin Finck     NTSTATUS Status;
1338c2c66affSColin Finck     PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.VDMCurrentDirsRequest;
1339c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord;
1340c2c66affSColin Finck     PCHAR Buffer = NULL;
1341c2c66affSColin Finck 
1342c2c66affSColin Finck     /* Validate the input buffer */
1343c2c66affSColin Finck     if (!CsrValidateMessageBuffer(ApiMessage,
1344c2c66affSColin Finck                                   (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs,
1345c2c66affSColin Finck                                   VDMCurrentDirsRequest->cchCurDirs,
1346c2c66affSColin Finck                                   sizeof(*VDMCurrentDirsRequest->lpszzCurDirs)))
1347c2c66affSColin Finck     {
1348c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1349c2c66affSColin Finck     }
1350c2c66affSColin Finck 
1351c2c66affSColin Finck     /* Enter the critical section */
1352c2c66affSColin Finck     RtlEnterCriticalSection(&DosCriticalSection);
1353c2c66affSColin Finck 
1354c2c66affSColin Finck     /* Find the console record */
1355c2c66affSColin Finck     Status = BaseSrvGetConsoleRecord(VDMCurrentDirsRequest->ConsoleHandle, &ConsoleRecord);
1356c2c66affSColin Finck     if (!NT_SUCCESS(Status)) goto Cleanup;
1357c2c66affSColin Finck 
1358c2c66affSColin Finck     if (ConsoleRecord->CurrentDirs == NULL)
1359c2c66affSColin Finck     {
1360c2c66affSColin Finck         /* Allocate memory for the current directory information */
1361c2c66affSColin Finck         Buffer = RtlAllocateHeap(BaseSrvHeap,
1362c2c66affSColin Finck                                  HEAP_ZERO_MEMORY,
1363c2c66affSColin Finck                                  VDMCurrentDirsRequest->cchCurDirs);
1364c2c66affSColin Finck     }
1365c2c66affSColin Finck     else
1366c2c66affSColin Finck     {
1367c2c66affSColin Finck         /* Resize the amount of allocated memory */
1368c2c66affSColin Finck         Buffer = RtlReAllocateHeap(BaseSrvHeap,
1369c2c66affSColin Finck                                    HEAP_ZERO_MEMORY,
1370c2c66affSColin Finck                                    ConsoleRecord->CurrentDirs,
1371c2c66affSColin Finck                                    VDMCurrentDirsRequest->cchCurDirs);
1372c2c66affSColin Finck     }
1373c2c66affSColin Finck 
1374c2c66affSColin Finck     if (Buffer == NULL)
1375c2c66affSColin Finck     {
1376c2c66affSColin Finck         /* Allocation failed */
1377c2c66affSColin Finck         Status = STATUS_NO_MEMORY;
1378c2c66affSColin Finck         goto Cleanup;
1379c2c66affSColin Finck     }
1380c2c66affSColin Finck 
1381c2c66affSColin Finck     /* Update the console record */
1382c2c66affSColin Finck     ConsoleRecord->CurrentDirs = Buffer;
1383c2c66affSColin Finck     ConsoleRecord->CurDirsLength = VDMCurrentDirsRequest->cchCurDirs;
1384c2c66affSColin Finck 
1385c2c66affSColin Finck     /* Copy the data */
1386c2c66affSColin Finck     RtlMoveMemory(ConsoleRecord->CurrentDirs,
1387c2c66affSColin Finck                   VDMCurrentDirsRequest->lpszzCurDirs,
1388c2c66affSColin Finck                   VDMCurrentDirsRequest->cchCurDirs);
1389c2c66affSColin Finck 
1390c2c66affSColin Finck Cleanup:
1391c2c66affSColin Finck     /* Leave the critical section */
1392c2c66affSColin Finck     RtlLeaveCriticalSection(&DosCriticalSection);
1393c2c66affSColin Finck 
1394c2c66affSColin Finck     return Status;
1395c2c66affSColin Finck }
1396c2c66affSColin Finck 
CSR_API(BaseSrvGetVDMCurDirs)1397c2c66affSColin Finck CSR_API(BaseSrvGetVDMCurDirs)
1398c2c66affSColin Finck {
1399c2c66affSColin Finck     NTSTATUS Status;
1400c2c66affSColin Finck     PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.VDMCurrentDirsRequest;
1401c2c66affSColin Finck     PVDM_CONSOLE_RECORD ConsoleRecord;
1402c2c66affSColin Finck 
1403c2c66affSColin Finck     /* Validate the output buffer */
1404c2c66affSColin Finck     if (!CsrValidateMessageBuffer(ApiMessage,
1405c2c66affSColin Finck                                   (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs,
1406c2c66affSColin Finck                                   VDMCurrentDirsRequest->cchCurDirs,
1407c2c66affSColin Finck                                   sizeof(*VDMCurrentDirsRequest->lpszzCurDirs)))
1408c2c66affSColin Finck     {
1409c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1410c2c66affSColin Finck     }
1411c2c66affSColin Finck 
1412c2c66affSColin Finck     /* Enter the critical section */
1413c2c66affSColin Finck     RtlEnterCriticalSection(&DosCriticalSection);
1414c2c66affSColin Finck 
1415c2c66affSColin Finck     /* Find the console record */
1416c2c66affSColin Finck     Status = BaseSrvGetConsoleRecord(VDMCurrentDirsRequest->ConsoleHandle, &ConsoleRecord);
1417c2c66affSColin Finck     if (!NT_SUCCESS(Status)) goto Cleanup;
1418c2c66affSColin Finck 
1419c2c66affSColin Finck     /* Return the actual size of the current directory information */
1420c2c66affSColin Finck     VDMCurrentDirsRequest->cchCurDirs = ConsoleRecord->CurDirsLength;
1421c2c66affSColin Finck 
1422c2c66affSColin Finck     /* Check if the buffer is large enough */
1423c2c66affSColin Finck     if (VDMCurrentDirsRequest->cchCurDirs < ConsoleRecord->CurDirsLength)
1424c2c66affSColin Finck     {
1425c2c66affSColin Finck         Status = STATUS_BUFFER_TOO_SMALL;
1426c2c66affSColin Finck         goto Cleanup;
1427c2c66affSColin Finck     }
1428c2c66affSColin Finck 
1429c2c66affSColin Finck     /* Copy the data */
1430c2c66affSColin Finck     RtlMoveMemory(VDMCurrentDirsRequest->lpszzCurDirs,
1431c2c66affSColin Finck                   ConsoleRecord->CurrentDirs,
1432c2c66affSColin Finck                   ConsoleRecord->CurDirsLength);
1433c2c66affSColin Finck 
1434c2c66affSColin Finck Cleanup:
1435c2c66affSColin Finck     /* Leave the critical section */
1436c2c66affSColin Finck     RtlLeaveCriticalSection(&DosCriticalSection);
1437c2c66affSColin Finck 
1438c2c66affSColin Finck     return Status;
1439c2c66affSColin Finck }
1440c2c66affSColin Finck 
CSR_API(BaseSrvBatNotification)1441c2c66affSColin Finck CSR_API(BaseSrvBatNotification)
1442c2c66affSColin Finck {
1443c2c66affSColin Finck     DPRINT1("%s not yet implemented\n", __FUNCTION__);
1444c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1445c2c66affSColin Finck }
1446c2c66affSColin Finck 
CSR_API(BaseSrvRegisterWowExec)1447c2c66affSColin Finck CSR_API(BaseSrvRegisterWowExec)
1448c2c66affSColin Finck {
1449c2c66affSColin Finck     DPRINT1("%s not yet implemented\n", __FUNCTION__);
1450c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1451c2c66affSColin Finck }
1452c2c66affSColin Finck 
CSR_API(BaseSrvRefreshIniFileMapping)1453c2c66affSColin Finck CSR_API(BaseSrvRefreshIniFileMapping)
1454c2c66affSColin Finck {
1455c2c66affSColin Finck     DPRINT1("%s not yet implemented\n", __FUNCTION__);
1456c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
1457c2c66affSColin Finck }
1458c2c66affSColin Finck 
1459c2c66affSColin Finck /* EOF */
1460