2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/client/vdm.c
5 * PURPOSE: Virtual DOS Machines (VDM) Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES *******************************************************************/
16 /* TYPES **********************************************************************/
18 typedef struct _ENV_INFO
23 } ENV_INFO
, *PENV_INFO
;
25 /* GLOBALS ********************************************************************/
27 ENV_INFO BasepEnvNameType
[] =
29 {3, sizeof(L
"PATH") , L
"PATH" },
30 {2, sizeof(L
"WINDIR") , L
"WINDIR" },
31 {2, sizeof(L
"SYSTEMROOT"), L
"SYSTEMROOT"},
32 {3, sizeof(L
"TEMP") , L
"TEMP" },
33 {3, sizeof(L
"TMP") , L
"TMP" },
36 UNICODE_STRING BaseDotComSuffixName
= RTL_CONSTANT_STRING(L
".com");
37 UNICODE_STRING BaseDotPifSuffixName
= RTL_CONSTANT_STRING(L
".pif");
38 UNICODE_STRING BaseDotExeSuffixName
= RTL_CONSTANT_STRING(L
".exe");
40 /* FUNCTIONS ******************************************************************/
44 BaseIsDosApplication(IN PUNICODE_STRING PathName
,
47 UNICODE_STRING String
;
50 String
.Length
= BaseDotComSuffixName
.Length
;
51 String
.Buffer
= &PathName
->Buffer
[(PathName
->Length
- String
.Length
) / sizeof(WCHAR
)];
52 if (RtlEqualUnicodeString(&String
, &BaseDotComSuffixName
, TRUE
)) return BINARY_TYPE_COM
;
55 String
.Length
= BaseDotPifSuffixName
.Length
;
56 String
.Buffer
= &PathName
->Buffer
[(PathName
->Length
- String
.Length
) / sizeof(WCHAR
)];
57 if (RtlEqualUnicodeString(&String
, &BaseDotPifSuffixName
, TRUE
)) return BINARY_TYPE_PIF
;
60 String
.Length
= BaseDotExeSuffixName
.Length
;
61 String
.Buffer
= &PathName
->Buffer
[(PathName
->Length
- String
.Length
) / sizeof(WCHAR
)];
62 if (RtlEqualUnicodeString(&String
, &BaseDotExeSuffixName
, TRUE
)) return BINARY_TYPE_EXE
;
69 BaseCheckVDM(IN ULONG BinaryType
,
70 IN PCWCH ApplicationName
,
72 IN PCWCH CurrentDirectory
,
73 IN PANSI_STRING AnsiEnvironment
,
74 IN PBASE_API_MESSAGE ApiMessage
,
76 IN DWORD CreationFlags
,
77 IN LPSTARTUPINFOW StartupInfo
,
78 IN HANDLE hUserToken OPTIONAL
)
81 PBASE_CHECK_VDM CheckVdm
= &ApiMessage
->Data
.CheckVDMRequest
;
82 PCSR_CAPTURE_BUFFER CaptureBuffer
;
83 PWCHAR CurrentDir
= NULL
;
84 PWCHAR ShortAppName
= NULL
;
85 PWCHAR ShortCurrentDir
= NULL
;
87 PCHAR AnsiCmdLine
= NULL
;
88 PCHAR AnsiAppName
= NULL
;
89 PCHAR AnsiCurDirectory
= NULL
;
90 PCHAR AnsiDesktop
= NULL
;
91 PCHAR AnsiTitle
= NULL
;
92 PCHAR AnsiReserved
= NULL
;
93 STARTUPINFOA AnsiStartupInfo
;
96 if (CurrentDirectory
== NULL
)
98 /* Allocate memory for the current directory path */
99 Length
= GetCurrentDirectoryW(0, NULL
);
100 CurrentDir
= (PWCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
102 Length
* sizeof(WCHAR
));
103 if (CurrentDir
== NULL
)
105 Status
= STATUS_NO_MEMORY
;
109 /* Get the current directory */
110 GetCurrentDirectoryW(Length
, CurrentDir
);
111 CurrentDirectory
= CurrentDir
;
114 /* Calculate the size of the short application name */
115 Length
= GetShortPathNameW(ApplicationName
, NULL
, 0);
117 /* Allocate memory for the short application name */
118 ShortAppName
= (PWCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
120 Length
* sizeof(WCHAR
));
123 Status
= STATUS_NO_MEMORY
;
127 /* Get the short application name */
128 if (!GetShortPathNameW(ApplicationName
, ShortAppName
, Length
))
130 /* Try to determine which error occurred */
131 switch (GetLastError())
133 case ERROR_NOT_ENOUGH_MEMORY
:
135 Status
= STATUS_NO_MEMORY
;
139 case ERROR_INVALID_PARAMETER
:
141 Status
= STATUS_INVALID_PARAMETER
;
147 Status
= STATUS_OBJECT_PATH_INVALID
;
154 /* Calculate the size of the short current directory path */
155 Length
= GetShortPathNameW(CurrentDirectory
, NULL
, 0);
157 /* Allocate memory for the short current directory path */
158 ShortCurrentDir
= (PWCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
160 Length
* sizeof(WCHAR
));
161 if (!ShortCurrentDir
)
163 Status
= STATUS_NO_MEMORY
;
167 /* Get the short current directory path */
168 if (!GetShortPathNameW(CurrentDirectory
, ShortCurrentDir
, Length
))
170 /* Try to determine which error occurred */
171 switch (GetLastError())
173 case ERROR_NOT_ENOUGH_MEMORY
:
175 Status
= STATUS_NO_MEMORY
;
179 case ERROR_INVALID_PARAMETER
:
181 Status
= STATUS_INVALID_PARAMETER
;
187 Status
= STATUS_OBJECT_PATH_INVALID
;
193 /* Setup the input parameters */
194 CheckVdm
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
195 CheckVdm
->BinaryType
= BinaryType
;
196 CheckVdm
->CodePage
= CP_ACP
;
197 CheckVdm
->dwCreationFlags
= CreationFlags
;
198 CheckVdm
->CurDrive
= CurrentDirectory
[0] - L
'A';
199 CheckVdm
->CmdLen
= wcslen(CommandLine
) + 1;
200 CheckVdm
->AppLen
= wcslen(ShortAppName
) + 1;
201 CheckVdm
->PifLen
= 0; // TODO: PIF file support!
202 CheckVdm
->CurDirectoryLen
= wcslen(ShortCurrentDir
) + 1;
203 CheckVdm
->EnvLen
= AnsiEnvironment
->Length
;
204 CheckVdm
->DesktopLen
= (StartupInfo
->lpDesktop
!= NULL
) ? (wcslen(StartupInfo
->lpDesktop
) + 1) : 0;
205 CheckVdm
->TitleLen
= (StartupInfo
->lpTitle
!= NULL
) ? (wcslen(StartupInfo
->lpTitle
) + 1) : 0;
206 CheckVdm
->ReservedLen
= (StartupInfo
->lpReserved
!= NULL
) ? (wcslen(StartupInfo
->lpReserved
) + 1) : 0;
208 if (StartupInfo
->dwFlags
& STARTF_USESTDHANDLES
)
210 /* Set the standard handles */
211 CheckVdm
->StdIn
= StartupInfo
->hStdInput
;
212 CheckVdm
->StdOut
= StartupInfo
->hStdOutput
;
213 CheckVdm
->StdErr
= StartupInfo
->hStdError
;
216 /* Allocate memory for the ANSI strings */
217 AnsiCmdLine
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, CheckVdm
->CmdLen
);
218 AnsiAppName
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, CheckVdm
->AppLen
);
219 AnsiCurDirectory
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, CheckVdm
->CurDirectoryLen
);
220 if (StartupInfo
->lpDesktop
) AnsiDesktop
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
222 CheckVdm
->DesktopLen
);
223 if (StartupInfo
->lpTitle
) AnsiTitle
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
226 if (StartupInfo
->lpReserved
) AnsiReserved
= (PCHAR
)RtlAllocateHeap(RtlGetProcessHeap(),
228 CheckVdm
->ReservedLen
);
233 || (StartupInfo
->lpDesktop
&& !AnsiDesktop
)
234 || (StartupInfo
->lpTitle
&& !AnsiTitle
)
235 || (StartupInfo
->lpReserved
&& !AnsiReserved
))
237 Status
= STATUS_NO_MEMORY
;
241 /* Convert the command line into an ANSI string */
242 WideCharToMultiByte(CP_ACP
,
251 /* Convert the short application name into an ANSI string */
252 WideCharToMultiByte(CP_ACP
,
261 /* Convert the short current directory path into an ANSI string */
262 WideCharToMultiByte(CP_ACP
,
265 CheckVdm
->CurDirectoryLen
,
267 CheckVdm
->CurDirectoryLen
,
271 if (StartupInfo
->lpDesktop
)
273 /* Convert the desktop name into an ANSI string */
274 WideCharToMultiByte(CP_ACP
,
276 StartupInfo
->lpDesktop
,
277 CheckVdm
->DesktopLen
,
279 CheckVdm
->DesktopLen
,
285 if (StartupInfo
->lpTitle
)
287 /* Convert the title into an ANSI string */
288 WideCharToMultiByte(CP_ACP
,
290 StartupInfo
->lpTitle
,
299 if (StartupInfo
->lpReserved
)
301 /* Convert the reserved value into an ANSI string */
302 WideCharToMultiByte(CP_ACP
,
304 StartupInfo
->lpReserved
,
305 CheckVdm
->ReservedLen
,
307 CheckVdm
->ReservedLen
,
313 /* Fill the ANSI startup info structure */
314 RtlCopyMemory(&AnsiStartupInfo
, StartupInfo
, sizeof(STARTUPINFO
));
315 AnsiStartupInfo
.lpReserved
= AnsiReserved
;
316 AnsiStartupInfo
.lpDesktop
= AnsiDesktop
;
317 AnsiStartupInfo
.lpTitle
= AnsiTitle
;
319 /* Allocate the capture buffer */
320 CaptureBuffer
= CsrAllocateCaptureBuffer(NumStrings
,
324 + CheckVdm
->CurDirectoryLen
325 + CheckVdm
->DesktopLen
327 + CheckVdm
->ReservedLen
329 + sizeof(STARTUPINFOA
));
330 if (CaptureBuffer
== NULL
)
332 Status
= STATUS_NO_MEMORY
;
336 /* Capture the command line */
337 CsrCaptureMessageBuffer(CaptureBuffer
,
340 (PVOID
*)&CheckVdm
->CmdLine
);
342 /* Capture the application name */
343 CsrCaptureMessageBuffer(CaptureBuffer
,
346 (PVOID
*)&CheckVdm
->AppName
);
348 CheckVdm
->PifFile
= NULL
; // TODO: PIF file support!
350 /* Capture the current directory */
351 CsrCaptureMessageBuffer(CaptureBuffer
,
353 CheckVdm
->CurDirectoryLen
,
354 (PVOID
*)&CheckVdm
->CurDirectory
);
356 /* Capture the environment */
357 CsrCaptureMessageBuffer(CaptureBuffer
,
358 AnsiEnvironment
->Buffer
,
360 (PVOID
*)&CheckVdm
->Env
);
362 /* Capture the startup info structure */
363 CsrCaptureMessageBuffer(CaptureBuffer
,
365 sizeof(STARTUPINFOA
),
366 (PVOID
*)&CheckVdm
->StartupInfo
);
368 if (StartupInfo
->lpDesktop
)
370 /* Capture the desktop name */
371 CsrCaptureMessageBuffer(CaptureBuffer
,
373 CheckVdm
->DesktopLen
,
374 (PVOID
*)&CheckVdm
->Desktop
);
376 else CheckVdm
->Desktop
= NULL
;
378 if (StartupInfo
->lpTitle
)
380 /* Capture the title */
381 CsrCaptureMessageBuffer(CaptureBuffer
,
384 (PVOID
*)&CheckVdm
->Title
);
386 else CheckVdm
->Title
= NULL
;
388 if (StartupInfo
->lpReserved
)
390 /* Capture the reserved parameter */
391 CsrCaptureMessageBuffer(CaptureBuffer
,
393 CheckVdm
->ReservedLen
,
394 (PVOID
*)&CheckVdm
->Reserved
);
396 else CheckVdm
->Reserved
= NULL
;
398 /* Send the message to CSRSS */
399 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)ApiMessage
,
401 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepCheckVDM
),
402 sizeof(BASE_CHECK_VDM
));
404 /* Write back the task ID */
405 *iTask
= CheckVdm
->iTask
;
409 /* Free the ANSI strings */
410 if (AnsiCmdLine
) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine
);
411 if (AnsiAppName
) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName
);
412 if (AnsiCurDirectory
) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory
);
413 if (AnsiDesktop
) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop
);
414 if (AnsiTitle
) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle
);
415 if (AnsiReserved
) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved
);
417 /* Free the capture buffer */
418 CsrFreeCaptureBuffer(CaptureBuffer
);
420 /* Free the short paths */
421 if (ShortAppName
) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName
);
422 if (ShortCurrentDir
) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir
);
424 /* Free the current directory, if it was allocated here */
425 if (CurrentDir
) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir
);
432 BaseUpdateVDMEntry(IN ULONG UpdateIndex
,
433 IN OUT PHANDLE WaitHandle
,
438 BASE_API_MESSAGE ApiMessage
;
439 PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry
= &ApiMessage
.Data
.UpdateVDMEntryRequest
;
441 /* Check what update is being sent */
444 /* VDM is being undone */
447 /* Tell the server how far we had gotten along */
448 UpdateVdmEntry
->iTask
= HandleToUlong(*WaitHandle
);
449 UpdateVdmEntry
->VDMCreationState
= IndexInfo
;
453 /* VDM is ready with a new process handle */
454 case VdmEntryUpdateProcess
:
456 /* Send it the process handle */
457 UpdateVdmEntry
->VDMProcessHandle
= *WaitHandle
;
458 UpdateVdmEntry
->iTask
= IndexInfo
;
463 /* Also check what kind of binary this is for the console handle */
464 if (BinaryType
== BINARY_TYPE_WOW
)
466 /* Magic value for 16-bit apps */
467 UpdateVdmEntry
->ConsoleHandle
= (HANDLE
)-1;
469 else if (UpdateVdmEntry
->iTask
)
471 /* No handle for true VDM */
472 UpdateVdmEntry
->ConsoleHandle
= NULL
;
476 /* Otherwise, use the regular console handle */
477 UpdateVdmEntry
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
480 /* Finally write the index and binary type */
481 UpdateVdmEntry
->EntryIndex
= UpdateIndex
;
482 UpdateVdmEntry
->BinaryType
= BinaryType
;
484 /* Send the message to CSRSS */
485 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
487 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepUpdateVDMEntry
),
488 sizeof(BASE_UPDATE_VDM_ENTRY
));
489 if (!NT_SUCCESS(Status
))
492 BaseSetLastNTError(Status
);
496 /* If this was an update, CSRSS returns a new wait handle */
497 if (UpdateIndex
== VdmEntryUpdateProcess
)
499 /* Return it to the caller */
500 *WaitHandle
= UpdateVdmEntry
->WaitObjectForParent
;
509 BaseCheckForVDM(IN HANDLE ProcessHandle
,
510 OUT LPDWORD ExitCode
)
513 EVENT_BASIC_INFORMATION EventBasicInfo
;
514 BASE_API_MESSAGE ApiMessage
;
515 PBASE_GET_VDM_EXIT_CODE GetVdmExitCode
= &ApiMessage
.Data
.GetVDMExitCodeRequest
;
517 /* It's VDM if the process is actually a wait handle (an event) */
518 Status
= NtQueryEvent(ProcessHandle
,
519 EventBasicInformation
,
521 sizeof(EventBasicInfo
),
523 if (!NT_SUCCESS(Status
)) return FALSE
;
525 /* Setup the input parameters */
526 GetVdmExitCode
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
527 GetVdmExitCode
->hParent
= ProcessHandle
;
530 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
532 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepGetVDMExitCode
),
533 sizeof(BASE_GET_VDM_EXIT_CODE
));
534 if (!NT_SUCCESS(Status
)) return FALSE
;
536 /* Get the exit code from the reply */
537 *ExitCode
= GetVdmExitCode
->ExitCode
;
543 BaseGetVdmConfigInfo(IN LPCWSTR CommandLineReserved
,
546 IN PUNICODE_STRING CmdLineString
,
549 WCHAR Buffer
[MAX_PATH
];
550 WCHAR CommandLine
[MAX_PATH
* 2];
553 /* Clear the buffer in case we fail */
554 CmdLineString
->Buffer
= 0;
556 /* Always return the same size: 16 Mb */
557 *VdmSize
= 0x1000000;
559 /* Get the system directory */
560 Length
= GetSystemDirectoryW(Buffer
, MAX_PATH
);
561 if (!(Length
) || (Length
>= MAX_PATH
))
563 /* Eliminate no path or path too big */
564 SetLastError(ERROR_INVALID_NAME
);
568 /* Check if this is VDM with a DOS Sequence ID */
572 * Build the VDM string for it:
573 * -i%lx : Gives the DOS Sequence ID;
574 * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
576 _snwprintf(CommandLine
,
577 sizeof(CommandLine
) / sizeof(CommandLine
[0]),
578 L
"\"%s\\ntvdm.exe\" -i%lx %s%c",
581 (BinaryType
== BINARY_TYPE_DOS
) ? L
" " : L
"-w",
582 (BinaryType
== BINARY_TYPE_SEPARATE_WOW
) ? L
's' : L
' ');
587 * Build the string for it without the DOS Sequence ID:
588 * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
590 _snwprintf(CommandLine
,
591 sizeof(CommandLine
) / sizeof(CommandLine
[0]),
592 L
"\"%s\\ntvdm.exe\" %s%c",
594 (BinaryType
== BINARY_TYPE_DOS
) ? L
" " : L
"-w",
595 (BinaryType
== BINARY_TYPE_SEPARATE_WOW
) ? L
's' : L
' ');
598 /* Create the actual string */
599 return RtlCreateUnicodeString(CmdLineString
, CommandLine
);
604 BaseGetEnvNameType_U(IN PWCHAR Name
,
610 /* Start by assuming unknown type */
613 /* Loop all the environment names */
614 for (i
= 0; i
< (sizeof(BasepEnvNameType
) / sizeof(ENV_INFO
)); i
++)
617 EnvInfo
= &BasepEnvNameType
[i
];
619 /* Check if it matches the name */
620 if ((EnvInfo
->NameLength
== NameLength
) &&
621 !(_wcsnicmp(EnvInfo
->Name
, Name
, NameLength
)))
623 /* It does, return the type */
624 NameType
= EnvInfo
->NameType
;
629 /* Return what we found, or unknown if nothing */
635 BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv
,
636 IN PUNICODE_STRING UnicodeEnv
)
640 /* Clear the ASCII buffer since Rtl creates this for us */
641 if (AnsiEnv
->Buffer
) RtlFreeAnsiString(AnsiEnv
);
643 /* The Unicode buffer is build by hand, though */
644 if (UnicodeEnv
->Buffer
)
646 /* So clear it through the API */
647 NtFreeVirtualMemory(NtCurrentProcess(),
648 (PVOID
*)&UnicodeEnv
->Buffer
,
659 BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment
,
660 IN PANSI_STRING AnsiEnv
,
661 IN PUNICODE_STRING UnicodeEnv
)
664 ULONG RegionSize
, EnvironmentSize
= 0;
665 PWCHAR SourcePtr
, DestPtr
, Environment
, NewEnvironment
= NULL
;
666 WCHAR PathBuffer
[MAX_PATH
];
669 /* Make sure we have both strings */
670 if (!(AnsiEnv
) || !(UnicodeEnv
))
673 SetLastError(ERROR_INVALID_PARAMETER
);
677 /* Check if an environment was passed in */
680 /* Nope, create one */
681 Status
= RtlCreateEnvironment(TRUE
, &Environment
);
682 if (!NT_SUCCESS(Status
)) goto Quickie
;
686 /* Use the one we got */
687 Environment
= lpEnvironment
;
690 /* Do we have something now ? */
693 /* Still not, fail out */
694 SetLastError(ERROR_BAD_ENVIRONMENT
);
698 /* Count how much space the whole environment takes */
699 SourcePtr
= Environment
;
700 while ((*SourcePtr
++ != UNICODE_NULL
) && (*SourcePtr
!= UNICODE_NULL
)) EnvironmentSize
++;
701 EnvironmentSize
+= sizeof(UNICODE_NULL
);
703 /* Allocate a new copy */
704 RegionSize
= (EnvironmentSize
+ MAX_PATH
) * sizeof(WCHAR
);
705 if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(),
706 (PVOID
*)&NewEnvironment
,
712 /* We failed, bail out */
713 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
714 NewEnvironment
= NULL
;
718 /* Begin parsing the new environment */
719 SourcePtr
= Environment
;
720 DestPtr
= NewEnvironment
;
722 while (*SourcePtr
!= UNICODE_NULL
)
724 while (*SourcePtr
!= UNICODE_NULL
)
726 if (*SourcePtr
== L
'=')
728 /* Store the '=' sign */
729 *DestPtr
++ = *SourcePtr
++;
731 /* Check if this is likely a full path */
732 if (isalphaW(SourcePtr
[0])
733 && (SourcePtr
[1] == L
':')
734 && ((SourcePtr
[2] == '\\') || (SourcePtr
[2] == '/')))
736 PWCHAR Delimiter
= wcschr(SourcePtr
, L
';');
739 if (Delimiter
!= NULL
)
743 min(Delimiter
- SourcePtr
, MAX_PATH
));
745 /* Seek to the part after the delimiter */
746 SourcePtr
= Delimiter
+ 1;
750 wcsncpy(PathBuffer
, SourcePtr
, MAX_PATH
);
752 /* Seek to the end of the string */
753 SourcePtr
= wcschr(SourcePtr
, UNICODE_NULL
);
756 /* Convert the path into a short path */
757 NumChars
= GetShortPathNameW(PathBuffer
,
759 EnvironmentSize
- (DestPtr
- NewEnvironment
));
763 * If it failed, this block won't be executed, so it
764 * will continue from the character after the '=' sign.
768 /* Append the delimiter */
769 if (Delimiter
!= NULL
) *DestPtr
++ = L
';';
773 else if (islowerW(*SourcePtr
)) *DestPtr
++ = toupperW(*SourcePtr
++);
774 else *DestPtr
++ = *SourcePtr
++;
777 /* Copy the terminating NULL character */
778 *DestPtr
++ = *SourcePtr
++;
782 *DestPtr
++ = UNICODE_NULL
;
784 /* Initialize the unicode string to hold it */
785 EnvironmentSize
= (DestPtr
- NewEnvironment
) * sizeof(WCHAR
);
786 RtlInitEmptyUnicodeString(UnicodeEnv
, NewEnvironment
, (USHORT
)EnvironmentSize
);
787 UnicodeEnv
->Length
= (USHORT
)EnvironmentSize
;
789 /* Create the ASCII version of it */
790 Status
= RtlUnicodeStringToAnsiString(AnsiEnv
, UnicodeEnv
, TRUE
);
791 if (!NT_SUCCESS(Status
))
793 /* Set last error if conversion failure */
794 BaseSetLastNTError(Status
);
798 /* Everything went okay, so return success */
800 NewEnvironment
= NULL
;
804 /* Cleanup path starts here, start by destroying the envrionment copy */
805 if (!(lpEnvironment
) && (Environment
)) RtlDestroyEnvironment(Environment
);
807 /* See if we are here due to failure */
810 /* Initialize the paths to be empty */
811 RtlInitEmptyUnicodeString(UnicodeEnv
, NULL
, 0);
812 RtlInitEmptyAnsiString(AnsiEnv
, NULL
, 0);
814 /* Free the environment copy */
816 Status
= NtFreeVirtualMemory(NtCurrentProcess(),
817 (PVOID
*)&NewEnvironment
,
820 ASSERT(NT_SUCCESS(Status
));
823 /* Return the result */
828 /* Check whether a file is an OS/2 or a very old Windows executable
829 * by testing on import of KERNEL.
831 * FIXME: is reading the module imports the only way of discerning
832 * old Windows binaries from OS/2 ones ? At least it seems so...
835 InternalIsOS2OrOldWin(HANDLE hFile
, IMAGE_DOS_HEADER
*mz
, IMAGE_OS2_HEADER
*ne
)
838 LPWORD modtab
= NULL
;
839 LPSTR nametab
= NULL
;
844 CurPos
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
);
846 /* read modref table */
847 if((SetFilePointer(hFile
, mz
->e_lfanew
+ ne
->ne_modtab
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
848 (!(modtab
= HeapAlloc(GetProcessHeap(), 0, ne
->ne_cmod
* sizeof(WORD
)))) ||
849 (!(ReadFile(hFile
, modtab
, ne
->ne_cmod
* sizeof(WORD
), &Read
, NULL
))) ||
850 (Read
!= (DWORD
)ne
->ne_cmod
* sizeof(WORD
)))
855 /* read imported names table */
856 if((SetFilePointer(hFile
, mz
->e_lfanew
+ ne
->ne_imptab
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
857 (!(nametab
= HeapAlloc(GetProcessHeap(), 0, ne
->ne_enttab
- ne
->ne_imptab
))) ||
858 (!(ReadFile(hFile
, nametab
, ne
->ne_enttab
- ne
->ne_imptab
, &Read
, NULL
))) ||
859 (Read
!= (DWORD
)ne
->ne_enttab
- ne
->ne_imptab
))
864 for(i
= 0; i
< ne
->ne_cmod
; i
++)
867 module
= &nametab
[modtab
[i
]];
868 if(!strncmp(&module
[1], "KERNEL", module
[0]))
870 /* very old windows file */
877 DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
880 HeapFree(GetProcessHeap(), 0, modtab
);
881 HeapFree(GetProcessHeap(), 0, nametab
);
882 SetFilePointer(hFile
, CurPos
, NULL
, FILE_BEGIN
);
887 InternalGetBinaryType(HANDLE hFile
)
893 unsigned char magic
[4];
894 unsigned char ignored
[12];
900 unsigned long cputype
;
901 unsigned long cpusubtype
;
902 unsigned long filetype
;
909 if((SetFilePointer(hFile
, 0, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
910 (!ReadFile(hFile
, &Header
, sizeof(Header
), &Read
, NULL
) ||
911 (Read
!= sizeof(Header
))))
913 return BINARY_UNKNOWN
;
916 if(!memcmp(Header
.elf
.magic
, "\177ELF", sizeof(Header
.elf
.magic
)))
918 /* FIXME: we don't bother to check byte order, architecture, etc. */
919 switch(Header
.elf
.type
)
922 return BINARY_UNIX_EXE
;
924 return BINARY_UNIX_LIB
;
926 return BINARY_UNKNOWN
;
929 /* Mach-o File with Endian set to Big Endian or Little Endian*/
930 if(Header
.macho
.magic
== 0xFEEDFACE ||
931 Header
.macho
.magic
== 0xCEFAEDFE)
933 switch(Header
.macho
.filetype
)
937 return BINARY_UNIX_LIB
;
939 return BINARY_UNKNOWN
;
942 /* Not ELF, try DOS */
943 if(Header
.mz
.e_magic
== IMAGE_DOS_SIGNATURE
)
945 /* We do have a DOS image so we will now try to seek into
946 * the file by the amount indicated by the field
947 * "Offset to extended header" and read in the
948 * "magic" field information at that location.
949 * This will tell us if there is more header information
952 if((SetFilePointer(hFile
, Header
.mz
.e_lfanew
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
) ||
953 (!ReadFile(hFile
, magic
, sizeof(magic
), &Read
, NULL
) ||
954 (Read
!= sizeof(magic
))))
959 /* Reading the magic field succeeded so
960 * we will try to determine what type it is.
962 if(!memcmp(magic
, "PE\0\0", sizeof(magic
)))
964 IMAGE_FILE_HEADER FileHeader
;
965 if(!ReadFile(hFile
, &FileHeader
, sizeof(IMAGE_FILE_HEADER
), &Read
, NULL
) ||
966 (Read
!= sizeof(IMAGE_FILE_HEADER
)))
971 /* FIXME - detect 32/64 bit */
973 if(FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
974 return BINARY_PE_DLL32
;
975 return BINARY_PE_EXE32
;
978 if(!memcmp(magic
, "NE", 2))
980 /* This is a Windows executable (NE) header. This can
981 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
982 * DOS program (running under a DOS extender). To decide
983 * which, we'll have to read the NE header.
986 if((SetFilePointer(hFile
, Header
.mz
.e_lfanew
, NULL
, FILE_BEGIN
) == 1) ||
987 !ReadFile(hFile
, &ne
, sizeof(IMAGE_OS2_HEADER
), &Read
, NULL
) ||
988 (Read
!= sizeof(IMAGE_OS2_HEADER
)))
990 /* Couldn't read header, so abort. */
1001 return InternalIsOS2OrOldWin(hFile
, &Header
.mz
, &ne
);
1006 return BINARY_UNKNOWN
;
1015 LPCWSTR lpApplicationName
,
1016 LPDWORD lpBinaryType
1022 if(!lpApplicationName
|| !lpBinaryType
)
1024 SetLastError(ERROR_INVALID_PARAMETER
);
1028 hFile
= CreateFileW(lpApplicationName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
1029 OPEN_EXISTING
, 0, 0);
1030 if(hFile
== INVALID_HANDLE_VALUE
)
1035 BinType
= InternalGetBinaryType(hFile
);
1040 case BINARY_UNKNOWN
:
1045 * guess from filename
1047 if(!(dot
= wcsrchr(lpApplicationName
, L
'.')))
1051 if(!lstrcmpiW(dot
, L
".COM"))
1053 *lpBinaryType
= SCS_DOS_BINARY
;
1056 if(!lstrcmpiW(dot
, L
".PIF"))
1058 *lpBinaryType
= SCS_PIF_BINARY
;
1063 case BINARY_PE_EXE32
:
1064 case BINARY_PE_DLL32
:
1066 *lpBinaryType
= SCS_32BIT_BINARY
;
1069 case BINARY_PE_EXE64
:
1070 case BINARY_PE_DLL64
:
1072 *lpBinaryType
= SCS_64BIT_BINARY
;
1077 *lpBinaryType
= SCS_WOW_BINARY
;
1082 *lpBinaryType
= SCS_OS216_BINARY
;
1087 *lpBinaryType
= SCS_DOS_BINARY
;
1090 case BINARY_UNIX_EXE
:
1091 case BINARY_UNIX_LIB
:
1097 DPRINT1("Invalid binary type %lu returned!\n", BinType
);
1106 GetBinaryTypeA(IN LPCSTR lpApplicationName
,
1107 OUT LPDWORD lpBinaryType
)
1109 ANSI_STRING ApplicationNameString
;
1110 UNICODE_STRING ApplicationNameW
;
1111 BOOL StringAllocated
= FALSE
, Result
;
1114 RtlInitAnsiString(&ApplicationNameString
, lpApplicationName
);
1116 if (ApplicationNameString
.Length
* sizeof(WCHAR
) >= NtCurrentTeb()->StaticUnicodeString
.MaximumLength
)
1118 StringAllocated
= TRUE
;
1119 Status
= RtlAnsiStringToUnicodeString(&ApplicationNameW
, &ApplicationNameString
, TRUE
);
1123 Status
= RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString
), &ApplicationNameString
, FALSE
);
1126 if (!NT_SUCCESS(Status
))
1128 BaseSetLastNTError(Status
);
1132 if (StringAllocated
)
1134 Result
= GetBinaryTypeW(ApplicationNameW
.Buffer
, lpBinaryType
);
1135 RtlFreeUnicodeString(&ApplicationNameW
);
1139 Result
= GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString
.Buffer
, lpBinaryType
);
1150 CmdBatNotification (
1163 ExitVDM(BOOL IsWow
, ULONG iWowTask
)
1165 BASE_API_MESSAGE ApiMessage
;
1166 PBASE_EXIT_VDM ExitVdm
= &ApiMessage
.Data
.ExitVDMRequest
;
1168 /* Setup the input parameters */
1169 ExitVdm
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1170 ExitVdm
->iWowTask
= IsWow
? iWowTask
: 0; /* Always zero for DOS tasks */
1171 ExitVdm
->WaitObjectForVDM
= NULL
;
1174 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1176 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepExitVDM
),
1177 sizeof(BASE_EXIT_VDM
));
1179 /* Close the returned wait object handle, if any */
1180 if (NT_SUCCESS(ApiMessage
.Status
) && (ExitVdm
->WaitObjectForVDM
!= NULL
))
1182 CloseHandle(ExitVdm
->WaitObjectForVDM
);
1191 GetNextVDMCommand(PVDM_COMMAND_INFO CommandData
)
1194 BOOL Result
= FALSE
;
1195 BASE_API_MESSAGE ApiMessage
;
1196 PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand
= &ApiMessage
.Data
.GetNextVDMCommandRequest
;
1197 PBASE_IS_FIRST_VDM IsFirstVdm
= &ApiMessage
.Data
.IsFirstVDMRequest
;
1198 PBASE_SET_REENTER_COUNT SetReenterCount
= &ApiMessage
.Data
.SetReenterCountRequest
;
1199 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
1200 ULONG NumStrings
= 0;
1202 if (CommandData
!= NULL
)
1204 if (CommandData
->VDMState
& (VDM_NOT_LOADED
| VDM_NOT_READY
| VDM_READY
))
1206 /* Clear the structure */
1207 ZeroMemory(GetNextVdmCommand
, sizeof(*GetNextVdmCommand
));
1209 /* Setup the input parameters */
1210 GetNextVdmCommand
->iTask
= CommandData
->TaskId
;
1211 GetNextVdmCommand
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1212 GetNextVdmCommand
->CmdLen
= CommandData
->CmdLen
;
1213 GetNextVdmCommand
->AppLen
= CommandData
->AppLen
;
1214 GetNextVdmCommand
->PifLen
= CommandData
->PifLen
;
1215 GetNextVdmCommand
->CurDirectoryLen
= CommandData
->CurDirectoryLen
;
1216 GetNextVdmCommand
->EnvLen
= CommandData
->EnvLen
;
1217 GetNextVdmCommand
->DesktopLen
= CommandData
->DesktopLen
;
1218 GetNextVdmCommand
->TitleLen
= CommandData
->TitleLen
;
1219 GetNextVdmCommand
->ReservedLen
= CommandData
->ReservedLen
;
1220 GetNextVdmCommand
->VDMState
= CommandData
->VDMState
;
1222 /* Count the number of strings */
1223 if (CommandData
->CmdLen
) NumStrings
++;
1224 if (CommandData
->AppLen
) NumStrings
++;
1225 if (CommandData
->PifLen
) NumStrings
++;
1226 if (CommandData
->CurDirectoryLen
) NumStrings
++;
1227 if (CommandData
->EnvLen
) NumStrings
++;
1228 if (CommandData
->DesktopLen
) NumStrings
++;
1229 if (CommandData
->TitleLen
) NumStrings
++;
1230 if (CommandData
->ReservedLen
) NumStrings
++;
1232 /* Allocate the capture buffer */
1233 CaptureBuffer
= CsrAllocateCaptureBuffer(NumStrings
+ 1,
1234 GetNextVdmCommand
->CmdLen
1235 + GetNextVdmCommand
->AppLen
1236 + GetNextVdmCommand
->PifLen
1237 + GetNextVdmCommand
->CurDirectoryLen
1238 + GetNextVdmCommand
->EnvLen
1239 + GetNextVdmCommand
->DesktopLen
1240 + GetNextVdmCommand
->TitleLen
1241 + GetNextVdmCommand
->ReservedLen
1242 + sizeof(STARTUPINFOA
));
1243 if (CaptureBuffer
== NULL
)
1245 BaseSetLastNTError(STATUS_NO_MEMORY
);
1249 /* Allocate memory for the startup info */
1250 CsrAllocateMessagePointer(CaptureBuffer
,
1251 sizeof(STARTUPINFOA
),
1252 (PVOID
*)&GetNextVdmCommand
->StartupInfo
);
1254 if (CommandData
->CmdLen
)
1256 /* Allocate memory for the command line */
1257 CsrAllocateMessagePointer(CaptureBuffer
,
1258 CommandData
->CmdLen
,
1259 (PVOID
*)&GetNextVdmCommand
->CmdLine
);
1262 if (CommandData
->AppLen
)
1264 /* Allocate memory for the application name */
1265 CsrAllocateMessagePointer(CaptureBuffer
,
1266 CommandData
->AppLen
,
1267 (PVOID
*)&GetNextVdmCommand
->AppName
);
1270 if (CommandData
->PifLen
)
1272 /* Allocate memory for the PIF file name */
1273 CsrAllocateMessagePointer(CaptureBuffer
,
1274 CommandData
->PifLen
,
1275 (PVOID
*)&GetNextVdmCommand
->PifFile
);
1278 if (CommandData
->CurDirectoryLen
)
1280 /* Allocate memory for the current directory */
1281 CsrAllocateMessagePointer(CaptureBuffer
,
1282 CommandData
->CurDirectoryLen
,
1283 (PVOID
*)&GetNextVdmCommand
->CurDirectory
);
1286 if (CommandData
->EnvLen
)
1288 /* Allocate memory for the environment */
1289 CsrAllocateMessagePointer(CaptureBuffer
,
1290 CommandData
->EnvLen
,
1291 (PVOID
*)&GetNextVdmCommand
->Env
);
1294 if (CommandData
->DesktopLen
)
1296 /* Allocate memory for the desktop name */
1297 CsrAllocateMessagePointer(CaptureBuffer
,
1298 CommandData
->DesktopLen
,
1299 (PVOID
*)&GetNextVdmCommand
->Desktop
);
1302 if (CommandData
->TitleLen
)
1304 /* Allocate memory for the title */
1305 CsrAllocateMessagePointer(CaptureBuffer
,
1306 CommandData
->TitleLen
,
1307 (PVOID
*)&GetNextVdmCommand
->Title
);
1310 if (CommandData
->ReservedLen
)
1312 /* Allocate memory for the reserved parameter */
1313 CsrAllocateMessagePointer(CaptureBuffer
,
1314 CommandData
->ReservedLen
,
1315 (PVOID
*)&GetNextVdmCommand
->Reserved
);
1321 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1323 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepGetNextVDMCommand
),
1324 sizeof(BASE_GET_NEXT_VDM_COMMAND
));
1326 if (!NT_SUCCESS(Status
))
1328 /* Store the correct lengths */
1329 CommandData
->CmdLen
= GetNextVdmCommand
->CmdLen
;
1330 CommandData
->AppLen
= GetNextVdmCommand
->AppLen
;
1331 CommandData
->PifLen
= GetNextVdmCommand
->PifLen
;
1332 CommandData
->CurDirectoryLen
= GetNextVdmCommand
->CurDirectoryLen
;
1333 CommandData
->EnvLen
= GetNextVdmCommand
->EnvLen
;
1334 CommandData
->DesktopLen
= GetNextVdmCommand
->DesktopLen
;
1335 CommandData
->TitleLen
= GetNextVdmCommand
->TitleLen
;
1336 CommandData
->ReservedLen
= GetNextVdmCommand
->ReservedLen
;
1338 BaseSetLastNTError(Status
);
1342 /* Did we receive an event handle? */
1343 if (GetNextVdmCommand
->WaitObjectForVDM
!= NULL
)
1345 /* Wait for the event to become signaled and try again */
1346 Status
= NtWaitForSingleObject(GetNextVdmCommand
->WaitObjectForVDM
,
1349 if (!NT_SUCCESS(Status
))
1351 BaseSetLastNTError(Status
);
1355 /* Set the retry flag and clear the exit code */
1356 GetNextVdmCommand
->VDMState
|= VDM_FLAG_RETRY
;
1357 GetNextVdmCommand
->ExitCode
= 0;
1360 while (GetNextVdmCommand
->WaitObjectForVDM
!= NULL
);
1362 /* Write back the standard handles */
1363 CommandData
->StdIn
= GetNextVdmCommand
->StdIn
;
1364 CommandData
->StdOut
= GetNextVdmCommand
->StdOut
;
1365 CommandData
->StdErr
= GetNextVdmCommand
->StdErr
;
1367 /* Write back the startup info */
1368 RtlMoveMemory(&CommandData
->StartupInfo
,
1369 GetNextVdmCommand
->StartupInfo
,
1370 sizeof(STARTUPINFOA
));
1372 if (CommandData
->CmdLen
)
1374 /* Write back the command line */
1375 RtlMoveMemory(CommandData
->CmdLine
,
1376 GetNextVdmCommand
->CmdLine
,
1377 GetNextVdmCommand
->CmdLen
);
1379 /* Set the actual length */
1380 CommandData
->CmdLen
= GetNextVdmCommand
->CmdLen
;
1383 if (CommandData
->AppLen
)
1385 /* Write back the application name */
1386 RtlMoveMemory(CommandData
->AppName
,
1387 GetNextVdmCommand
->AppName
,
1388 GetNextVdmCommand
->AppLen
);
1390 /* Set the actual length */
1391 CommandData
->AppLen
= GetNextVdmCommand
->AppLen
;
1394 if (CommandData
->PifLen
)
1396 /* Write back the PIF file name */
1397 RtlMoveMemory(CommandData
->PifFile
,
1398 GetNextVdmCommand
->PifFile
,
1399 GetNextVdmCommand
->PifLen
);
1401 /* Set the actual length */
1402 CommandData
->PifLen
= GetNextVdmCommand
->PifLen
;
1405 if (CommandData
->CurDirectoryLen
)
1407 /* Write back the current directory */
1408 RtlMoveMemory(CommandData
->CurDirectory
,
1409 GetNextVdmCommand
->CurDirectory
,
1410 GetNextVdmCommand
->CurDirectoryLen
);
1412 /* Set the actual length */
1413 CommandData
->CurDirectoryLen
= GetNextVdmCommand
->CurDirectoryLen
;
1416 if (CommandData
->EnvLen
)
1418 /* Write back the environment */
1419 RtlMoveMemory(CommandData
->Env
,
1420 GetNextVdmCommand
->Env
,
1421 GetNextVdmCommand
->EnvLen
);
1423 /* Set the actual length */
1424 CommandData
->EnvLen
= GetNextVdmCommand
->EnvLen
;
1427 if (CommandData
->DesktopLen
)
1429 /* Write back the desktop name */
1430 RtlMoveMemory(CommandData
->Desktop
,
1431 GetNextVdmCommand
->Desktop
,
1432 GetNextVdmCommand
->DesktopLen
);
1434 /* Set the actual length */
1435 CommandData
->DesktopLen
= GetNextVdmCommand
->DesktopLen
;
1438 if (CommandData
->TitleLen
)
1440 /* Write back the title */
1441 RtlMoveMemory(CommandData
->Title
,
1442 GetNextVdmCommand
->Title
,
1443 GetNextVdmCommand
->TitleLen
);
1445 /* Set the actual length */
1446 CommandData
->TitleLen
= GetNextVdmCommand
->TitleLen
;
1449 if (CommandData
->ReservedLen
)
1451 /* Write back the reserved parameter */
1452 RtlMoveMemory(CommandData
->Reserved
,
1453 GetNextVdmCommand
->Reserved
,
1454 GetNextVdmCommand
->ReservedLen
);
1456 /* Set the actual length */
1457 CommandData
->ReservedLen
= GetNextVdmCommand
->ReservedLen
;
1460 /* Write the remaining output parameters */
1461 CommandData
->TaskId
= GetNextVdmCommand
->iTask
;
1462 CommandData
->CreationFlags
= GetNextVdmCommand
->dwCreationFlags
;
1463 CommandData
->CodePage
= GetNextVdmCommand
->CodePage
;
1464 CommandData
->ExitCode
= GetNextVdmCommand
->ExitCode
;
1465 CommandData
->CurrentDrive
= GetNextVdmCommand
->CurrentDrive
;
1466 CommandData
->VDMState
= GetNextVdmCommand
->VDMState
;
1467 CommandData
->ComingFromBat
= GetNextVdmCommand
->fComingFromBat
;
1469 /* It was successful */
1472 else if ((CommandData
->VDMState
== VDM_INC_REENTER_COUNT
)
1473 || (CommandData
->VDMState
== VDM_DEC_REENTER_COUNT
))
1475 /* Setup the input parameters */
1476 SetReenterCount
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1477 SetReenterCount
->fIncDec
= CommandData
->VDMState
;
1480 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1482 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepSetReenterCount
),
1483 sizeof(BASE_SET_REENTER_COUNT
));
1484 BaseSetLastNTError(Status
);
1485 Result
= NT_SUCCESS(Status
);
1489 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
1496 Status
= CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1498 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepIsFirstVDM
),
1499 sizeof(BASE_IS_FIRST_VDM
));
1500 if (!NT_SUCCESS(Status
))
1502 BaseSetLastNTError(Status
);
1506 /* Return TRUE if this is the first VDM */
1507 Result
= IsFirstVdm
->FirstVDM
;
1511 if (CaptureBuffer
!= NULL
) CsrFreeCaptureBuffer(CaptureBuffer
);
1521 GetVDMCurrentDirectories(DWORD cchCurDirs
, PCHAR lpszzCurDirs
)
1523 BASE_API_MESSAGE ApiMessage
;
1524 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &ApiMessage
.Data
.VDMCurrentDirsRequest
;
1525 PCSR_CAPTURE_BUFFER CaptureBuffer
;
1527 /* Allocate the capture buffer */
1528 CaptureBuffer
= CsrAllocateCaptureBuffer(1, cchCurDirs
);
1529 if (CaptureBuffer
== NULL
)
1531 BaseSetLastNTError(STATUS_NO_MEMORY
);
1535 /* Setup the input parameters */
1536 VDMCurrentDirsRequest
->cchCurDirs
= cchCurDirs
;
1537 CsrAllocateMessagePointer(CaptureBuffer
,
1539 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
);
1542 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1544 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepGetVDMCurDirs
),
1545 sizeof(BASE_GETSET_VDM_CURDIRS
));
1547 /* Set the last error */
1548 BaseSetLastNTError(ApiMessage
.Status
);
1550 if (NT_SUCCESS(ApiMessage
.Status
))
1552 /* Copy the result */
1553 RtlMoveMemory(lpszzCurDirs
, VDMCurrentDirsRequest
->lpszzCurDirs
, cchCurDirs
);
1556 /* Free the capture buffer */
1557 CsrFreeCaptureBuffer(CaptureBuffer
);
1559 /* Return the size if it was successful, or if the buffer was too small */
1560 return (NT_SUCCESS(ApiMessage
.Status
) || (ApiMessage
.Status
== STATUS_BUFFER_TOO_SMALL
))
1561 ? VDMCurrentDirsRequest
->cchCurDirs
: 0;
1570 RegisterConsoleVDM (
1594 RegisterWowBaseHandlers (
1622 SetVDMCurrentDirectories(DWORD cchCurDirs
, PCHAR lpszzCurDirs
)
1624 BASE_API_MESSAGE ApiMessage
;
1625 PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
= &ApiMessage
.Data
.VDMCurrentDirsRequest
;
1626 PCSR_CAPTURE_BUFFER CaptureBuffer
;
1628 /* Allocate the capture buffer */
1629 CaptureBuffer
= CsrAllocateCaptureBuffer(1, cchCurDirs
);
1630 if (CaptureBuffer
== NULL
)
1632 BaseSetLastNTError(STATUS_NO_MEMORY
);
1636 /* Setup the input parameters */
1637 VDMCurrentDirsRequest
->cchCurDirs
= cchCurDirs
;
1638 CsrCaptureMessageBuffer(CaptureBuffer
,
1641 (PVOID
*)&VDMCurrentDirsRequest
->lpszzCurDirs
);
1644 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1646 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX
, BasepSetVDMCurDirs
),
1647 sizeof(BASE_GETSET_VDM_CURDIRS
));
1649 /* Free the capture buffer */
1650 CsrFreeCaptureBuffer(CaptureBuffer
);
1652 /* Set the last error */
1653 BaseSetLastNTError(ApiMessage
.Status
);
1655 return NT_SUCCESS(ApiMessage
.Status
) ? TRUE
: FALSE
;
1663 VDMConsoleOperation (
1678 VDMOperationStarted(IN ULONG Unknown0
)
1680 DPRINT1("VDMOperationStarted(%d)\n", Unknown0
);
1683 BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler
,