ReactOS  0.4.11-dev-433-g473ca91
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

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

Definition at line 610 of file vdm.c.

Referenced by GetExitCodeProcess().

612 {
614  EVENT_BASIC_INFORMATION EventBasicInfo;
615  BASE_API_MESSAGE ApiMessage;
616  PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest;
617 
618  /* It's VDM if the process is actually a wait handle (an event) */
619  Status = NtQueryEvent(ProcessHandle,
621  &EventBasicInfo,
622  sizeof(EventBasicInfo),
623  NULL);
624  if (!NT_SUCCESS(Status)) return FALSE;
625 
626  /* Setup the input parameters */
627  GetVdmExitCode->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
628  GetVdmExitCode->hParent = ProcessHandle;
629 
630  /* Call CSRSS */
631  Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
632  NULL,
634  sizeof(*GetVdmExitCode));
635  if (!NT_SUCCESS(Status)) return FALSE;
636 
637  /* Get the exit code from the reply */
638  *ExitCode = GetVdmExitCode->ExitCode;
639  return TRUE;
640 }
BASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
Definition: basemsg.h:292
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage, IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, IN CSR_API_NUMBER ApiNumber, IN ULONG DataLength)
Definition: connect.c:360
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI NtQueryEvent(IN HANDLE EventHandle, IN EVENT_INFORMATION_CLASS EventInformationClass, OUT PVOID EventInformation, IN ULONG EventInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: event.c:317
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
LONG NTSTATUS
Definition: precomp.h:26
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
Status
Definition: gdiplustypes.h:24
#define NtCurrentPeb()
Definition: FLS.c:19
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
union _BASE_API_MESSAGE::@3380 Data
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.

Referenced by CreateProcessInternalW().

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;
108  ULONG Length;
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')
126  ++ApplicationName;
127 
128  /* Calculate the size of the short application name */
129  Length = GetShortPathNameW(ApplicationName, NULL, 0);
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  {
142  Status = STATUS_NO_MEMORY;
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  {
154  Status = STATUS_NO_MEMORY;
155  break;
156  }
157 
159  {
160  Status = STATUS_INVALID_PARAMETER;
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... */
190  Length = wcslen(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 */
232  Length = GetCurrentDirectoryW(0, NULL);
233  CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
235  Length * sizeof(WCHAR));
236  if (CurrentDir == NULL)
237  {
238  Status = STATUS_NO_MEMORY;
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  {
256  Status = STATUS_NO_MEMORY;
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  {
268  Status = STATUS_NO_MEMORY;
269  break;
270  }
271 
273  {
274  Status = STATUS_INVALID_PARAMETER;
275  break;
276  }
277 
278  default:
279  {
281  }
282  }
283  goto Cleanup;
284  }
285 
286  /* Setup the input parameters */
287  CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
288  CheckVdm->BinaryType = BinaryType;
289  CheckVdm->CodePage = CP_ACP;
290  CheckVdm->dwCreationFlags = CreationFlags;
291  CheckVdm->CurDrive = CurrentDirectory[0] - L'A';
292  CheckVdm->CmdLen = wcslen(CommandLine) + 1;
293  CheckVdm->AppLen = wcslen(ShortAppName) + 1;
294  CheckVdm->PifLen = 0; // TODO: PIF file support!
295  CheckVdm->CurDirectoryLen = wcslen(ShortCurrentDir) + 1;
296  CheckVdm->EnvLen = AnsiEnvironment->Length;
297  CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0;
298  CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0;
299  CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0;
300 
301  if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
302  {
303  /* Set the standard handles */
304  CheckVdm->StdIn = StartupInfo->hStdInput;
305  CheckVdm->StdOut = StartupInfo->hStdOutput;
306  CheckVdm->StdErr = StartupInfo->hStdError;
307  }
308 
309  /* Allocate memory for the ANSI strings */
310  // We need to add the newline characters '\r\n' to the command line
311  AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen + 2);
312  AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
313  AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
314  if (StartupInfo->lpDesktop)
315  AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
317  CheckVdm->DesktopLen);
318  if (StartupInfo->lpTitle)
319  AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
321  CheckVdm->TitleLen);
322  if (StartupInfo->lpReserved)
323  AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
325  CheckVdm->ReservedLen);
326 
327  if (!AnsiCmdLine
328  || !AnsiAppName
329  || !AnsiCurDirectory
330  || (StartupInfo->lpDesktop && !AnsiDesktop)
331  || (StartupInfo->lpTitle && !AnsiTitle)
332  || (StartupInfo->lpReserved && !AnsiReserved))
333  {
334  Status = STATUS_NO_MEMORY;
335  goto Cleanup;
336  }
337 
338  /* Convert the command line into an ANSI string */
340  0,
341  CommandLine,
342  CheckVdm->CmdLen,
343  AnsiCmdLine,
344  CheckVdm->CmdLen,
345  NULL,
346  NULL);
347  /* Add the needed newline and NULL-terminate */
348  CheckVdm->CmdLen--; // Rewind back to the NULL character
349  AnsiCmdLine[CheckVdm->CmdLen++] = '\r';
350  AnsiCmdLine[CheckVdm->CmdLen++] = '\n';
351  AnsiCmdLine[CheckVdm->CmdLen++] = 0;
352 
353  /* Convert the short application name into an ANSI string */
355  0,
356  ShortAppName,
357  CheckVdm->AppLen,
358  AnsiAppName,
359  CheckVdm->AppLen,
360  NULL,
361  NULL);
362 
363  /* Convert the short current directory path into an ANSI string */
365  0,
366  ShortCurrentDir,
367  CheckVdm->CurDirectoryLen,
368  AnsiCurDirectory,
369  CheckVdm->CurDirectoryLen,
370  NULL,
371  NULL);
372 
373  if (StartupInfo->lpDesktop)
374  {
375  /* Convert the desktop name into an ANSI string */
377  0,
378  StartupInfo->lpDesktop,
379  CheckVdm->DesktopLen,
380  AnsiDesktop,
381  CheckVdm->DesktopLen,
382  NULL,
383  NULL);
384  NumStrings++;
385  }
386 
387  if (StartupInfo->lpTitle)
388  {
389  /* Convert the title into an ANSI string */
391  0,
392  StartupInfo->lpTitle,
393  CheckVdm->TitleLen,
394  AnsiTitle,
395  CheckVdm->TitleLen,
396  NULL,
397  NULL);
398  NumStrings++;
399  }
400 
401  if (StartupInfo->lpReserved)
402  {
403  /* Convert the reserved value into an ANSI string */
405  0,
406  StartupInfo->lpReserved,
407  CheckVdm->ReservedLen,
408  AnsiReserved,
409  CheckVdm->ReservedLen,
410  NULL,
411  NULL);
412  NumStrings++;
413  }
414 
415  /* Fill the ANSI startup info structure */
416  RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(AnsiStartupInfo));
417  AnsiStartupInfo.lpReserved = AnsiReserved;
418  AnsiStartupInfo.lpDesktop = AnsiDesktop;
419  AnsiStartupInfo.lpTitle = AnsiTitle;
420 
421  /* Allocate the capture buffer */
422  CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings,
423  CheckVdm->CmdLen
424  + CheckVdm->AppLen
425  + CheckVdm->PifLen
426  + CheckVdm->CurDirectoryLen
427  + CheckVdm->DesktopLen
428  + CheckVdm->TitleLen
429  + CheckVdm->ReservedLen
430  + CheckVdm->EnvLen
431  + sizeof(*CheckVdm->StartupInfo));
432  if (CaptureBuffer == NULL)
433  {
434  Status = STATUS_NO_MEMORY;
435  goto Cleanup;
436  }
437 
438  /* Capture the command line */
439  CsrCaptureMessageBuffer(CaptureBuffer,
440  AnsiCmdLine,
441  CheckVdm->CmdLen,
442  (PVOID*)&CheckVdm->CmdLine);
443 
444  /* Capture the application name */
445  CsrCaptureMessageBuffer(CaptureBuffer,
446  AnsiAppName,
447  CheckVdm->AppLen,
448  (PVOID*)&CheckVdm->AppName);
449 
450  CheckVdm->PifFile = NULL; // TODO: PIF file support!
451 
452  /* Capture the current directory */
453  CsrCaptureMessageBuffer(CaptureBuffer,
454  AnsiCurDirectory,
455  CheckVdm->CurDirectoryLen,
456  (PVOID*)&CheckVdm->CurDirectory);
457 
458  /* Capture the environment */
459  CsrCaptureMessageBuffer(CaptureBuffer,
460  AnsiEnvironment->Buffer,
461  CheckVdm->EnvLen,
462  (PVOID*)&CheckVdm->Env);
463 
464  /* Capture the startup info structure */
465  CsrCaptureMessageBuffer(CaptureBuffer,
466  &AnsiStartupInfo,
467  sizeof(*CheckVdm->StartupInfo),
468  (PVOID*)&CheckVdm->StartupInfo);
469 
470  if (StartupInfo->lpDesktop)
471  {
472  /* Capture the desktop name */
473  CsrCaptureMessageBuffer(CaptureBuffer,
474  AnsiDesktop,
475  CheckVdm->DesktopLen,
476  (PVOID*)&CheckVdm->Desktop);
477  }
478  else CheckVdm->Desktop = NULL;
479 
480  if (StartupInfo->lpTitle)
481  {
482  /* Capture the title */
483  CsrCaptureMessageBuffer(CaptureBuffer,
484  AnsiTitle,
485  CheckVdm->TitleLen,
486  (PVOID*)&CheckVdm->Title);
487  }
488  else CheckVdm->Title = NULL;
489 
490  if (StartupInfo->lpReserved)
491  {
492  /* Capture the reserved parameter */
493  CsrCaptureMessageBuffer(CaptureBuffer,
494  AnsiReserved,
495  CheckVdm->ReservedLen,
496  (PVOID*)&CheckVdm->Reserved);
497  }
498  else CheckVdm->Reserved = NULL;
499 
500  /* Send the message to CSRSS */
501  Status = CsrClientCallServer((PCSR_API_MESSAGE)ApiMessage,
502  CaptureBuffer,
504  sizeof(*CheckVdm));
505 
506  /* Write back the task ID */
507  *iTask = CheckVdm->iTask;
508 
509 Cleanup:
510 
511  /* Free the ANSI strings */
512  if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine);
513  if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName);
514  if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory);
515  if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop);
516  if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle);
517  if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved);
518 
519  /* Free the capture buffer */
520  if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
521 
522  /* Free the current directory, if it was allocated here, and its short path */
523  if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
524  if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
525 
526  /* Free the short app name */
527  if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
528 
529  return Status;
530 }
DWORD *typedef PVOID
Definition: winlogon.h:61
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
VOID NTAPI CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:189
HANDLE StdOut
Definition: basemsg.h:125
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
LPSTR lpTitle
Definition: winbase.h:799
PCHAR AppName
Definition: basemsg.h:130
#define WideCharToMultiByte
Definition: compat.h:101
PCHAR CmdLine
Definition: basemsg.h:129
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:71
PCSR_CAPTURE_BUFFER NTAPI CsrAllocateCaptureBuffer(IN ULONG ArgumentCount, IN ULONG BufferSize)
Definition: capture.c:90
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define CP_ACP
Definition: compat.h:99
ULONG DesktopLen
Definition: basemsg.h:137
NTSTATUS NTAPI CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage, IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, IN CSR_API_NUMBER ApiNumber, IN ULONG DataLength)
Definition: connect.c:360
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:413
_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)
PCHAR CurDirectory
Definition: basemsg.h:132
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
USHORT PifLen
Definition: basemsg.h:144
uint16_t * PWCHAR
Definition: typedefs.h:54
#define WCHAR
Definition: msvc.h:43
ULONG TitleLen
Definition: basemsg.h:139
VOID NTAPI CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PVOID MessageBuffer OPTIONAL, IN ULONG MessageLength, OUT PVOID *CapturedData)
Definition: capture.c:169
ULONG dwCreationFlags
Definition: basemsg.h:128
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT NumStrings
Definition: ndis.h:4733
HANDLE StdErr
Definition: basemsg.h:126
smooth NULL
Definition: ftsmooth.c:416
LPSTR lpReserved
Definition: winbase.h:797
USHORT CmdLen
Definition: basemsg.h:142
#define PCHAR
Definition: match.c:90
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
#define STARTF_USESTDHANDLES
Definition: winbase.h:480
LONG NTSTATUS
Definition: precomp.h:26
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
USHORT CurDrive
Definition: basemsg.h:146
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1832
PCHAR PifFile
Definition: basemsg.h:131
HANDLE StdIn
Definition: basemsg.h:124
static const WCHAR L[]
Definition: oid.c:1087
VOID UINTN Length
Definition: acefiex.h:744
static const WCHAR Cleanup[]
Definition: register.c:80
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:135
Status
Definition: gdiplustypes.h:24
PVOID PVOID PWCHAR ApplicationName
Definition: env.c:45
LPSTR lpDesktop
Definition: winbase.h:798
ULONG BinaryType
Definition: basemsg.h:122
#define NtCurrentPeb()
Definition: FLS.c:19
PCHAR Desktop
Definition: basemsg.h:136
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define STATUS_OBJECT_PATH_INVALID
Definition: ntstatus.h:279
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
unsigned int ULONG
Definition: retypes.h:1
ULONG CodePage
Definition: basemsg.h:127
USHORT CurDirectoryLen
Definition: basemsg.h:145
ULONG ReservedLen
Definition: basemsg.h:141
ULONG EnvLen
Definition: basemsg.h:134
PCHAR Reserved
Definition: basemsg.h:140
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
USHORT AppLen
Definition: basemsg.h:143
HANDLE ConsoleHandle
Definition: basemsg.h:121
BOOL NTAPI BaseCreateVDMEnvironment ( IN PWCHAR  lpEnvironment,
OUT PANSI_STRING  AnsiEnv,
OUT PUNICODE_STRING  UnicodeEnv 
)

