ReactOS 0.4.15-dev-7942-gd23573b
vdm.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

BOOL NTAPI BaseCreateVDMEnvironment (IN PWCHAR lpEnvironment, OUT PANSI_STRING AnsiEnv, OUT PUNICODE_STRING UnicodeEnv)
 
BOOL NTAPI BaseDestroyVDMEnvironment (IN PANSI_STRING AnsiEnv, IN PUNICODE_STRING UnicodeEnv)
 
BOOL WINAPI BaseGetVdmConfigInfo (IN LPCWSTR CommandLineReserved, IN ULONG DosSeqId, IN ULONG BinaryType, IN PUNICODE_STRING CmdLineString, OUT PULONG VdmSize)
 
BOOL WINAPI BaseUpdateVDMEntry (IN ULONG UpdateIndex, IN OUT PHANDLE WaitHandle, IN ULONG IndexInfo, IN ULONG BinaryType)
 
BOOL WINAPI BaseCheckForVDM (IN HANDLE ProcessHandle, OUT LPDWORD ExitCode)
 
NTSTATUS WINAPI BaseCheckVDM (IN ULONG BinaryType, IN PCWCH ApplicationName, IN PCWCH CommandLine, IN PCWCH CurrentDirectory, IN PANSI_STRING AnsiEnvironment, IN PBASE_API_MESSAGE ApiMessage, IN OUT PULONG iTask, IN DWORD CreationFlags, IN LPSTARTUPINFOW StartupInfo, IN HANDLE hUserToken OPTIONAL)
 

Function Documentation

◆ BaseCheckForVDM()

BOOL WINAPI BaseCheckForVDM ( IN HANDLE  ProcessHandle,
OUT LPDWORD  ExitCode 
)

Definition at line 618 of file vdm.c.

