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 VOID NTAPI
BaseInitializeVDM(VOID
)
74 /* Initialize the list head */
75 InitializeListHead(&VDMConsoleListHead
);
77 /* Initialize the critical section */
78 RtlInitializeCriticalSection(&DosCriticalSection
);
79 RtlInitializeCriticalSection(&WowCriticalSection
);
82 /* PUBLIC SERVER APIS *********************************************************/
84 CSR_API(BaseSrvCheckVDM
)
87 PBASE_CHECK_VDM CheckVdmRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CheckVDMRequest
;
88 PRTL_CRITICAL_SECTION CriticalSection
= NULL
;
89 PVDM_CONSOLE_RECORD ConsoleRecord
= NULL
;
91 /* Validate the message buffers */
92 if (!CsrValidateMessageBuffer(ApiMessage
,
93 (PVOID
*)&CheckVdmRequest
->CmdLine
,
94 CheckVdmRequest
->CmdLen
,
95 sizeof(*CheckVdmRequest
->CmdLine
))
96 || !CsrValidateMessageBuffer(ApiMessage
,
97 (PVOID
*)&CheckVdmRequest
->AppName
,
98 CheckVdmRequest
->AppLen
,
99 sizeof(*CheckVdmRequest
->AppName
))
100 || !CsrValidateMessageBuffer(ApiMessage
,
101 (PVOID
*)&CheckVdmRequest
->PifFile
,
102 CheckVdmRequest
->PifLen
,
103 sizeof(*CheckVdmRequest
->PifFile
))
104 || !CsrValidateMessageBuffer(ApiMessage
,
105 (PVOID
*)&CheckVdmRequest
->CurDirectory
,
106 CheckVdmRequest
->CurDirectoryLen
,
107 sizeof(*CheckVdmRequest
->CurDirectory
))
108 || !CsrValidateMessageBuffer(ApiMessage
,
109 (PVOID
*)&CheckVdmRequest
->Desktop
,
110 CheckVdmRequest
->DesktopLen
,
111 sizeof(*CheckVdmRequest
->Desktop
))
112 || !CsrValidateMessageBuffer(ApiMessage
,
113 (PVOID
*)&CheckVdmRequest
->Title
,
114 CheckVdmRequest
->TitleLen
,
115 sizeof(*CheckVdmRequest
->Title
))
116 || !CsrValidateMessageBuffer(ApiMessage
,
117 (PVOID
*)&CheckVdmRequest
->Reserved
,
118 CheckVdmRequest
->ReservedLen
,
119 sizeof(*CheckVdmRequest
->Reserved
)))
121 return STATUS_INVALID_PARAMETER
;
124 CriticalSection
= (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
125 ? &DosCriticalSection
126 : &WowCriticalSection
;
128 /* Enter the critical section */
129 RtlEnterCriticalSection(CriticalSection
);
131 /* Check if this is a DOS or WOW VDM */
132 if (CheckVdmRequest
->BinaryType
!= BINARY_TYPE_SEPARATE_WOW
)
134 /* Get the console record */
135 Status
= BaseSrvGetConsoleRecord(CheckVdmRequest
->ConsoleHandle
,
138 if (!NT_SUCCESS(Status
))
140 /* Allocate a new console record */
141 ConsoleRecord
= (PVDM_CONSOLE_RECORD
)RtlAllocateHeap(BaseSrvHeap
,
143 sizeof(VDM_CONSOLE_RECORD
));
144 if (ConsoleRecord
== NULL
)
146 Status
= STATUS_NO_MEMORY
;
150 /* Initialize the console record */
151 ConsoleRecord
->ConsoleHandle
= CheckVdmRequest
->ConsoleHandle
;
152 ConsoleRecord
->CurrentDirs
= NULL
;
153 ConsoleRecord
->CurDirsLength
= 0;
154 ConsoleRecord
->SessionId
= GetNextDosSesId();
155 InitializeListHead(&ConsoleRecord
->DosListHead
);
157 /* Add the console record */
158 InsertTailList(&VDMConsoleListHead
, &ConsoleRecord
->Entry
);
161 // TODO: NOT IMPLEMENTED
163 return STATUS_NOT_IMPLEMENTED
;
167 // TODO: NOT IMPLEMENTED
169 return STATUS_NOT_IMPLEMENTED
;
173 /* Leave the critical section */
174 RtlLeaveCriticalSection(CriticalSection
);
179 CSR_API(BaseSrvUpdateVDMEntry
)
181 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
182 return STATUS_NOT_IMPLEMENTED
;
185 CSR_API(BaseSrvGetNextVDMCommand
)
187 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
188 return STATUS_NOT_IMPLEMENTED
;
191 CSR_API(BaseSrvExitVDM
)
193 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
194 return STATUS_NOT_IMPLEMENTED
;
197 CSR_API(BaseSrvIsFirstVDM
)
199 PBASE_IS_FIRST_VDM IsFirstVDMRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.IsFirstVDMRequest
;
201 /* Return the result */
202 IsFirstVDMRequest
->FirstVDM
= FirstVDM
;
204 /* Clear the first VDM flag */
207 return STATUS_SUCCESS
;
210 CSR_API(BaseSrvGetVDMExitCode
)
212 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
213 return STATUS_NOT_IMPLEMENTED
;
216 CSR_API(BaseSrvSetReenterCount
)
218 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
219 return STATUS_NOT_IMPLEMENTED
;
222 CSR_API(BaseSrvSetVDMCurDirs
)
225 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
226 PVDM_CONSOLE_RECORD ConsoleRecord
;
229 /* Validate the input buffer */
230 if (!CsrValidateMessageBuffer(ApiMessage
,
231 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
232 VDMCurrentDirsRequest
->cchCurDirs
,
233 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
235 return STATUS_INVALID_PARAMETER
;
238 /* Enter the critical section */
239 RtlEnterCriticalSection(&DosCriticalSection
);
241 /* Find the console record */
242 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
243 if (!NT_SUCCESS(Status
)) goto Cleanup
;
245 if (ConsoleRecord
->CurrentDirs
== NULL
)
247 /* Allocate memory for the current directory information */
248 Buffer
= RtlAllocateHeap(BaseSrvHeap
,
250 VDMCurrentDirsRequest
->cchCurDirs
);
254 /* Resize the amount of allocated memory */
255 Buffer
= RtlReAllocateHeap(BaseSrvHeap
,
257 ConsoleRecord
->CurrentDirs
,
258 VDMCurrentDirsRequest
->cchCurDirs
);
263 /* Allocation failed */
264 Status
= STATUS_NO_MEMORY
;
268 /* Update the console record */
269 ConsoleRecord
->CurrentDirs
= Buffer
;
270 ConsoleRecord
->CurDirsLength
= VDMCurrentDirsRequest
->cchCurDirs
;
273 RtlMoveMemory(ConsoleRecord
->CurrentDirs
,
274 VDMCurrentDirsRequest
->lpszzCurDirs
,
275 VDMCurrentDirsRequest
->cchCurDirs
);
278 /* Leave the critical section */
279 RtlLeaveCriticalSection(&DosCriticalSection
);
284 CSR_API(BaseSrvGetVDMCurDirs
)
287 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.VDMCurrentDirsRequest
;
288 PVDM_CONSOLE_RECORD ConsoleRecord
;
290 /* Validate the output buffer */
291 if (!CsrValidateMessageBuffer(ApiMessage
,
292 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
,
293 VDMCurrentDirsRequest
->cchCurDirs
,
294 sizeof(*VDMCurrentDirsRequest
->lpszzCurDirs
)))
296 return STATUS_INVALID_PARAMETER
;
299 /* Enter the critical section */
300 RtlEnterCriticalSection(&DosCriticalSection
);
302 /* Find the console record */
303 Status
= BaseSrvGetConsoleRecord(VDMCurrentDirsRequest
->ConsoleHandle
, &ConsoleRecord
);
304 if (!NT_SUCCESS(Status
)) goto Cleanup
;
306 /* Return the actual size of the current directory information */
307 VDMCurrentDirsRequest
->cchCurDirs
= ConsoleRecord
->CurDirsLength
;
309 /* Check if the buffer is large enough */
310 if (VDMCurrentDirsRequest
->cchCurDirs
< ConsoleRecord
->CurDirsLength
)
312 Status
= STATUS_BUFFER_TOO_SMALL
;
317 RtlMoveMemory(VDMCurrentDirsRequest
->lpszzCurDirs
,
318 ConsoleRecord
->CurrentDirs
,
319 ConsoleRecord
->CurDirsLength
);
322 /* Leave the critical section */
323 RtlLeaveCriticalSection(&DosCriticalSection
);
328 CSR_API(BaseSrvBatNotification
)
330 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
331 return STATUS_NOT_IMPLEMENTED
;
334 CSR_API(BaseSrvRegisterWowExec
)
336 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
337 return STATUS_NOT_IMPLEMENTED
;
340 CSR_API(BaseSrvRefreshIniFileMapping
)
342 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
343 return STATUS_NOT_IMPLEMENTED
;