ReactOS  0.4.15-dev-3165-gdf6fff7
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 }
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:365
LONG NTSTATUS
Definition: precomp.h:26
#define FALSE
Definition: types.h:117
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
#define CSR_CREATE_API_NUMBER(ServerId, ApiId)
Definition: csrmsg.h:37
Status
Definition: gdiplustypes.h:24
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union _BASE_API_MESSAGE::@3456 Data
#define NtCurrentPeb()
Definition: FLS.c:22
#define NULL
Definition: types.h:112
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403

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;
108  SIZE_T 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 */
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 
517 Cleanup:
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 }
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
VOID NTAPI CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:210
HANDLE StdOut
Definition: basemsg.h:125
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
LPSTR lpTitle
Definition: winbase.h:828
PCHAR AppName
Definition: basemsg.h:130
#define WideCharToMultiByte
Definition: compat.h:111
PCHAR CmdLine
Definition: basemsg.h:129
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
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:109
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:365
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:615
_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:1040
USHORT PifLen
Definition: basemsg.h:144
uint16_t * PWCHAR
Definition: typedefs.h:56
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:190
ULONG dwCreationFlags
Definition: basemsg.h:128
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT NumStrings
Definition: ndis.h:4751
HANDLE StdErr
Definition: basemsg.h:126
LPSTR lpReserved
Definition: winbase.h:826
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:588
Status
Definition: gdiplustypes.h:24
#define STARTF_USESTDHANDLES
Definition: winbase.h:496
#define UNICODE_STRING_MAX_CHARS
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
__wchar_t WCHAR
Definition: xmlstorage.h:180
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:1250
static const WCHAR Cleanup[]
Definition: register.c:80
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:135
ULONG_PTR SIZE_T
Definition: typedefs.h:80
PVOID PVOID PWCHAR ApplicationName
Definition: env.c:47
LPSTR lpDesktop
Definition: winbase.h:827
ULONG BinaryType
Definition: basemsg.h:122
#define NtCurrentPeb()
Definition: FLS.c:22
unsigned short USHORT
Definition: pedump.c:61
PCHAR Desktop
Definition: basemsg.h:136
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_OBJECT_PATH_INVALID
Definition: ntstatus.h:293
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
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
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
PCHAR Reserved
Definition: basemsg.h:140
USHORT AppLen
Definition: basemsg.h:143
HANDLE ConsoleHandle
Definition: basemsg.h:121

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 
755  BOOL Success = FALSE;
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,
817  MEM_COMMIT,
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 
900  if (NameType == EnvNameNotAPath)
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 
1008 Cleanup:
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 }
enum _ENV_NAME_TYPE ENV_NAME_TYPE
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_BAD_ENVIRONMENT
Definition: winerror.h:113
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define IS_PATH_SEPARATOR(x)
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlDestroyEnvironment(_In_ PWSTR Environment)
LONG NTSTATUS
Definition: precomp.h:26
#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:713
uint16_t * PWCHAR
Definition: typedefs.h:56
#define MEM_COMMIT
Definition: nt_native.h:1313
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
#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
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1832
#define MAX_PATH
Definition: compat.h:34
#define SetLastError(x)
Definition: compat.h:611
static const WCHAR L[]
Definition: oid.c:1250
static const WCHAR Cleanup[]
Definition: register.c:80
NTSYSAPI NTSTATUS NTAPI RtlCreateEnvironment(_In_ BOOLEAN Inherit, _Out_ PWSTR *Environment)
ULONG_PTR SIZE_T
Definition: typedefs.h:80
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:4481
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define NULL
Definition: types.h:112
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define MEM_RELEASE
Definition: nt_native.h:1316
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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:654
#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:5204

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 }
#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:80
#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:5204

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];
660  ULONG Length;
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 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#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
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:34
#define SetLastError(x)
Definition: compat.h:611
#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:1250
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:103

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 }
#define BINARY_TYPE_WOW
Definition: vdm.h:40
Definition: basemsg.h:150
BASE_UPDATE_VDM_ENTRY UpdateVDMEntryRequest
Definition: basemsg.h:288
#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:365
#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
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:32
ULONG iTask
Definition: basemsg.h:152
PVOID HANDLE
Definition: typedefs.h:73
union _BASE_API_MESSAGE::@3456 Data
USHORT EntryIndex
Definition: basemsg.h:157
USHORT VDMCreationState
Definition: basemsg.h:158
#define NtCurrentPeb()
Definition: FLS.c:22
HANDLE VDMProcessHandle
Definition: basemsg.h:155
#define NULL
Definition: types.h:112
HANDLE ConsoleHandle
Definition: basemsg.h:154

Referenced by CreateProcessInternalW(), and VDMOperationStarted().