620{
622 EVENT_BASIC_INFORMATION EventBasicInfo;
623 BASE_API_MESSAGE ApiMessage;
624 PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest;
625
626 /* It's VDM if the process is actually a wait handle (an event) */
629 &EventBasicInfo,
630 sizeof(EventBasicInfo),
631 NULL);
632 if (!NT_SUCCESS(Status)) return FALSE;
633
634 /* Setup the input parameters */
635 GetVdmExitCode->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
636 GetVdmExitCode->hParent = ProcessHandle;
637
638 /* Call CSRSS */
640 NULL,
642 sizeof(*GetVdmExitCode));
643 if (!NT_SUCCESS(Status)) return FALSE;
644
645 /* Get the exit code from the reply */
646 *ExitCode = GetVdmExitCode->ExitCode;
647 return TRUE;
648}
#define NtCurrentPeb()
Definition: FLS.c:22
LONG NTSTATUS
Definition: precomp.h:26
@ BasepGetVDMExitCode
Definition: basemsg.h:31
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
@ EventBasicInformation
Definition: extypes.h:357
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
NTSTATUS NTAPI NtQueryEvent(IN HANDLE EventHandle, IN EVENT_INFORMATION_CLASS EventInformationClass, OUT PVOID EventInformation, IN ULONG EventInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: event.c:313
NTSTATUS NTAPI CsrClientCallServer(_Inout_ PCSR_API_MESSAGE ApiMessage, _Inout_opt_ PCSR_CAPTURE_BUFFER CaptureBuffer, _In_ CSR_API_NUMBER ApiNumber, _In_ ULONG DataLength)
Definition: connect.c:366
union _BASE_API_MESSAGE::@3538 Data
BASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
Definition: basemsg.h:292

Referenced by GetExitCodeProcess().

◆ BaseCheckVDM()

NTSTATUS WINAPI BaseCheckVDM ( IN ULONG  BinaryType,
IN PCWCH  ApplicationName,
IN PCWCH  CommandLine,
IN PCWCH  CurrentDirectory,
IN PANSI_STRING  AnsiEnvironment,
IN PBASE_API_MESSAGE  ApiMessage,
IN OUT PULONG  iTask,
IN DWORD  CreationFlags,
IN LPSTARTUPINFOW  StartupInfo,
IN HANDLE hUserToken  OPTIONAL 
)

Definition at line 91 of file vdm.c.

101{
103 PBASE_CHECK_VDM CheckVdm = &ApiMessage->Data.CheckVDMRequest;
104 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
105 PWCHAR CurrentDir = NULL;
106 PWCHAR ShortAppName = NULL;
107 PWCHAR ShortCurrentDir = NULL;
109 PCHAR AnsiCmdLine = NULL;
110 PCHAR AnsiAppName = NULL;
111 PCHAR AnsiCurDirectory = NULL;
112 PCHAR AnsiDesktop = NULL;
113 PCHAR AnsiTitle = NULL;
114 PCHAR AnsiReserved = NULL;
115 STARTUPINFOA AnsiStartupInfo;
116 ULONG NumStrings = 5;
117
118 /* Parameters validation */
119 if (ApplicationName == NULL || CommandLine == NULL)
120 {
122 }
123
124 /* Trim leading whitespace from ApplicationName */
125 while (*ApplicationName == L' ' || *ApplicationName == L'\t')
127
128 /* Calculate the size of the short application name */
130 if (Length == 0)
131 {
133 goto Cleanup;
134 }
135
136 /* Allocate memory for the short application name */
137 ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
139 Length * sizeof(WCHAR));
140 if (!ShortAppName)
141 {
143 goto Cleanup;
144 }
145
146 /* Get the short application name */
147 if (GetShortPathNameW(ApplicationName, ShortAppName, Length) == 0)
148 {
149 /* Try to determine which error occurred */
150 switch (GetLastError())
151 {
153 {
155 break;
156 }
157
159 {
161 break;
162 }
163
164 default:
165 {
167 }
168 }
169
170 goto Cleanup;
171 }
172
173 /* Trim leading whitespace from CommandLine */
174 while (*CommandLine == L' ' || *CommandLine == L'\t')
175 ++CommandLine;
176
177 /*
178 * CommandLine is usually formatted as: 'ApplicationName param0 ...'.
179 * So we want to strip the first token (ApplicationName) from it.
180 * Two cases are in fact possible:
181 * - either the first token is indeed ApplicationName, so we just skip it;
182 * - or the first token is not exactly ApplicationName, because it happened
183 * that somebody else already preprocessed CommandLine. Therefore we
184 * suppose that the first token corresponds to an application name and
185 * we skip it. Care should be taken when quotes are present in this token.
186 */
187 if (*CommandLine)
188 {
189 /* The first part of CommandLine should be the ApplicationName... */
191 if (Length <= wcslen(CommandLine) &&
192 _wcsnicmp(ApplicationName, CommandLine, Length) == 0)
193 {
194 /* Skip it */
195 CommandLine += Length;
196 }
197 /*
198 * ... but it is not, however we still have a token. We suppose that
199 * it corresponds to some sort of application name, so we skip it too.
200 */
201 else
202 {
203 /* Get rid of the first token. We stop when we see whitespace. */
204 while (*CommandLine && !(*CommandLine == L' ' || *CommandLine == L'\t'))
205 {
206 if (*CommandLine == L'\"')
207 {
208 /* We enter a quoted part, skip it */
209 ++CommandLine;
210 while (*CommandLine && *CommandLine++ != L'\"') ;
211 }
212 else
213 {
214 /* Go to the next character */
215 ++CommandLine;
216 }
217 }
218 }
219 }
220
221 /*
222 * Trim remaining whitespace from CommandLine that may be
223 * present between the application name and the parameters.
224 */
225 while (*CommandLine == L' ' || *CommandLine == L'\t')
226 ++CommandLine;
227
228 /* Get the current directory */
229 if (CurrentDirectory == NULL)
230 {
231 /* Allocate memory for the current directory path */
233 CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
235 Length * sizeof(WCHAR));
236 if (CurrentDir == NULL)
237 {
239 goto Cleanup;
240 }
241
242 /* Get the current directory */
243 GetCurrentDirectoryW(Length, CurrentDir);
244 CurrentDirectory = CurrentDir;
245 }
246
247 /* Calculate the size of the short current directory path */
249
250 /* Allocate memory for the short current directory path */
251 ShortCurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
253 Length * sizeof(WCHAR));
254 if (!ShortCurrentDir)
255 {
257 goto Cleanup;
258 }
259
260 /* Get the short current directory path */
261 if (!GetShortPathNameW(CurrentDirectory, ShortCurrentDir, Length))
262 {
263 /* Try to determine which error occurred */
264 switch (GetLastError())
265 {
267 {
269 break;
270 }
271
273 {
275 break;
276 }
277
278 default:
279 {
281 }
282 }
283 goto Cleanup;
284 }
285
286 /* Make sure that the command line isn't too long */
287 Length = wcslen(CommandLine);
289 {
291 goto Cleanup;
292 }
293
294 /* Setup the input parameters */
295 CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
296 CheckVdm->BinaryType = BinaryType;
297 CheckVdm->CodePage = CP_ACP;
298 CheckVdm->dwCreationFlags = CreationFlags;
299 CheckVdm->CurDrive = CurrentDirectory[0] - L'A';
300 CheckVdm->CmdLen = (USHORT)Length + 1;
301 CheckVdm->AppLen = (USHORT)wcslen(ShortAppName) + 1;
302 CheckVdm->PifLen = 0; // TODO: PIF file support!
303 CheckVdm->CurDirectoryLen = (USHORT)wcslen(ShortCurrentDir) + 1;
304 CheckVdm->EnvLen = AnsiEnvironment->Length;
305 CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0;
306 CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0;
307 CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0;
308
309 if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
310 {
311 /* Set the standard handles */
312 CheckVdm->StdIn = StartupInfo->hStdInput;
313 CheckVdm->StdOut = StartupInfo->hStdOutput;
314 CheckVdm->StdErr = StartupInfo->hStdError;
315 }
316
317 /* Allocate memory for the ANSI strings */
318 // We need to add the newline characters '\r\n' to the command line
319 AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen + 2);
320 AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
321 AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
322 if (StartupInfo->lpDesktop)
323 AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
325 CheckVdm->DesktopLen);
326 if (StartupInfo->lpTitle)
327 AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
329 CheckVdm->TitleLen);
330 if (StartupInfo->lpReserved)
331 AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
333 CheckVdm->ReservedLen);
334
335 if (!AnsiCmdLine
336 || !AnsiAppName
337 || !AnsiCurDirectory
338 || (StartupInfo->lpDesktop && !AnsiDesktop)
339 || (StartupInfo->lpTitle && !AnsiTitle)
340 || (StartupInfo->lpReserved && !AnsiReserved))
341 {
343 goto Cleanup;
344 }
345
346 /* Convert the command line into an ANSI string */
348 0,
349 CommandLine,
350 CheckVdm->CmdLen,
351 AnsiCmdLine,
352 CheckVdm->CmdLen,
353 NULL,
354 NULL);
355 /* Add the needed newline and NULL-terminate */
356 CheckVdm->CmdLen--; // Rewind back to the NULL character
357 AnsiCmdLine[CheckVdm->CmdLen++] = '\r';
358 AnsiCmdLine[CheckVdm->CmdLen++] = '\n';
359 AnsiCmdLine[CheckVdm->CmdLen++] = 0;
360
361 /* Convert the short application name into an ANSI string */
363 0,
364 ShortAppName,
365 CheckVdm->AppLen,
366 AnsiAppName,
367 CheckVdm->AppLen,
368 NULL,
369 NULL);
370
371 /* Convert the short current directory path into an ANSI string */
373 0,
374 ShortCurrentDir,
375 CheckVdm->CurDirectoryLen,
376 AnsiCurDirectory,
377 CheckVdm->CurDirectoryLen,
378 NULL,
379 NULL);
380
381 if (StartupInfo->lpDesktop)
382 {
383 /* Convert the desktop name into an ANSI string */
385 0,
386 StartupInfo->lpDesktop,
387 CheckVdm->DesktopLen,
388 AnsiDesktop,
389 CheckVdm->DesktopLen,
390 NULL,
391 NULL);
392 NumStrings++;
393 }
394
395 if (StartupInfo->lpTitle)
396 {
397 /* Convert the title into an ANSI string */
399 0,
400 StartupInfo->lpTitle,
401 CheckVdm->TitleLen,
402 AnsiTitle,
403 CheckVdm->TitleLen,
404 NULL,
405 NULL);
406 NumStrings++;
407 }
408
409 if (StartupInfo->lpReserved)
410 {
411 /* Convert the reserved value into an ANSI string */
413 0,
414 StartupInfo->lpReserved,
415 CheckVdm->ReservedLen,
416 AnsiReserved,
417 CheckVdm->ReservedLen,
418 NULL,
419 NULL);
420 NumStrings++;
421 }
422
423 /* Fill the ANSI startup info structure */
424 RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(AnsiStartupInfo));
425 AnsiStartupInfo.lpReserved = AnsiReserved;
426 AnsiStartupInfo.lpDesktop = AnsiDesktop;
427 AnsiStartupInfo.lpTitle = AnsiTitle;
428
429 /* Allocate the capture buffer */
430 CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings,
431 CheckVdm->CmdLen
432 + CheckVdm->AppLen
433 + CheckVdm->PifLen
434 + CheckVdm->CurDirectoryLen
435 + CheckVdm->DesktopLen
436 + CheckVdm->TitleLen
437 + CheckVdm->ReservedLen
438 + CheckVdm->EnvLen
439 + sizeof(*CheckVdm->StartupInfo));
440 if (CaptureBuffer == NULL)
441 {
443 goto Cleanup;
444 }
445
446 /* Capture the command line */
447 CsrCaptureMessageBuffer(CaptureBuffer,
448 AnsiCmdLine,
449 CheckVdm->CmdLen,
450 (PVOID*)&CheckVdm->CmdLine);
451
452 /* Capture the application name */
453 CsrCaptureMessageBuffer(CaptureBuffer,
454 AnsiAppName,
455 CheckVdm->AppLen,
456 (PVOID*)&CheckVdm->AppName);
457
458 CheckVdm->PifFile = NULL; // TODO: PIF file support!
459
460 /* Capture the current directory */
461 CsrCaptureMessageBuffer(CaptureBuffer,
462 AnsiCurDirectory,
463 CheckVdm->CurDirectoryLen,
464 (PVOID*)&CheckVdm->CurDirectory);
465
466 /* Capture the environment */
467 CsrCaptureMessageBuffer(CaptureBuffer,
468 AnsiEnvironment->Buffer,
469 CheckVdm->EnvLen,
470 (PVOID*)&CheckVdm->Env);
471
472 /* Capture the startup info structure */
473 CsrCaptureMessageBuffer(CaptureBuffer,
474 &AnsiStartupInfo,
475 sizeof(*CheckVdm->StartupInfo),
476 (PVOID*)&CheckVdm->StartupInfo);
477
478 if (StartupInfo->lpDesktop)
479 {
480 /* Capture the desktop name */
481 CsrCaptureMessageBuffer(CaptureBuffer,
482 AnsiDesktop,
483 CheckVdm->DesktopLen,
484 (PVOID*)&CheckVdm->Desktop);
485 }
486 else CheckVdm->Desktop = NULL;
487
488 if (StartupInfo->lpTitle)
489 {
490 /* Capture the title */
491 CsrCaptureMessageBuffer(CaptureBuffer,
492 AnsiTitle,
493 CheckVdm->TitleLen,
494 (PVOID*)&CheckVdm->Title);
495 }
496 else CheckVdm->Title = NULL;
497
498 if (StartupInfo->lpReserved)
499 {
500 /* Capture the reserved parameter */
501 CsrCaptureMessageBuffer(CaptureBuffer,
502 AnsiReserved,
503 CheckVdm->ReservedLen,
504 (PVOID*)&CheckVdm->Reserved);
505 }
506 else CheckVdm->Reserved = NULL;
507
508 /* Send the message to CSRSS */
510 CaptureBuffer,
512 sizeof(*CheckVdm));
513
514 /* Write back the task ID */
515 *iTask = CheckVdm->iTask;
516
517Cleanup:
518
519 /* Free the ANSI strings */
520 if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine);
521 if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName);
522 if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory);
523 if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop);
524 if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle);
525 if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved);
526
527 /* Free the capture buffer */
528 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
529
530 /* Free the current directory, if it was allocated here, and its short path */
531 if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
532 if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
533
534 /* Free the short app name */
535 if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
536
537 return Status;
538}
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
@ BasepCheckVDM
Definition: basemsg.h:26
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define CP_ACP
Definition: compat.h:109
#define WideCharToMultiByte
Definition: compat.h:111
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1833
static const WCHAR Cleanup[]
Definition: register.c:80
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define PCHAR
Definition: match.c:90
PVOID PVOID PWCHAR ApplicationName
Definition: env.c:47
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT NumStrings
Definition: ndis.h:4753
#define UNICODE_STRING_MAX_CHARS
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_OBJECT_PATH_INVALID
Definition: ntstatus.h:293
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
PCSR_CAPTURE_BUFFER NTAPI CsrAllocateCaptureBuffer(_In_ ULONG ArgumentCount, _In_ ULONG BufferSize)
Definition: capture.c:87
VOID NTAPI CsrFreeCaptureBuffer(_In_ _Frees_ptr_ PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:210
VOID NTAPI CsrCaptureMessageBuffer(_Inout_ PCSR_CAPTURE_BUFFER CaptureBuffer, _In_opt_ PVOID MessageBuffer, _In_ ULONG MessageLength, _Out_ PVOID *CapturedData)
Definition: capture.c:189
ULONG EnvLen
Definition: basemsg.h:134
USHORT CurDrive
Definition: basemsg.h:146
ULONG CodePage
Definition: basemsg.h:127
ULONG TitleLen
Definition: basemsg.h:139
PCHAR Desktop
Definition: basemsg.h:136
USHORT CurDirectoryLen
Definition: basemsg.h:145
HANDLE StdOut
Definition: basemsg.h:125
PCHAR PifFile
Definition: basemsg.h:131
HANDLE StdErr
Definition: basemsg.h:126
ULONG ReservedLen
Definition: basemsg.h:141
HANDLE ConsoleHandle
Definition: basemsg.h:121
PCHAR Reserved
Definition: basemsg.h:140
HANDLE StdIn
Definition: basemsg.h:124
PCHAR CmdLine
Definition: basemsg.h:129
ULONG dwCreationFlags
Definition: basemsg.h:128
ULONG DesktopLen
Definition: basemsg.h:137
PCHAR AppName
Definition: basemsg.h:130
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:135
USHORT PifLen
Definition: basemsg.h:144
ULONG BinaryType
Definition: basemsg.h:122
PCHAR CurDirectory
Definition: basemsg.h:132
USHORT CmdLen
Definition: basemsg.h:142
USHORT AppLen
Definition: basemsg.h:143
LPSTR lpTitle
Definition: winbase.h:834
LPSTR lpReserved
Definition: winbase.h:832
LPSTR lpDesktop
Definition: winbase.h:833
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESTDHANDLES
Definition: winbase.h:499
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CreateProcessInternalW().

◆ BaseCreateVDMEnvironment()

BOOL NTAPI BaseCreateVDMEnvironment ( IN PWCHAR  lpEnvironment,
OUT PANSI_STRING  AnsiEnv,
OUT PUNICODE_STRING  UnicodeEnv 
)

Definition at line 744 of file vdm.c.

747{
748#define IS_ALPHA(x) \
749 ( ((x) >= L'A' && (x) <= L'Z') || ((x) >= L'a' && (x) <= L'z') )
750
751// From lib/rtl/path.c :
752// Can be put in some .h ??
753#define IS_PATH_SEPARATOR(x) ((x) == L'\\' || (x) == L'/')
754
757 ULONG EnvironmentSize = 0;
759 PWCHAR Environment, NewEnvironment = NULL;
761 ULONG NameLength, NumChars, Remaining;
762 PWCHAR SourcePtr, DestPtr, StartPtr;
763
764 /* Make sure we have both strings */
765 if (!AnsiEnv || !UnicodeEnv)
766 {
767 /* Fail */
769 return FALSE;
770 }
771
772 /* Check if an environment was passed in */
773 if (!lpEnvironment)
774 {
775 /* Nope, create one */
777 if (!NT_SUCCESS(Status)) goto Cleanup;
778 }
779 else
780 {
781 /* Use the one we got */
782 Environment = lpEnvironment;
783 }
784
785 /* Do we have something now ? */
786 if (!Environment)
787 {
788 /* Still not, bail out */
790 goto Cleanup;
791 }
792
793 /*
794 * Count how much space the whole environment takes. The environment block is
795 * doubly NULL-terminated (NULL from last string and final NULL terminator).
796 */
797 SourcePtr = Environment;
798 while (!(*SourcePtr++ == UNICODE_NULL && *SourcePtr == UNICODE_NULL))
799 ++EnvironmentSize;
800 EnvironmentSize += 2; // Add the two terminating NULLs
801
802 /*
803 * Allocate a new copy large enough to hold all the environment with paths
804 * in their short form. Since the short form of a path can be a bit longer
805 * than its long form, for example in the case where characters that are
806 * invalid in the 8.3 representation are present in the long path name:
807 * 'C:\\a+b' --> 'C:\\A_B~1', or:
808 * 'C:\\a b' --> 'C:\\AB2761~1' (with checksum inserted),
809 * we suppose that the possible total number of extra characters needed to
810 * convert the long paths into their short form is at most equal to MAX_PATH.
811 */
812 RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR);
814 (PVOID*)&NewEnvironment,
815 0,
816 &RegionSize,
819 if (!NT_SUCCESS(Status))
820 {
821 /* We failed, bail out */
823 NewEnvironment = NULL;
824 goto Cleanup;
825 }
826
827 /* Parse the environment block */
828 Remaining = MAX_PATH - 2; // '-2': remove the last two NULLs. FIXME: is it really needed??
829 SourcePtr = Environment;
830 DestPtr = NewEnvironment;
831
832 /* Loop through all the environment strings */
833 while (*SourcePtr != UNICODE_NULL)
834 {
835 /*
836 * 1. Check the type of the environment variable and copy its name.
837 */
838
839 /* Regular environment variable */
840 if (*SourcePtr != L'=')
841 {
842 StartPtr = SourcePtr;
843
844 /* Copy the environment variable name, including the '=' */
845 while (*SourcePtr != UNICODE_NULL)
846 {
847 *DestPtr++ = *SourcePtr;
848 if (*SourcePtr++ == L'=') break;
849 }
850
851 /* Guess the type of the environment variable */
852 NameType = BaseGetEnvNameType_U(StartPtr, SourcePtr - StartPtr - 1);
853 }
854 /* 'Current directory' environment variable (i.e. of '=X:=' form) */
855 else // if (*SourcePtr == L'=')
856 {
857 /* First assume we have a possibly malformed environment variable */
859
860 /* Check for a valid 'Current directory' environment variable */
861 if (IS_ALPHA(SourcePtr[1]) && SourcePtr[2] == L':' && SourcePtr[3] == L'=')
862 {
863 /*
864 * Small optimization: convert the path to short form only if
865 * the current directory is not the root directory (i.e. not
866 * of the '=X:=Y:\' form), otherwise just do a simple copy.
867 */
868 if ( wcslen(SourcePtr) >= ARRAYSIZE("=X:=Y:\\")-1 &&
869 !( IS_ALPHA(SourcePtr[4]) && SourcePtr[5] == L':' &&
870 IS_PATH_SEPARATOR(SourcePtr[6]) && SourcePtr[7] == UNICODE_NULL ) )
871 {
873
874 /* Copy the '=X:=' prefix */
875 *DestPtr++ = SourcePtr[0];
876 *DestPtr++ = SourcePtr[1];
877 *DestPtr++ = SourcePtr[2];
878 *DestPtr++ = SourcePtr[3];
879 SourcePtr += 4;
880 }
881 }
882 else
883 {
884 /*
885 * Invalid stuff starting with '=', i.e.:
886 * =? (with '?' not being a letter)
887 * =X??? (with '?' not being ":=" and not followed by something longer than 3 characters)
888 * =X:=??? (with '?' not being "X:\\")
889 *
890 * 'NameType' is already set to 'EnvNameNotAPath'.
891 */
892 }
893 }
894
895
896 /*
897 * 2. Copy the environment value and perform conversions accordingly.
898 */
899
901 {
902 /* Copy everything, including the NULL terminator */
903 do
904 {
905 *DestPtr++ = *SourcePtr;
906 } while (*SourcePtr++ != UNICODE_NULL);
907 }
908 else if (NameType == EnvNameSinglePath)
909 {
910 /* Convert the path to its short form */
911 NameLength = wcslen(SourcePtr);
912 NumChars = GetShortPathNameW(SourcePtr, DestPtr, NameLength + 1 + Remaining);
913 if (NumChars == 0 || NumChars > NameLength + Remaining)
914 {
915 /* If the conversion failed, just copy the original value */
916 RtlCopyMemory(DestPtr, SourcePtr, NameLength * sizeof(WCHAR));
917 NumChars = NameLength;
918 }
919 DestPtr += NumChars;
920 if (NumChars > NameLength)
921 Remaining -= (NumChars - NameLength);
922
923 SourcePtr += NameLength;
924
925 /* Copy the NULL terminator */
926 *DestPtr++ = *SourcePtr++;
927 }
928 else // if (NameType == EnvNameMultiplePath)
929 {
930 WCHAR Delimiter;
931
932 /* Loop through the list of paths (delimited by ';') and convert each path to its short form */
933 do
934 {
935 /* Copy any trailing ';' before going to the next path */
936 while (*SourcePtr == L';')
937 {
938 *DestPtr++ = *SourcePtr++;
939 }
940
941 StartPtr = SourcePtr;
942
943 /* Find the next path list delimiter or the NULL terminator */
944 while (*SourcePtr != UNICODE_NULL && *SourcePtr != L';')
945 {
946 ++SourcePtr;
947 }
948 Delimiter = *SourcePtr;
949
950 NameLength = SourcePtr - StartPtr;
951 if (NameLength)
952 {
953 /*
954 * Temporarily replace the possible path list delimiter by NULL.
955 * 'lpEnvironment' must point to a read+write memory buffer!
956 */
957 *SourcePtr = UNICODE_NULL;
958
959 NumChars = GetShortPathNameW(StartPtr, DestPtr, NameLength + 1 + Remaining);
960 if ( NumChars == 0 ||
961 (Delimiter == L';' ? NumChars > NameLength + Remaining
962 : NumChars > NameLength /* + Remaining ?? */) )
963 {
964 /* If the conversion failed, just copy the original value */
965 RtlCopyMemory(DestPtr, StartPtr, NameLength * sizeof(WCHAR));
966 NumChars = NameLength;
967 }
968 DestPtr += NumChars;
969 if (NumChars > NameLength)
970 Remaining -= (NumChars - NameLength);
971
972 /* If removed, restore the path list delimiter in the source environment value and copy it */
973 if (Delimiter != UNICODE_NULL)
974 {
975 *SourcePtr = Delimiter;
976 *DestPtr++ = *SourcePtr++;
977 }
978 }
979 } while (*SourcePtr != UNICODE_NULL);
980
981 /* Copy the NULL terminator */
982 *DestPtr++ = *SourcePtr++;
983 }
984 }
985
986 /* NULL-terminate the environment block */
987 *DestPtr++ = UNICODE_NULL;
988
989 /* Initialize the Unicode string to hold it */
990 RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment,
991 (DestPtr - NewEnvironment) * sizeof(WCHAR));
992 UnicodeEnv->Length = UnicodeEnv->MaximumLength;
993
994 /* Create its ANSI version */
995 Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE);
996 if (!NT_SUCCESS(Status))
997 {
998 /* Set last error if conversion failure */
1000 }
1001 else
1002 {
1003 /* Everything went okay, so return success */
1004 Success = TRUE;
1005 NewEnvironment = NULL;
1006 }
1007
1008Cleanup:
1009 /* Cleanup path starts here, start by destroying the environment copy */
1010 if (!lpEnvironment && Environment) RtlDestroyEnvironment(Environment);
1011
1012 /* See if we are here due to failure */
1013 if (NewEnvironment)
1014 {
1015 /* Initialize the paths to be empty */
1016 RtlInitEmptyUnicodeString(UnicodeEnv, NULL, 0);
1017 RtlInitEmptyAnsiString(AnsiEnv, NULL, 0);
1018
1019 /* Free the environment copy */
1020 RegionSize = 0;
1022 (PVOID*)&NewEnvironment,
1023 &RegionSize,
1024 MEM_RELEASE);
1026 }
1027
1028 /* Return the result */
1029 return Success;
1030}
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 NameType
Definition: acpixf.h:658
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define SetLastError(x)
Definition: compat.h:752
#define MAX_PATH
Definition: compat.h:34
enum _ENV_NAME_TYPE ENV_NAME_TYPE
ENV_NAME_TYPE WINAPI BaseGetEnvNameType_U(IN PWCHAR Name, IN ULONG NameLength)
Definition: vdm.c:713
@ EnvNameSinglePath
Definition: vdm.c:33
@ EnvNameNotAPath
Definition: vdm.c:32
#define IS_PATH_SEPARATOR(x)
#define IS_ALPHA(x)
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ASSERT(a)
Definition: mode.c:44
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
NTSYSAPI NTSTATUS NTAPI RtlCreateEnvironment(_In_ BOOLEAN Inherit, _Out_ PWSTR *Environment)
NTSYSAPI VOID NTAPI RtlDestroyEnvironment(_In_ PWSTR Environment)
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define MEM_RELEASE
Definition: nt_native.h:1316
#define MEM_COMMIT
Definition: nt_native.h:1313
#define UNICODE_NULL
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5230
NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
Definition: virtual.c:4492
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
#define ERROR_BAD_ENVIRONMENT
Definition: winerror.h:113

