ReactOS  0.4.10-dev-479-g13a3cf0
vdm.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Win32 Base API
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: dll/win32/kernel32/client/vdm.c
5  * PURPOSE: Virtual DOS Machines (VDM) Support
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <k32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* TYPES **********************************************************************/
17 
18 #define BINARY_UNKNOWN (0)
19 #define BINARY_PE_EXE32 (1)
20 #define BINARY_PE_DLL32 (2)
21 #define BINARY_PE_EXE64 (3)
22 #define BINARY_PE_DLL64 (4)
23 #define BINARY_WIN16 (5)
24 #define BINARY_OS216 (6)
25 #define BINARY_DOS (7)
26 #define BINARY_UNIX_EXE (8)
27 #define BINARY_UNIX_LIB (9)
28 
29 
30 typedef enum _ENV_NAME_TYPE
31 {
36 
37 typedef struct _ENV_INFO
38 {
43 
44 /* GLOBALS ********************************************************************/
45 
46 #define ENV_NAME_ENTRY(type, name) \
47  {(type), _ARRAYSIZE(name) - 1, (name)}
48 
50 {
53  ENV_NAME_ENTRY(EnvNameSinglePath , L"SYSTEMROOT"),
56 };
57 
61 
62 /* FUNCTIONS ******************************************************************/
63 
64 ULONG
65 WINAPI
68 {
70 
71  /* Is it a .com? */
72  String.Length = BaseDotComSuffixName.Length;
73  String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
74  if (RtlEqualUnicodeString(&String, &BaseDotComSuffixName, TRUE)) return BINARY_TYPE_COM;
75 
76  /* Is it a .pif? */
77  String.Length = BaseDotPifSuffixName.Length;
78  String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
79  if (RtlEqualUnicodeString(&String, &BaseDotPifSuffixName, TRUE)) return BINARY_TYPE_PIF;
80 
81  /* Is it an exe? */
82  String.Length = BaseDotExeSuffixName.Length;
83  String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
84  if (RtlEqualUnicodeString(&String, &BaseDotExeSuffixName, TRUE)) return BINARY_TYPE_EXE;
85 
86  return 0;
87 }
88 
90 WINAPI
91 BaseCheckVDM(IN ULONG BinaryType,
93  IN PCWCH CommandLine,
95  IN PANSI_STRING AnsiEnvironment,
96  IN PBASE_API_MESSAGE ApiMessage,
97  IN OUT PULONG iTask,
98  IN DWORD CreationFlags,
99  IN LPSTARTUPINFOW StartupInfo,
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 */
248  Length = GetShortPathNameW(CurrentDirectory, NULL, 0);
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 }
531 
532 BOOL
533 WINAPI
535  IN OUT PHANDLE WaitHandle,
536  IN ULONG IndexInfo,
537  IN ULONG BinaryType)
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 }
607 
608 BOOL
609 WINAPI
611  OUT LPDWORD ExitCode)
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 }
641 
642 BOOL
643 WINAPI
644 BaseGetVdmConfigInfo(IN LPCWSTR CommandLineReserved,
645  IN ULONG DosSeqId,
646  IN ULONG BinaryType,
647  IN PUNICODE_STRING CmdLineString,
648  OUT PULONG VdmSize)
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 }
702 
704 WINAPI
706  IN ULONG NameLength)
707 {
708  PENV_INFO EnvInfo;
710  ULONG i;
711 
712  /* Start by assuming the environment variable doesn't describe paths */
713  NameType = EnvNameNotAPath;
714 
715  /* Loop all the environment names */
716  for (i = 0; i < ARRAYSIZE(BasepEnvNameType); i++)
717  {
718  /* Get this entry */
719  EnvInfo = &BasepEnvNameType[i];
720 
721  /* Check if it matches the name */
722  if ((EnvInfo->NameLength == NameLength) &&
723  (_wcsnicmp(EnvInfo->Name, Name, NameLength) == 0))
724  {
725  /* It does, return the type */
726  NameType = EnvInfo->NameType;
727  break;
728  }
729  }
730 
731  return NameType;
732 }
733 
734 BOOL
735 NTAPI
737  OUT PANSI_STRING AnsiEnv,
738  OUT PUNICODE_STRING UnicodeEnv)
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 }
1023 
1024 BOOL
1025 NTAPI
1027  IN PUNICODE_STRING UnicodeEnv)
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 }
1047 
1048 
1049 /* Check whether a file is an OS/2 or a very old Windows executable
1050  * by testing on import of KERNEL.
1051  *
1052  * FIXME: is reading the module imports the only way of discerning
1053  * old Windows binaries from OS/2 ones ? At least it seems so...
1054  */
1055 static DWORD WINAPI
1057 {
1058  DWORD CurPos;
1059  LPWORD modtab = NULL;
1060  LPSTR nametab = NULL;
1061  DWORD Read, Ret;
1062  int i;
1063 
1064  Ret = BINARY_OS216;
1065  CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1066 
1067  /* read modref table */
1069  (!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
1070  (!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
1071  (Read != (DWORD)ne->ne_cmod * sizeof(WORD)))
1072  {
1073  goto broken;
1074  }
1075 
1076  /* read imported names table */
1078  (!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
1079  (!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
1080  (Read != (DWORD)ne->ne_enttab - ne->ne_imptab))
1081  {
1082  goto broken;
1083  }
1084 
1085  for(i = 0; i < ne->ne_cmod; i++)
1086  {
1087  LPSTR module;
1088  module = &nametab[modtab[i]];
1089  if(!strncmp(&module[1], "KERNEL", module[0]))
1090  {
1091  /* very old windows file */
1092  Ret = BINARY_WIN16;
1093  goto done;
1094  }
1095  }
1096 
1097  broken:
1098  DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
1099 
1100  done:
1101  HeapFree(GetProcessHeap(), 0, modtab);
1102  HeapFree(GetProcessHeap(), 0, nametab);
1103  SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
1104  return Ret;
1105 }
1106 
1107 static DWORD WINAPI
1109 {
1110  union
1111  {
1112  struct
1113  {
1114  unsigned char magic[4];
1115  unsigned char ignored[12];
1116  unsigned short type;
1117  } elf;
1118  struct
1119  {
1120  unsigned long magic;
1121  unsigned long cputype;
1122  unsigned long cpusubtype;
1123  unsigned long filetype;
1124  } macho;
1125  IMAGE_DOS_HEADER mz;
1126  } Header;
1127  char magic[4];
1128  DWORD Read;
1129 
1131  (!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
1132  (Read != sizeof(Header))))
1133  {
1134  return BINARY_UNKNOWN;
1135  }
1136 
1137  if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
1138  {
1139  /* FIXME: we don't bother to check byte order, architecture, etc. */
1140  switch(Header.elf.type)
1141  {
1142  case 2:
1143  return BINARY_UNIX_EXE;
1144  case 3:
1145  return BINARY_UNIX_LIB;
1146  }
1147  return BINARY_UNKNOWN;
1148  }
1149 
1150  /* Mach-o File with Endian set to Big Endian or Little Endian*/
1151  if(Header.macho.magic == 0xFEEDFACE ||
1152  Header.macho.magic == 0xCEFAEDFE)
1153  {
1154  switch(Header.macho.filetype)
1155  {
1156  case 0x8:
1157  /* MH_BUNDLE */
1158  return BINARY_UNIX_LIB;
1159  }
1160  return BINARY_UNKNOWN;
1161  }
1162 
1163  /* Not ELF, try DOS */
1164  if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
1165  {
1166  /* We do have a DOS image so we will now try to seek into
1167  * the file by the amount indicated by the field
1168  * "Offset to extended header" and read in the
1169  * "magic" field information at that location.
1170  * This will tell us if there is more header information
1171  * to read or not.
1172  */
1173  if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
1174  (!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
1175  (Read != sizeof(magic))))
1176  {
1177  return BINARY_DOS;
1178  }
1179 
1180  /* Reading the magic field succeeded so
1181  * we will try to determine what type it is.
1182  */
1183  if(!memcmp(magic, "PE\0\0", sizeof(magic)))
1184  {
1185  IMAGE_FILE_HEADER FileHeader;
1186  if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
1187  (Read != sizeof(IMAGE_FILE_HEADER)))
1188  {
1189  return BINARY_DOS;
1190  }
1191 
1192  /* FIXME - detect 32/64 bit */
1193 
1194  if(FileHeader.Characteristics & IMAGE_FILE_DLL)
1195  return BINARY_PE_DLL32;
1196  return BINARY_PE_EXE32;
1197  }
1198 
1199  if(!memcmp(magic, "NE", 2))
1200  {
1201  /* This is a Windows executable (NE) header. This can
1202  * mean either a 16-bit OS/2 or a 16-bit Windows or even a
1203  * DOS program (running under a DOS extender). To decide
1204  * which, we'll have to read the NE header.
1205  */
1206  IMAGE_OS2_HEADER ne;
1207  if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
1208  !ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
1209  (Read != sizeof(IMAGE_OS2_HEADER)))
1210  {
1211  /* Couldn't read header, so abort. */
1212  return BINARY_DOS;
1213  }
1214 
1215  switch(ne.ne_exetyp)
1216  {
1217  case 2:
1218  return BINARY_WIN16;
1219  case 5:
1220  return BINARY_DOS;
1221  default:
1222  return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
1223  }
1224  }
1225  return BINARY_DOS;
1226  }
1227  return BINARY_UNKNOWN;
1228 }
1229 
1230 /*
1231  * @implemented
1232  */
1233 BOOL
1234 WINAPI
1236  LPCWSTR lpApplicationName,
1237  LPDWORD lpBinaryType
1238  )
1239 {
1240  HANDLE hFile;
1241  DWORD BinType;
1242 
1243  if(!lpApplicationName || !lpBinaryType)
1244  {
1246  return FALSE;
1247  }
1248 
1249  hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
1250  OPEN_EXISTING, 0, 0);
1251  if(hFile == INVALID_HANDLE_VALUE)
1252  {
1253  return FALSE;
1254  }
1255 
1256  BinType = InternalGetBinaryType(hFile);
1257  CloseHandle(hFile);
1258 
1259  switch(BinType)
1260  {
1261  case BINARY_UNKNOWN:
1262  {
1263  WCHAR *dot;
1264 
1265  /*
1266  * guess from filename
1267  */
1268  if(!(dot = wcsrchr(lpApplicationName, L'.')))
1269  {
1270  return FALSE;
1271  }
1272  if(!lstrcmpiW(dot, L".COM"))
1273  {
1274  *lpBinaryType = SCS_DOS_BINARY;
1275  return TRUE;
1276  }
1277  if(!lstrcmpiW(dot, L".PIF"))
1278  {
1279  *lpBinaryType = SCS_PIF_BINARY;
1280  return TRUE;
1281  }
1282  return FALSE;
1283  }
1284  case BINARY_PE_EXE32:
1285  case BINARY_PE_DLL32:
1286  {
1287  *lpBinaryType = SCS_32BIT_BINARY;
1288  return TRUE;
1289  }
1290  case BINARY_PE_EXE64:
1291  case BINARY_PE_DLL64:
1292  {
1293  *lpBinaryType = SCS_64BIT_BINARY;
1294  return TRUE;
1295  }
1296  case BINARY_WIN16:
1297  {
1298  *lpBinaryType = SCS_WOW_BINARY;
1299  return TRUE;
1300  }
1301  case BINARY_OS216:
1302  {
1303  *lpBinaryType = SCS_OS216_BINARY;
1304  return TRUE;
1305  }
1306  case BINARY_DOS:
1307  {
1308  *lpBinaryType = SCS_DOS_BINARY;
1309  return TRUE;
1310  }
1311  case BINARY_UNIX_EXE:
1312  case BINARY_UNIX_LIB:
1313  {
1314  return FALSE;
1315  }
1316  }
1317 
1318  DPRINT1("Invalid binary type %lu returned!\n", BinType);
1319  return FALSE;
1320 }
1321 
1322 /*
1323  * @implemented
1324  */
1325 BOOL
1326 WINAPI
1327 GetBinaryTypeA(IN LPCSTR lpApplicationName,
1328  OUT LPDWORD lpBinaryType)
1329 {
1330  ANSI_STRING ApplicationNameString;
1331  UNICODE_STRING ApplicationNameW;
1332  BOOL StringAllocated = FALSE, Result;
1333  NTSTATUS Status;
1334 
1335  RtlInitAnsiString(&ApplicationNameString, lpApplicationName);
1336 
1337  if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength)
1338  {
1339  StringAllocated = TRUE;
1340  Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE);
1341  }
1342  else
1343  {
1344  Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE);
1345  }
1346 
1347  if (!NT_SUCCESS(Status))
1348  {
1349  BaseSetLastNTError(Status);
1350  return FALSE;
1351  }
1352 
1353  if (StringAllocated)
1354  {
1355  Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType);
1356  RtlFreeUnicodeString(&ApplicationNameW);
1357  }
1358  else
1359  {
1360  Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
1361  }
1362 
1363  return Result;
1364 }
1365 
1366 /*
1367  * @unimplemented
1368  */
1369 BOOL
1370 WINAPI
1372  DWORD Unknown
1373  )
1374 {
1375  STUB;
1376  return FALSE;
1377 }
1378 
1379 /*
1380  * @implemented
1381  */
1382 VOID
1383 WINAPI
1384 ExitVDM(BOOL IsWow, ULONG iWowTask)
1385 {
1386  BASE_API_MESSAGE ApiMessage;
1387  PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest;
1388 
1389  /* Setup the input parameters */
1390  ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1391  ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */
1392  ExitVdm->WaitObjectForVDM = NULL;
1393 
1394  /* Call CSRSS */
1396  NULL,
1398  sizeof(*ExitVdm));
1399 
1400  /* Close the returned wait object handle, if any */
1401  if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL))
1402  {
1403  CloseHandle(ExitVdm->WaitObjectForVDM);
1404  }
1405 }
1406 
1407 /*
1408  * @implemented
1409  */
1410 BOOL
1411 WINAPI
1413 {
1414  BOOL Success = FALSE;
1415  NTSTATUS Status;
1416  BASE_API_MESSAGE ApiMessage;
1417  PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest;
1418  PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest;
1419  PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
1420  PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
1421  ULONG NumStrings = 0;
1422 
1423  /*
1424  * Special case to test whether the VDM is the first one.
1425  */
1426  if (CommandData == NULL)
1427  {
1428  /* Call CSRSS */
1430  NULL,
1432  sizeof(*IsFirstVdm));
1433  if (!NT_SUCCESS(ApiMessage.Status))
1434  {
1435  BaseSetLastNTError(ApiMessage.Status);
1436  return FALSE;
1437  }
1438 
1439  /* Return TRUE if this is the first VDM */
1440  return IsFirstVdm->FirstVDM;
1441  }
1442 
1443  /* CommandData != NULL */
1444 
1445  /*
1446  * Special case to increment or decrement the reentrancy count.
1447  */
1448  if ((CommandData->VDMState == VDM_INC_REENTER_COUNT) ||
1449  (CommandData->VDMState == VDM_DEC_REENTER_COUNT))
1450  {
1451  /* Setup the input parameters */
1452  SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1453  SetReenterCount->fIncDec = CommandData->VDMState;
1454 
1455  /* Call CSRSS */
1457  NULL,
1459  sizeof(*SetReenterCount));
1460  if (!NT_SUCCESS(ApiMessage.Status))
1461  {
1462  BaseSetLastNTError(ApiMessage.Status);
1463  return FALSE;
1464  }
1465 
1466  return TRUE;
1467  }
1468 
1469  /*
1470  * TODO!
1471  * Special case to retrieve or set WOW information.
1472  */
1473  // TODO: if CommandData->VDMState & (VDM_LIST_WOW_PROCESSES | VDM_LIST_WOW_TASKS | VDM_ADD_WOW_TASK)
1474  // then call BasepGetNextVDMCommand in a simpler way!
1475 
1476  /*
1477  * Regular case.
1478  */
1479 
1480  /* Clear the structure */
1481  RtlZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand));
1482 
1483  /* Setup the input parameters */
1484  GetNextVdmCommand->iTask = CommandData->TaskId;
1485  GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1486  GetNextVdmCommand->CmdLen = CommandData->CmdLen;
1487  GetNextVdmCommand->AppLen = CommandData->AppLen;
1488  GetNextVdmCommand->PifLen = CommandData->PifLen;
1489  GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen;
1490  GetNextVdmCommand->EnvLen = CommandData->EnvLen;
1491  GetNextVdmCommand->DesktopLen = CommandData->DesktopLen;
1492  GetNextVdmCommand->TitleLen = CommandData->TitleLen;
1493  GetNextVdmCommand->ReservedLen = CommandData->ReservedLen;
1494  GetNextVdmCommand->VDMState = CommandData->VDMState;
1495 
1496  /* Count the number of strings */
1497  if (CommandData->CmdLen) NumStrings++;
1498  if (CommandData->AppLen) NumStrings++;
1499  if (CommandData->PifLen) NumStrings++;
1500  if (CommandData->CurDirectoryLen) NumStrings++;
1501  if (CommandData->EnvLen) NumStrings++;
1502  if (CommandData->DesktopLen) NumStrings++;
1503  if (CommandData->TitleLen) NumStrings++;
1504  if (CommandData->ReservedLen) NumStrings++;
1505 
1506  /* Allocate the capture buffer */
1507  CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1,
1508  GetNextVdmCommand->CmdLen
1509  + GetNextVdmCommand->AppLen
1510  + GetNextVdmCommand->PifLen
1511  + GetNextVdmCommand->CurDirectoryLen
1512  + GetNextVdmCommand->EnvLen
1513  + GetNextVdmCommand->DesktopLen
1514  + GetNextVdmCommand->TitleLen
1515  + GetNextVdmCommand->ReservedLen
1516  + sizeof(*GetNextVdmCommand->StartupInfo));
1517  if (CaptureBuffer == NULL)
1518  {
1520  goto Cleanup;
1521  }
1522 
1523  /* Capture the data */
1524 
1525  CsrAllocateMessagePointer(CaptureBuffer,
1526  sizeof(*GetNextVdmCommand->StartupInfo),
1527  (PVOID*)&GetNextVdmCommand->StartupInfo);
1528 
1529  if (CommandData->CmdLen)
1530  {
1531  CsrAllocateMessagePointer(CaptureBuffer,
1532  CommandData->CmdLen,
1533  (PVOID*)&GetNextVdmCommand->CmdLine);
1534  }
1535 
1536  if (CommandData->AppLen)
1537  {
1538  CsrAllocateMessagePointer(CaptureBuffer,
1539  CommandData->AppLen,
1540  (PVOID*)&GetNextVdmCommand->AppName);
1541  }
1542 
1543  if (CommandData->PifLen)
1544  {
1545  CsrAllocateMessagePointer(CaptureBuffer,
1546  CommandData->PifLen,
1547  (PVOID*)&GetNextVdmCommand->PifFile);
1548  }
1549 
1550  if (CommandData->CurDirectoryLen)
1551  {
1552  CsrAllocateMessagePointer(CaptureBuffer,
1553  CommandData->CurDirectoryLen,
1554  (PVOID*)&GetNextVdmCommand->CurDirectory);
1555  }
1556 
1557  if (CommandData->EnvLen)
1558  {
1559  CsrAllocateMessagePointer(CaptureBuffer,
1560  CommandData->EnvLen,
1561  (PVOID*)&GetNextVdmCommand->Env);
1562  }
1563 
1564  if (CommandData->DesktopLen)
1565  {
1566  CsrAllocateMessagePointer(CaptureBuffer,
1567  CommandData->DesktopLen,
1568  (PVOID*)&GetNextVdmCommand->Desktop);
1569  }
1570 
1571  if (CommandData->TitleLen)
1572  {
1573  CsrAllocateMessagePointer(CaptureBuffer,
1574  CommandData->TitleLen,
1575  (PVOID*)&GetNextVdmCommand->Title);
1576  }
1577 
1578  if (CommandData->ReservedLen)
1579  {
1580  CsrAllocateMessagePointer(CaptureBuffer,
1581  CommandData->ReservedLen,
1582  (PVOID*)&GetNextVdmCommand->Reserved);
1583  }
1584 
1585  while (TRUE)
1586  {
1587  /* Call CSRSS */
1588  Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1589  CaptureBuffer,
1591  sizeof(*GetNextVdmCommand));
1592 
1593  /* Exit the waiting loop if we did not receive any event handle */
1594  if (GetNextVdmCommand->WaitObjectForVDM == NULL)
1595  break;
1596 
1597  /* Wait for the event to become signaled and try again */
1598  Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM,
1599  FALSE, NULL);
1600  if (Status != STATUS_SUCCESS)
1601  {
1602  /* Fail if we timed out, or if some other error happened */
1603  BaseSetLastNTError(Status);
1604  goto Cleanup;
1605  }
1606 
1607  /* Set the retry flag, clear the exit code, and retry a query */
1608  GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
1609  GetNextVdmCommand->ExitCode = 0;
1610  }
1611 
1612  if (!NT_SUCCESS(Status))
1613  {
1614  if (Status == STATUS_INVALID_PARAMETER)
1615  {
1616  /*
1617  * One of the buffer lengths was less than required. Store the correct ones.
1618  * Note that the status code is not STATUS_BUFFER_TOO_SMALL as one would expect,
1619  * in order to keep compatibility with Windows 2003 BASESRV.DLL.
1620  */
1621  CommandData->CmdLen = GetNextVdmCommand->CmdLen;
1622  CommandData->AppLen = GetNextVdmCommand->AppLen;
1623  CommandData->PifLen = GetNextVdmCommand->PifLen;
1624  CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
1625  CommandData->EnvLen = GetNextVdmCommand->EnvLen;
1626  CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
1627  CommandData->TitleLen = GetNextVdmCommand->TitleLen;
1628  CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
1629  }
1630  else
1631  {
1632  /* Any other failure */
1633  CommandData->CmdLen = 0;
1634  CommandData->AppLen = 0;
1635  CommandData->PifLen = 0;
1636  CommandData->CurDirectoryLen = 0;
1637  CommandData->EnvLen = 0;
1638  CommandData->DesktopLen = 0;
1639  CommandData->TitleLen = 0;
1640  CommandData->ReservedLen = 0;
1641  }
1642 
1643  BaseSetLastNTError(Status);
1644  goto Cleanup;
1645  }
1646 
1647  /* Write back the standard handles */
1648  CommandData->StdIn = GetNextVdmCommand->StdIn;
1649  CommandData->StdOut = GetNextVdmCommand->StdOut;
1650  CommandData->StdErr = GetNextVdmCommand->StdErr;
1651 
1652  /* Write back the startup info */
1653  RtlMoveMemory(&CommandData->StartupInfo,
1654  GetNextVdmCommand->StartupInfo,
1655  sizeof(*GetNextVdmCommand->StartupInfo));
1656 
1657  if (CommandData->CmdLen)
1658  {
1659  /* Write back the command line */
1660  RtlMoveMemory(CommandData->CmdLine,
1661  GetNextVdmCommand->CmdLine,
1662  GetNextVdmCommand->CmdLen);
1663 
1664  /* Set the actual length */
1665  CommandData->CmdLen = GetNextVdmCommand->CmdLen;
1666  }
1667 
1668  if (CommandData->AppLen)
1669  {
1670  /* Write back the application name */
1671  RtlMoveMemory(CommandData->AppName,
1672  GetNextVdmCommand->AppName,
1673  GetNextVdmCommand->AppLen);
1674 
1675  /* Set the actual length */
1676  CommandData->AppLen = GetNextVdmCommand->AppLen;
1677  }
1678 
1679  if (CommandData->PifLen)
1680  {
1681  /* Write back the PIF file name */
1682  RtlMoveMemory(CommandData->PifFile,
1683  GetNextVdmCommand->PifFile,
1684  GetNextVdmCommand->PifLen);
1685 
1686  /* Set the actual length */
1687  CommandData->PifLen = GetNextVdmCommand->PifLen;
1688  }
1689 
1690  if (CommandData->CurDirectoryLen)
1691  {
1692  /* Write back the current directory */
1693  RtlMoveMemory(CommandData->CurDirectory,
1694  GetNextVdmCommand->CurDirectory,
1695  GetNextVdmCommand->CurDirectoryLen);
1696 
1697  /* Set the actual length */
1698  CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
1699  }
1700 
1701  if (CommandData->EnvLen)
1702  {
1703  /* Write back the environment */
1704  RtlMoveMemory(CommandData->Env,
1705  GetNextVdmCommand->Env,
1706  GetNextVdmCommand->EnvLen);
1707 
1708  /* Set the actual length */
1709  CommandData->EnvLen = GetNextVdmCommand->EnvLen;
1710  }
1711 
1712  if (CommandData->DesktopLen)
1713  {
1714  /* Write back the desktop name */
1715  RtlMoveMemory(CommandData->Desktop,
1716  GetNextVdmCommand->Desktop,
1717  GetNextVdmCommand->DesktopLen);
1718 
1719  /* Set the actual length */
1720  CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
1721  }
1722 
1723  if (CommandData->TitleLen)
1724  {
1725  /* Write back the title */
1726  RtlMoveMemory(CommandData->Title,
1727  GetNextVdmCommand->Title,
1728  GetNextVdmCommand->TitleLen);
1729 
1730  /* Set the actual length */
1731  CommandData->TitleLen = GetNextVdmCommand->TitleLen;
1732  }
1733 
1734  if (CommandData->ReservedLen)
1735  {
1736  /* Write back the reserved parameter */
1737  RtlMoveMemory(CommandData->Reserved,
1738  GetNextVdmCommand->Reserved,
1739  GetNextVdmCommand->ReservedLen);
1740 
1741  /* Set the actual length */
1742  CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
1743  }
1744 
1745  /* Write the remaining output parameters */
1746  CommandData->TaskId = GetNextVdmCommand->iTask;
1747  CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags;
1748  CommandData->CodePage = GetNextVdmCommand->CodePage;
1749  CommandData->ExitCode = GetNextVdmCommand->ExitCode;
1750  CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive;
1751  CommandData->VDMState = GetNextVdmCommand->VDMState;
1752  CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat;
1753 
1754  /* It was successful */
1755  Success = TRUE;
1756 
1757 Cleanup:
1758  if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer);
1759  return Success;
1760 }
1761 
1762 
1763 /*
1764  * @implemented
1765  */
1766 DWORD
1767 WINAPI
1768 GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
1769 {
1770  BASE_API_MESSAGE ApiMessage;
1771  PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
1772  PCSR_CAPTURE_BUFFER CaptureBuffer;
1773 
1774  /* Allocate the capture buffer */
1775  CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
1776  if (CaptureBuffer == NULL)
1777  {
1779  return 0;
1780  }
1781 
1782  /* Setup the input parameters */
1783  VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
1784  CsrAllocateMessagePointer(CaptureBuffer,
1785  cchCurDirs,
1786  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
1787 
1788  /* Call CSRSS */
1790  CaptureBuffer,
1792  sizeof(*VDMCurrentDirsRequest));
1793 
1794  /* Set the last error */
1795  BaseSetLastNTError(ApiMessage.Status);
1796 
1797  if (NT_SUCCESS(ApiMessage.Status))
1798  {
1799  /* Copy the result */
1800  RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs);
1801  }
1802 
1803  /* Free the capture buffer */
1804  CsrFreeCaptureBuffer(CaptureBuffer);
1805 
1806  /* Return the size if it was successful, or if the buffer was too small */
1807  return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL))
1808  ? VDMCurrentDirsRequest->cchCurDirs : 0;
1809 }
1810 
1811 
1812 /*
1813  * @implemented (undocumented)
1814  */
1815 BOOL
1816 WINAPI
1817 RegisterConsoleVDM(IN DWORD dwRegisterFlags,
1818  IN HANDLE hStartHardwareEvent,
1819  IN HANDLE hEndHardwareEvent,
1820  IN HANDLE hErrorHardwareEvent,
1821  IN DWORD dwUnusedVar,
1822  OUT LPDWORD lpVideoStateLength,
1823  OUT PVOID* lpVideoState, // PVIDEO_HARDWARE_STATE_HEADER*
1824  IN PVOID lpUnusedBuffer,
1825  IN DWORD dwUnusedBufferLength,
1826  IN COORD dwVDMBufferSize,
1827  OUT PVOID* lpVDMBuffer)
1828 {
1829  BOOL Success;
1830  CONSOLE_API_MESSAGE ApiMessage;
1831  PCONSOLE_REGISTERVDM RegisterVDMRequest = &ApiMessage.Data.RegisterVDMRequest;
1832  PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
1833 
1834  /* Set up the data to send to the Console Server */
1835  RegisterVDMRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1836  RegisterVDMRequest->RegisterFlags = dwRegisterFlags;
1837 
1838  if (dwRegisterFlags != 0)
1839  {
1840  RegisterVDMRequest->StartHardwareEvent = hStartHardwareEvent;
1841  RegisterVDMRequest->EndHardwareEvent = hEndHardwareEvent;
1842  RegisterVDMRequest->ErrorHardwareEvent = hErrorHardwareEvent;
1843 
1844  RegisterVDMRequest->VDMBufferSize = dwVDMBufferSize;
1845 
1846 #if 0
1847  RegisterVDMRequest->UnusedBufferLength = dwUnusedBufferLength;
1848 
1849  /* Allocate a Capture Buffer */
1850  CaptureBuffer = CsrAllocateCaptureBuffer(1, dwUnusedBufferLength);
1851  if (CaptureBuffer == NULL)
1852  {
1853  DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1855  return FALSE;
1856  }
1857 
1858  /* Capture the buffer to write */
1859  CsrCaptureMessageBuffer(CaptureBuffer,
1860  (PVOID)lpUnusedBuffer,
1861  dwUnusedBufferLength,
1862  (PVOID*)&RegisterVDMRequest->UnusedBuffer);
1863 #endif
1864  }
1865  else
1866  {
1867  // CaptureBuffer = NULL;
1868  }
1869 
1870  /* Call the server */
1872  CaptureBuffer,
1874  sizeof(*RegisterVDMRequest));
1875 
1876  /* Check for success */
1877  Success = NT_SUCCESS(ApiMessage.Status);
1878 
1879  /* Release the capture buffer if needed */
1880  if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1881 
1882  /* Retrieve the results */
1883  if (Success)
1884  {
1885  if (dwRegisterFlags != 0)
1886  {
1887  _SEH2_TRY
1888  {
1889  *lpVideoStateLength = RegisterVDMRequest->VideoStateLength;
1890  *lpVideoState = RegisterVDMRequest->VideoState;
1891  *lpVDMBuffer = RegisterVDMRequest->VDMBuffer;
1892  }
1894  {
1896  Success = FALSE;
1897  }
1898  _SEH2_END;
1899  }
1900  }
1901  else
1902  {
1903  BaseSetLastNTError(ApiMessage.Status);
1904  }
1905 
1906  /* Return success status */
1907  return Success;
1908 }
1909 
1910 
1911 /*
1912  * @unimplemented
1913  */
1914 BOOL
1915 WINAPI
1917  DWORD Unknown0
1918  )
1919 {
1920  STUB;
1921  return FALSE;
1922 }
1923 
1924 
1925 /*
1926  * @unimplemented
1927  */
1928 BOOL
1929 WINAPI
1931  DWORD Unknown0
1932  )
1933 {
1934  STUB;
1935  return FALSE;
1936 }
1937 
1938 
1939 /*
1940  * @implemented
1941  */
1942 BOOL
1943 WINAPI
1944 SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
1945 {
1946  BASE_API_MESSAGE ApiMessage;
1947  PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
1948  PCSR_CAPTURE_BUFFER CaptureBuffer;
1949 
1950  /* Allocate the capture buffer */
1951  CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
1952  if (CaptureBuffer == NULL)
1953  {
1955  return FALSE;
1956  }
1957 
1958  /* Setup the input parameters */
1959  VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
1960  CsrCaptureMessageBuffer(CaptureBuffer,
1961  lpszzCurDirs,
1962  cchCurDirs,
1963  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
1964 
1965  /* Call CSRSS */
1967  CaptureBuffer,
1969  sizeof(*VDMCurrentDirsRequest));
1970 
1971  /* Free the capture buffer */
1972  CsrFreeCaptureBuffer(CaptureBuffer);
1973 
1974  /* Set the last error */
1975  BaseSetLastNTError(ApiMessage.Status);
1976 
1977  return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE;
1978 }
1979 
1980 /*
1981  * @unimplemented
1982  */
1983 DWORD
1984 WINAPI
1986  DWORD Unknown0,
1987  DWORD Unknown1
1988  )
1989 {
1990  STUB;
1991  return 0;
1992 }
1993 
1994 
1995 /*
1996  * @unimplemented
1997  */
1998 BOOL
1999 WINAPI
2001 {
2002  DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
2003 
2005  NULL,
2006  0,
2007  Unknown0);
2008 }
enum _ENV_NAME_TYPE ENV_NAME_TYPE
DWORD *typedef PVOID
Definition: winlogon.h:60
#define SCS_32BIT_BINARY
Definition: winbase.h:233
union _CONSOLE_API_MESSAGE::@3324 Data
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
LPSTR Desktop
Definition: vdm.h:84
CONST WCHAR * PCWCH
Definition: ntbasedef.h:418
static UNICODE_STRING BaseDotExeSuffixName
Definition: vdm.c:60
VOID NTAPI CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:189
#define ERROR_BAD_ENVIRONMENT
Definition: winerror.h:113
BOOL WINAPI VDMOperationStarted(IN ULONG Unknown0)
Definition: vdm.c:2000
HANDLE StdOut
Definition: basemsg.h:125
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define IN
Definition: typedefs.h:38
HANDLE EndHardwareEvent
Definition: conmsg.h:874
_In_ BOOLEAN Read
Definition: strmini.h:479
BASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest
Definition: basemsg.h:292
unsigned short WORD
Definition: ntddk_ex.h:93
ENV_NAME_TYPE NameType
Definition: vdm.c:39
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define CloseHandle
Definition: compat.h:398
HMODULE module
Definition: main.cpp:46
ULONG DesktopLen
Definition: vdm.h:85
#define INVALID_SET_FILE_POINTER
Definition: winbase.h:115
ULONG ExitCode
Definition: vdm.h:72
HANDLE WaitObjectForVDM
Definition: basemsg.h:198
#define BINARY_UNKNOWN
Definition: vdm.c:18
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
LPSTR lpTitle
Definition: winbase.h:799
PCHAR AppName
Definition: basemsg.h:130
USHORT CurrentDrive
Definition: vdm.h:95
#define BINARY_PE_DLL32
Definition: vdm.c:20
#define WideCharToMultiByte
Definition: compat.h:101
#define IS_PATH_SEPARATOR(x)
#define BINARY_TYPE_WOW
Definition: vdm.h:40
BOOL WINAPI BaseUpdateVDMEntry(IN ULONG UpdateIndex, IN OUT PHANDLE WaitHandle, IN ULONG IndexInfo, IN ULONG BinaryType)
Definition: vdm.c:534
#define BINARY_PE_EXE32
Definition: vdm.c:19
Definition: basemsg.h:150
LPSTR CmdLine
Definition: vdm.h:77
ULONG NTAPI CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN ULONG MessageLength, OUT PVOID *CapturedData)
Definition: capture.c:133
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
BASE_UPDATE_VDM_ENTRY UpdateVDMEntryRequest
Definition: basemsg.h:288
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
HANDLE StdErr
Definition: vdm.h:76
#define BINARY_DOS
Definition: vdm.c:25
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
__wchar_t WCHAR
Definition: xmlstorage.h:180
NTSYSAPI VOID NTAPI RtlDestroyEnvironment(_In_ PWSTR Environment)
BOOL NTAPI BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment, OUT PANSI_STRING AnsiEnv, OUT PUNICODE_STRING UnicodeEnv)
Definition: vdm.c:736
_ENV_NAME_TYPE
Definition: vdm.c:30
return STATUS_SUCCESS
Definition: btrfs.c:2690
#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
HANDLE ConsoleHandle
Definition: conmsg.h:871
#define FILE_CURRENT
Definition: winbase.h:113
BOOL WINAPI BaseGetVdmConfigInfo(IN LPCWSTR CommandLineReserved, IN ULONG DosSeqId, IN ULONG BinaryType, IN PUNICODE_STRING CmdLineString, OUT PULONG VdmSize)
Definition: vdm.c:644
BOOL NTAPI BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv, IN PUNICODE_STRING UnicodeEnv)
Definition: vdm.c:1026
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define HandleToUlong(h)
Definition: basetsd.h:79
#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
u32_t magic(void)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define BINARY_WIN16
Definition: vdm.c:23
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
static DWORD WINAPI InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
Definition: vdm.c:1056
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
USHORT PifLen
Definition: vdm.h:92
BOOL WINAPI BaseCheckForVDM(IN HANDLE ProcessHandle, OUT LPDWORD ExitCode)
Definition: vdm.c:610
#define SCS_OS216_BINARY
Definition: winbase.h:236
SIZE_T LPSTARTUPINFOW
Definition: cordebug.idl:85
USHORT PifLen
Definition: basemsg.h:144
#define SCS_64BIT_BINARY
Definition: winbase.h:234
ENV_NAME_TYPE WINAPI BaseGetEnvNameType_U(IN PWCHAR Name, IN ULONG NameLength)
Definition: vdm.c:705
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define BINARY_PE_DLL64
Definition: vdm.c:22
uint16_t * PWCHAR
Definition: typedefs.h:54
BASE_EXIT_VDM ExitVDMRequest
Definition: basemsg.h:290
USHORT CmdLen
Definition: vdm.h:90
VOID WINAPI ExitVDM(BOOL IsWow, ULONG iWowTask)
Definition: vdm.c:1384
char * LPSTR
Definition: xmlstorage.h:182
#define WCHAR
Definition: msvc.h:43
#define MEM_COMMIT
Definition: nt_native.h:1313
BOOL WINAPI GetBinaryTypeW(LPCWSTR lpApplicationName, LPDWORD lpBinaryType)
Definition: vdm.c:1235
DWORD DWORD
Definition: winlogon.h:83
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define FILE_SHARE_READ
Definition: compat.h:125
ULONG BinaryType
Definition: basemsg.h:153
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define BINARY_UNIX_LIB
Definition: vdm.c:27
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:52
_SEH2_TRY
Definition: create.c:4250
BOOLEAN ComingFromBat
Definition: vdm.h:96
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
ULONG TitleLen
Definition: basemsg.h:139
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
static UNICODE_STRING BaseDotComSuffixName
Definition: vdm.c:58
USHORT CurDirectoryLen
Definition: vdm.h:93
DWORD WINAPI GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
Definition: vdm.c:1768
CHAR16 * String
Definition: acefiex.h:201
GLenum GLclampf GLint i
Definition: glfuncs.h:14
NTSTATUS Status
Definition: csrmsg.h:112
#define SCS_DOS_BINARY
Definition: winbase.h:235
VOID NTAPI CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PVOID MessageBuffer OPTIONAL, IN ULONG MessageLength, OUT PVOID *CapturedData)
Definition: capture.c:169
static HANDLE hUserToken
Definition: umpnpmgr.c:68
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
CONSOLE_REGISTERVDM RegisterVDMRequest
Definition: conmsg.h:997
ULONG dwCreationFlags
Definition: basemsg.h:128
Definition: Header.h:8
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT NumStrings
Definition: ndis.h:4733
union _BASE_API_MESSAGE::@3322 Data
BASE_IS_FIRST_VDM IsFirstVDMRequest
Definition: basemsg.h:291
LPVOID Reserved
Definition: vdm.h:88
BOOL WINAPI RegisterConsoleVDM(IN DWORD dwRegisterFlags, IN HANDLE hStartHardwareEvent, IN HANDLE hEndHardwareEvent, IN HANDLE hErrorHardwareEvent, IN DWORD dwUnusedVar, OUT LPDWORD lpVideoStateLength, OUT PVOID *lpVideoState, IN PVOID lpUnusedBuffer, IN DWORD dwUnusedBufferLength, IN COORD dwVDMBufferSize, OUT PVOID *lpVDMBuffer)
Definition: vdm.c:1817
HANDLE StdErr
Definition: basemsg.h:126
#define SCS_PIF_BINARY
Definition: winbase.h:237
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
HANDLE StdIn
Definition: vdm.h:74
#define SCS_WOW_BINARY
Definition: winbase.h:239
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
smooth NULL
Definition: ftsmooth.c:416
#define VDM_FLAG_RETRY
Definition: vdm.h:56
#define BINARY_TYPE_PIF
Definition: vdm.h:37
#define ENV_NAME_ENTRY(type, name)
Definition: vdm.c:46
BOOL WINAPI SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
Definition: vdm.c:1944
#define BINARY_OS216
Definition: vdm.c:24
DWORD WINAPI VDMConsoleOperation(DWORD Unknown0, DWORD Unknown1)
Definition: vdm.c:1985
#define IS_ALPHA(x)
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
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
Definition: bufpool.h:45
USHORT VDMState
Definition: vdm.h:94
LPSTR lpReserved
Definition: winbase.h:797
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
#define VDM_DEC_REENTER_COUNT
Definition: vdm.h:58
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
const char * LPCSTR
Definition: xmlstorage.h:183
HANDLE WaitObjectForParent
Definition: basemsg.h:156
#define OPEN_EXISTING
Definition: compat.h:426
#define NtCurrentProcess()
Definition: nt_native.h:1657
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
ULONG CreationFlags
Definition: vdm.h:71
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:178
LPSTR CurDirectory
Definition: vdm.h:80
unsigned int BOOL
Definition: ntddk_ex.h:94
LONG NTSTATUS
Definition: precomp.h:26
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
ULONG iWowTask
Definition: basemsg.h:197
#define BINARY_PE_EXE64
Definition: vdm.c:21
BASE_SET_REENTER_COUNT SetReenterCountRequest
Definition: basemsg.h:293
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
USHORT CurDrive
Definition: basemsg.h:146
BASE_GET_NEXT_VDM_COMMAND GetNextVDMCommandRequest
Definition: basemsg.h:289
ULONG WINAPI BaseIsDosApplication(IN PUNICODE_STRING PathName, IN NTSTATUS Status)
Definition: vdm.c:66
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1832
LPSTR PifFile
Definition: vdm.h:79
#define MAX_PATH
Definition: compat.h:26
USHORT AppLen
Definition: vdm.h:91
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
ULONG iTask
Definition: basemsg.h:152
BOOL WINAPI CmdBatNotification(DWORD Unknown)
Definition: vdm.c:1371
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define SetLastError(x)
Definition: compat.h:409
#define BINARY_TYPE_SEPARATE_WOW
Definition: vdm.h:39
BASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest
Definition: basemsg.h:295
LPSTR Env
Definition: vdm.h:81
PWCHAR Name
Definition: vdm.c:41
ULONG VideoStateLength
Definition: conmsg.h:880
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
PCHAR PifFile
Definition: basemsg.h:131
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1327
HANDLE StdIn
Definition: basemsg.h:124
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
static const WCHAR L[]
Definition: oid.c:1087
VOID UINTN Length
Definition: acefiex.h:744
Definition: vdm.c:37
static ENV_INFO BasepEnvNameType[]
Definition: vdm.c:49
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
BOOL WINAPI RegisterWowExec(DWORD Unknown0)
Definition: vdm.c:1930
#define ERROR_INVALID_ACCESS
Definition: winerror.h:115
#define GENERIC_READ
Definition: compat.h:124
static const WCHAR Cleanup[]
Definition: register.c:80
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:135
_In_ HANDLE hFile
Definition: mswsock.h:90
BOOL WINAPI RegisterWowBaseHandlers(DWORD Unknown0)
Definition: vdm.c:1916
#define WINAPI
Definition: msvc.h:20
Definition: bl.h:1338
ULONG EnvLen
Definition: vdm.h:82
HANDLE ErrorHardwareEvent
Definition: conmsg.h:875
#define broken(x)
Definition: _sntprintf.h:21
HANDLE StartHardwareEvent
Definition: conmsg.h:873
Status
Definition: gdiplustypes.h:24
static UNICODE_STRING BaseDotPifSuffixName
Definition: vdm.c:59
NTSYSAPI NTSTATUS NTAPI RtlCreateEnvironment(_In_ BOOLEAN Inherit, _Out_ PWSTR *Environment)
uint16_t * LPWORD
Definition: typedefs.h:54
USHORT EntryIndex
Definition: basemsg.h:157
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define FILE_BEGIN
Definition: winbase.h:112
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: vdm.c:91
DWORD *typedef HANDLE
Definition: winlogon.h:60
PVOID PVOID PWCHAR ApplicationName
Definition: env.c:45
_SEH2_END
Definition: create.c:4424
USHORT VDMCreationState
Definition: basemsg.h:158
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
LPSTR lpDesktop
Definition: winbase.h:798
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
ULONG BinaryType
Definition: basemsg.h:122
#define STUB
Definition: kernel32.h:27
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
ULONG NameLength
Definition: vdm.c:40
#define BINARY_TYPE_COM
Definition: vdm.h:36
PCHAR Desktop
Definition: basemsg.h:136
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
LPSTR AppName
Definition: vdm.h:78
HANDLE VDMProcessHandle
Definition: basemsg.h:155
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
static DWORD WINAPI InternalGetBinaryType(HANDLE hFile)
Definition: vdm.c:1108
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2312
unsigned int * PULONG
Definition: retypes.h:1
#define STATUS_OBJECT_PATH_INVALID
Definition: ntstatus.h:279
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
HANDLE ConsoleHandle
Definition: basemsg.h:154
uint8_t ignored[3]
Definition: fsck.fat.h:35
#define DPRINT1
Definition: precomp.h:8
LPSTR Title
Definition: vdm.h:86
#define CreateFileW
Definition: compat.h:400
#define BINARY_UNIX_EXE
Definition: vdm.c:26
HANDLE ConsoleHandle
Definition: basemsg.h:196
#define MEM_RELEASE
Definition: nt_native.h:1316
#define VDM_INC_REENTER_COUNT
Definition: vdm.h:57
#define OUT
Definition: typedefs.h:39
uint32_t * LPDWORD
Definition: typedefs.h:57
unsigned int ULONG
Definition: retypes.h:1
ULONG CodePage
Definition: basemsg.h:127
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define BINARY_TYPE_DOS
Definition: vdm.h:38
USHORT CurDirectoryLen
Definition: basemsg.h:145
#define ERROR_INVALID_NAME
Definition: compat.h:93
LOCAL char * filetype(int t)
Definition: tree.c:114
ULONG ReservedLen
Definition: basemsg.h:141
STARTUPINFOA StartupInfo
Definition: vdm.h:83
ULONG EnvLen
Definition: basemsg.h:134
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
HANDLE StdOut
Definition: vdm.h:75
ULONG ReservedLen
Definition: vdm.h:89
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
PCHAR Reserved
Definition: basemsg.h:140
struct _ENV_INFO ENV_INFO
BOOL WINAPI GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
Definition: vdm.c:1412
ULONG TitleLen
Definition: vdm.h:87
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
struct _ENV_INFO * PENV_INFO
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
ULONG CodePage
Definition: vdm.h:73
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:394
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
ULONG TaskId
Definition: vdm.h:70
ULONG UnusedBufferLength
Definition: conmsg.h:885
USHORT AppLen
Definition: basemsg.h:143
#define BINARY_TYPE_EXE
Definition: vdm.h:35
#define NtCurrentPeb()
Definition: rtlfuncs.h:1073
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define CONSRV_SERVERDLL_INDEX
Definition: conmsg.h:15
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
HANDLE ConsoleHandle
Definition: basemsg.h:121
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5090
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)