Definition at line 736 of file vdm.c.

Referenced by CreateProcessInternalW().

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

Definition at line 1026 of file vdm.c.

Referenced by CreateProcessInternalW().

1028 {
1029  SIZE_T Dummy = 0;
1030 
1031  /* Clear the ANSI buffer since Rtl creates this for us */
1032  if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv);
1033 
1034  /* The Unicode buffer is build by hand, though */
1035  if (UnicodeEnv->Buffer)
1036  {
1037  /* So clear it through the API */
1039  (PVOID*)&UnicodeEnv->Buffer,
1040  &Dummy,
1041  MEM_RELEASE);
1042  }
1043 
1044  /* All done */
1045  return TRUE;
1046 }
DWORD *typedef PVOID
Definition: winlogon.h:61
#define TRUE
Definition: types.h:120
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define MEM_RELEASE
Definition: nt_native.h:1316
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5090
BOOL WINAPI BaseGetVdmConfigInfo ( IN LPCWSTR  CommandLineReserved,
IN ULONG  DosSeqId,
IN ULONG  BinaryType,
IN PUNICODE_STRING  CmdLineString,
OUT PULONG  VdmSize 
)

Definition at line 644 of file vdm.c.

Referenced by CreateProcessInternalW().

649 {
651  WCHAR CommandLine[MAX_PATH * 2];
652  ULONG Length;
653 
654  /* Clear the buffer in case we fail */
655  CmdLineString->Buffer = 0;
656 
657  /* Always return the same size: 16 Mb */
658  *VdmSize = 0x1000000;
659 
660  /* Get the system directory */
661  Length = GetSystemDirectoryW(Buffer, MAX_PATH);
662  if (!(Length) || (Length >= MAX_PATH))
663  {
664  /* Eliminate no path or path too big */
666  return FALSE;
667  }
668 
669  /* Check if this is VDM with a DOS Sequence ID */
670  if (DosSeqId)
671  {
672  /*
673  * Build the VDM string for it:
674  * -i%lx : Gives the DOS Sequence ID;
675  * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
676  */
677  _snwprintf(CommandLine,
678  ARRAYSIZE(CommandLine),
679  L"\"%s\\ntvdm.exe\" -i%lx %s%c",
680  Buffer,
681  DosSeqId,
682  (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
683  (BinaryType == BINARY_TYPE_SEPARATE_WOW) ? L's' : L' ');
684  }
685  else
686  {
687  /*
688  * Build the string for it without the DOS Sequence ID:
689  * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
690  */
691  _snwprintf(CommandLine,
692  ARRAYSIZE(CommandLine),
693  L"\"%s\\ntvdm.exe\" %s%c",
694  Buffer,
695  (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
696  (BinaryType == BINARY_TYPE_SEPARATE_WOW) ? L's' : L' ');
697  }
698 
699  /* Create the actual string */
700  return RtlCreateUnicodeString(CmdLineString, CommandLine);
701 }
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define FALSE
Definition: types.h:117
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
Definition: bufpool.h:45
#define MAX_PATH
Definition: compat.h:26
#define SetLastError(x)
Definition: compat.h:409
#define BINARY_TYPE_SEPARATE_WOW
Definition: vdm.h:39
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
static const WCHAR L[]
Definition: oid.c:1087
VOID UINTN Length
Definition: acefiex.h:744
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2312
unsigned int ULONG
Definition: retypes.h:1
#define BINARY_TYPE_DOS
Definition: vdm.h:38
#define ERROR_INVALID_NAME
Definition: compat.h:93
BOOL WINAPI BaseUpdateVDMEntry ( IN ULONG  UpdateIndex,
IN OUT PHANDLE  WaitHandle,
IN ULONG  IndexInfo,
IN ULONG  BinaryType 
)

Definition at line 534 of file vdm.c.

Referenced by CreateProcessInternalW(), and VDMOperationStarted().

538 {
539  BASE_API_MESSAGE ApiMessage;
540  PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest;
541 
542  /* Check what update is being sent */
543  switch (UpdateIndex)
544  {
545  /* VDM is being undone */
546  case VdmEntryUndo:
547  {
548  /* Tell the server how far we had gotten along */
549  UpdateVdmEntry->iTask = HandleToUlong(*WaitHandle);
550  UpdateVdmEntry->VDMCreationState = IndexInfo;
551  break;
552  }
553 
554  /* VDM is ready with a new process handle */
556  {
557  /* Send it the process handle */
558  UpdateVdmEntry->VDMProcessHandle = *WaitHandle;
559  UpdateVdmEntry->iTask = IndexInfo;
560  break;
561  }
562  }
563 
564  /* Also check what kind of binary this is for the console handle */
565  if (BinaryType == BINARY_TYPE_WOW)
566  {
567  /* Magic value for 16-bit apps */
568  UpdateVdmEntry->ConsoleHandle = (HANDLE)-1;
569  }
570  else if (UpdateVdmEntry->iTask)
571  {
572  /* No handle for true VDM */
573  UpdateVdmEntry->ConsoleHandle = NULL;
574  }
575  else
576  {
577  /* Otherwise, use the regular console handle */
578  UpdateVdmEntry->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
579  }
580 
581  /* Finally write the index and binary type */
582  UpdateVdmEntry->EntryIndex = UpdateIndex;
583  UpdateVdmEntry->BinaryType = BinaryType;
584 
585  /* Send the message to CSRSS */
587  NULL,
589  sizeof(*UpdateVdmEntry));
590  if (!NT_SUCCESS(ApiMessage.Status))
591  {
592  /* Handle failure */
593  BaseSetLastNTError(ApiMessage.Status);
594  return FALSE;
595  }
596 
597  /* If this was an update, CSRSS returns a new wait handle */
598  if (UpdateIndex == VdmEntryUpdateProcess)
599  {
600  /* Return it to the caller */
601  *WaitHandle = UpdateVdmEntry->WaitObjectForParent;
602  }
603 
604  /* We made it */
605  return TRUE;
606 }
#define TRUE
Definition: types.h:120
#define BINARY_TYPE_WOW
Definition: vdm.h:40
Definition: basemsg.h:150
BASE_UPDATE_VDM_ENTRY UpdateVDMEntryRequest
Definition: basemsg.h:288
NTSTATUS NTAPI CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage, IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, IN CSR_API_NUMBER ApiNumber, IN ULONG DataLength)
Definition: connect.c:360
#define HandleToUlong(h)
Definition: basetsd.h:79
ULONG BinaryType
Definition: basemsg.h:153
NTSTATUS Status
Definition: csrmsg.h:112
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
HANDLE WaitObjectForParent
Definition: basemsg.h:156
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
ULONG iTask
Definition: basemsg.h:152
USHORT EntryIndex
Definition: basemsg.h:157
DWORD *typedef HANDLE
Definition: winlogon.h:61
USHORT VDMCreationState
Definition: basemsg.h:158
#define NtCurrentPeb()
Definition: FLS.c:19
HANDLE VDMProcessHandle
Definition: basemsg.h:155
HANDLE ConsoleHandle
Definition: basemsg.h:154
union _BASE_API_MESSAGE::@3380 Data