Referenced by CreateProcessInternalW().

◆ BaseDestroyVDMEnvironment()

BOOL NTAPI BaseDestroyVDMEnvironment ( IN PANSI_STRING  AnsiEnv,
IN PUNICODE_STRING  UnicodeEnv 
)

Definition at line 1034 of file vdm.c.

1036{
1037 SIZE_T Dummy = 0;
1038
1039 /* Clear the ANSI buffer since Rtl creates this for us */
1040 if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv);
1041
1042 /* The Unicode buffer is build by hand, though */
1043 if (UnicodeEnv->Buffer)
1044 {
1045 /* So clear it through the API */
1047 (PVOID*)&UnicodeEnv->Buffer,
1048 &Dummy,
1049 MEM_RELEASE);
1050 }
1051
1052 /* All done */
1053 return TRUE;
1054}
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)

Referenced by CreateProcessInternalW().

◆ BaseGetVdmConfigInfo()

BOOL WINAPI BaseGetVdmConfigInfo ( IN LPCWSTR  CommandLineReserved,
IN ULONG  DosSeqId,
IN ULONG  BinaryType,
IN PUNICODE_STRING  CmdLineString,
OUT PULONG  VdmSize 
)

Definition at line 652 of file vdm.c.

657{
659 WCHAR CommandLine[MAX_PATH * 2];
661
662 /* Clear the buffer in case we fail */
663 CmdLineString->Buffer = 0;
664
665 /* Always return the same size: 16 Mb */
666 *VdmSize = 0x1000000;
667
668 /* Get the system directory */
670 if (!(Length) || (Length >= MAX_PATH))
671 {
672 /* Eliminate no path or path too big */
674 return FALSE;
675 }
676
677 /* Check if this is VDM with a DOS Sequence ID */
678 if (DosSeqId)
679 {
680 /*
681 * Build the VDM string for it:
682 * -i%lx : Gives the DOS Sequence ID;
683 * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
684 */
685 _snwprintf(CommandLine,
686 ARRAYSIZE(CommandLine),
687 L"\"%s\\ntvdm.exe\" -i%lx %s%c",
688 Buffer,
689 DosSeqId,
690 (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
691 (BinaryType == BINARY_TYPE_SEPARATE_WOW) ? L's' : L' ');
692 }
693 else
694 {
695 /*
696 * Build the string for it without the DOS Sequence ID:
697 * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
698 */
699 _snwprintf(CommandLine,
700 ARRAYSIZE(CommandLine),
701 L"\"%s\\ntvdm.exe\" %s%c",
702 Buffer,
703 (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
704 (BinaryType == BINARY_TYPE_SEPARATE_WOW) ? L's' : L' ');
705 }
706
707 /* Create the actual string */
708 return RtlCreateUnicodeString(CmdLineString, CommandLine);
709}
Definition: bufpool.h:45
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define ERROR_INVALID_NAME
Definition: compat.h:103
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
#define BINARY_TYPE_SEPARATE_WOW
Definition: vdm.h:39
#define BINARY_TYPE_DOS
Definition: vdm.h:38

Referenced by CreateProcessInternalW().

◆ BaseUpdateVDMEntry()

BOOL WINAPI BaseUpdateVDMEntry ( IN ULONG  UpdateIndex,
IN OUT PHANDLE  WaitHandle,
IN ULONG  IndexInfo,
IN ULONG  BinaryType 
)

Definition at line 542 of file vdm.c.

546{
547 BASE_API_MESSAGE ApiMessage;
548 PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest;
549
550 /* Check what update is being sent */
551 switch (UpdateIndex)
552 {
553 /* VDM is being undone */
554 case VdmEntryUndo:
555 {
556 /* Tell the server how far we had gotten along */
557 UpdateVdmEntry->iTask = HandleToUlong(*WaitHandle);
558 UpdateVdmEntry->VDMCreationState = IndexInfo;
559 break;
560 }
561
562 /* VDM is ready with a new process handle */
564 {
565 /* Send it the process handle */
566 UpdateVdmEntry->VDMProcessHandle = *WaitHandle;
567 UpdateVdmEntry->iTask = IndexInfo;
568 break;
569 }
570 }
571
572 /* Also check what kind of binary this is for the console handle */
573 if (BinaryType == BINARY_TYPE_WOW)
574 {
575 /* Magic value for 16-bit apps */
576 UpdateVdmEntry->ConsoleHandle = (HANDLE)-1;
577 }
578 else if (UpdateVdmEntry->iTask)
579 {
580 /* No handle for true VDM */
581 UpdateVdmEntry->ConsoleHandle = NULL;
582 }
583 else
584 {
585 /* Otherwise, use the regular console handle */
586 UpdateVdmEntry->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
587 }
588
589 /* Finally write the index and binary type */
590 UpdateVdmEntry->EntryIndex = UpdateIndex;
591 UpdateVdmEntry->BinaryType = BinaryType;
592
593 /* Send the message to CSRSS */
595 NULL,
597 sizeof(*UpdateVdmEntry));
598 if (!NT_SUCCESS(ApiMessage.Status))
599 {
600 /* Handle failure */
601 BaseSetLastNTError(ApiMessage.Status);
602 return FALSE;
603 }
604
605 /* If this was an update, CSRSS returns a new wait handle */
606 if (UpdateIndex == VdmEntryUpdateProcess)
607 {
608 /* Return it to the caller */
609 *WaitHandle = UpdateVdmEntry->WaitObjectForParent;
610 }
611
612 /* We made it */
613 return TRUE;
614}
@ BasepUpdateVDMEntry
Definition: basemsg.h:27
#define HandleToUlong(h)
Definition: basetsd.h:79
#define BINARY_TYPE_WOW
Definition: vdm.h:40
@ VdmEntryUndo
Definition: vdm.h:19
@ VdmEntryUpdateProcess
Definition: vdm.h:20
BASE_UPDATE_VDM_ENTRY UpdateVDMEntryRequest
Definition: basemsg.h:288
Definition: basemsg.h:151
ULONG BinaryType
Definition: basemsg.h:153
HANDLE WaitObjectForParent
Definition: basemsg.h:156
HANDLE VDMProcessHandle
Definition: basemsg.h:155
USHORT VDMCreationState
Definition: basemsg.h:158
USHORT EntryIndex
Definition: basemsg.h:157
ULONG iTask
Definition: basemsg.h:152
HANDLE ConsoleHandle
Definition: basemsg.h:154
NTSTATUS Status
Definition: csrmsg.h:110
PVOID HANDLE
Definition: typedefs.h:73

Referenced by CreateProcessInternalW(), and VDMOperationStarted().