ReactOS  r74227
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,
92  IN PCWCH ApplicationName,
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 RegionSize, EnvironmentSize = 0;
750  PWCHAR Environment, NewEnvironment = NULL;
752  ULONG NameLength, NumChars, Remaining;
753  PWCHAR SourcePtr, DestPtr, StartPtr;
754 
755  /* Make sure we have both strings */
756  if (!AnsiEnv || !UnicodeEnv)
757  {
758  /* Fail */
760  return FALSE;
761  }
762 
763  /* Check if an environment was passed in */
764  if (!lpEnvironment)
765  {
766  /* Nope, create one */
767  Status = RtlCreateEnvironment(TRUE, &Environment);
768  if (!NT_SUCCESS(Status)) goto Cleanup;
769  }
770  else
771  {
772  /* Use the one we got */
773  Environment = lpEnvironment;
774  }
775 
776  /* Do we have something now ? */
777  if (!Environment)
778  {
779  /* Still not, bail out */
781  goto Cleanup;
782  }
783 
784  /*
785  * Count how much space the whole environment takes. The environment block is
786  * doubly NULL-terminated (NULL from last string and final NULL terminator).
787  */
788  SourcePtr = Environment;
789  while (!(*SourcePtr++ == UNICODE_NULL && *SourcePtr == UNICODE_NULL))
790  ++EnvironmentSize;
791  EnvironmentSize += 2; // Add the two terminating NULLs
792 
793  /*
794  * Allocate a new copy large enough to hold all the environment with paths
795  * in their short form. Since the short form of a path can be a bit longer
796  * than its long form, for example in the case where characters that are
797  * invalid in the 8.3 representation are present in the long path name:
798  * 'C:\\a+b' --> 'C:\\A_B~1', or:
799  * 'C:\\a b' --> 'C:\\AB2761~1' (with checksum inserted),
800  * we suppose that the possible total number of extra characters needed to
801  * convert the long paths into their short form is at most equal to MAX_PATH.
802  */
803  RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR);
805  (PVOID*)&NewEnvironment,
806  0,
807  &RegionSize,
808  MEM_COMMIT,
810  if (!NT_SUCCESS(Status))
811  {
812  /* We failed, bail out */
814  NewEnvironment = NULL;
815  goto Cleanup;
816  }
817 
818  /* Parse the environment block */
819  Remaining = MAX_PATH - 2; // '-2': remove the last two NULLs. FIXME: is it really needed??
820  SourcePtr = Environment;
821  DestPtr = NewEnvironment;
822 
823  /* Loop through all the environment strings */
824  while (*SourcePtr != UNICODE_NULL)
825  {
826  /*
827  * 1. Check the type of the environment variable and copy its name.
828  */
829 
830  /* Regular environment variable */
831  if (*SourcePtr != L'=')
832  {
833  StartPtr = SourcePtr;
834 
835  /* Copy the environment variable name, including the '=' */
836  while (*SourcePtr != UNICODE_NULL)
837  {
838  *DestPtr++ = *SourcePtr;
839  if (*SourcePtr++ == L'=') break;
840  }
841 
842  /* Guess the type of the environment variable */
843  NameType = BaseGetEnvNameType_U(StartPtr, SourcePtr - StartPtr - 1);
844  }
845  /* 'Current directory' environment variable (i.e. of '=X:=' form) */
846  else // if (*SourcePtr == L'=')
847  {
848  /* First assume we have a possibly malformed environment variable */
849  NameType = EnvNameNotAPath;
850 
851  /* Check for a valid 'Current directory' environment variable */
852  if (IS_ALPHA(SourcePtr[1]) && SourcePtr[2] == L':' && SourcePtr[3] == L'=')
853  {
854  /*
855  * Small optimization: convert the path to short form only if
856  * the current directory is not the root directory (i.e. not
857  * of the '=X:=Y:\' form), otherwise just do a simple copy.
858  */
859  if ( wcslen(SourcePtr) >= ARRAYSIZE("=X:=Y:\\")-1 &&
860  !( IS_ALPHA(SourcePtr[4]) && SourcePtr[5] == L':' &&
861  IS_PATH_SEPARATOR(SourcePtr[6]) && SourcePtr[7] == UNICODE_NULL ) )
862  {
863  NameType = EnvNameSinglePath;
864 
865  /* Copy the '=X:=' prefix */
866  *DestPtr++ = SourcePtr[0];
867  *DestPtr++ = SourcePtr[1];
868  *DestPtr++ = SourcePtr[2];
869  *DestPtr++ = SourcePtr[3];
870  SourcePtr += 4;
871  }
872  }
873  else
874  {
875  /*
876  * Invalid stuff starting with '=', i.e.:
877  * =? (with '?' not being a letter)
878  * =X??? (with '?' not being ":=" and not followed by something longer than 3 characters)
879  * =X:=??? (with '?' not being "X:\\")
880  *
881  * 'NameType' is already set to 'EnvNameNotAPath'.
882  */
883  }
884  }
885 
886 
887  /*
888  * 2. Copy the environment value and perform conversions accordingly.
889  */
890 
891  if (NameType == EnvNameNotAPath)
892  {
893  /* Copy everything, including the NULL terminator */
894  do
895  {
896  *DestPtr++ = *SourcePtr;
897  } while (*SourcePtr++ != UNICODE_NULL);
898  }
899  else if (NameType == EnvNameSinglePath)
900  {
901  /* Convert the path to its short form */
902  NameLength = wcslen(SourcePtr);
903  NumChars = GetShortPathNameW(SourcePtr, DestPtr, NameLength + 1 + Remaining);
904  if (NumChars == 0 || NumChars > NameLength + Remaining)
905  {
906  /* If the conversion failed, just copy the original value */
907  RtlCopyMemory(DestPtr, SourcePtr, NameLength * sizeof(WCHAR));
908  NumChars = NameLength;
909  }
910  DestPtr += NumChars;
911  if (NumChars > NameLength)
912  Remaining -= (NumChars - NameLength);
913 
914  SourcePtr += NameLength;
915 
916  /* Copy the NULL terminator */
917  *DestPtr++ = *SourcePtr++;
918  }
919  else // if (NameType == EnvNameMultiplePath)
920  {
921  WCHAR Delimiter;
922 
923  /* Loop through the list of paths (delimited by ';') and convert each path to its short form */
924  do
925  {
926  /* Copy any trailing ';' before going to the next path */
927  while (*SourcePtr == L';')
928  {
929  *DestPtr++ = *SourcePtr++;
930  }
931 
932  StartPtr = SourcePtr;
933 
934  /* Find the next path list delimiter or the NULL terminator */
935  while (*SourcePtr != UNICODE_NULL && *SourcePtr != L';')
936  {
937  ++SourcePtr;
938  }
939  Delimiter = *SourcePtr;
940 
941  NameLength = SourcePtr - StartPtr;
942  if (NameLength)
943  {
944  /*
945  * Temporarily replace the possible path list delimiter by NULL.
946  * 'lpEnvironment' must point to a read+write memory buffer!
947  */
948  *SourcePtr = UNICODE_NULL;
949 
950  NumChars = GetShortPathNameW(StartPtr, DestPtr, NameLength + 1 + Remaining);
951  if ( NumChars == 0 ||
952  (Delimiter == L';' ? NumChars > NameLength + Remaining
953  : NumChars > NameLength /* + Remaining ?? */) )
954  {
955  /* If the conversion failed, just copy the original value */
956  RtlCopyMemory(DestPtr, StartPtr, NameLength * sizeof(WCHAR));
957  NumChars = NameLength;
958  }
959  DestPtr += NumChars;
960  if (NumChars > NameLength)
961  Remaining -= (NumChars - NameLength);
962 
963  /* If removed, restore the path list delimiter in the source environment value and copy it */
964  if (Delimiter != UNICODE_NULL)
965  {
966  *SourcePtr = Delimiter;
967  *DestPtr++ = *SourcePtr++;
968  }
969  }
970  } while (*SourcePtr != UNICODE_NULL);
971 
972  /* Copy the NULL terminator */
973  *DestPtr++ = *SourcePtr++;
974  }
975  }
976 
977  /* NULL-terminate the environment block */
978  *DestPtr++ = UNICODE_NULL;
979 
980  /* Initialize the Unicode string to hold it */
981  RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment,
982  (DestPtr - NewEnvironment) * sizeof(WCHAR));
983  UnicodeEnv->Length = UnicodeEnv->MaximumLength;
984 
985  /* Create its ANSI version */
986  Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE);
987  if (!NT_SUCCESS(Status))
988  {
989  /* Set last error if conversion failure */
990  BaseSetLastNTError(Status);
991  }
992  else
993  {
994  /* Everything went okay, so return success */
995  Success = TRUE;
996  NewEnvironment = NULL;
997  }
998 
999 Cleanup:
1000  /* Cleanup path starts here, start by destroying the environment copy */
1001  if (!lpEnvironment && Environment) RtlDestroyEnvironment(Environment);
1002 
1003  /* See if we are here due to failure */
1004  if (NewEnvironment)
1005  {
1006  /* Initialize the paths to be empty */
1007  RtlInitEmptyUnicodeString(UnicodeEnv, NULL, 0);
1008  RtlInitEmptyAnsiString(AnsiEnv, NULL, 0);
1009 
1010  /* Free the environment copy */
1011  RegionSize = 0;
1013  (PVOID*)&NewEnvironment,
1014  &RegionSize,
1015  MEM_RELEASE);
1016  ASSERT(NT_SUCCESS(Status));
1017  }
1018 
1019  /* Return the result */
1020  return Success;
1021 }
1022 
1023 BOOL
1024 NTAPI
1026  IN PUNICODE_STRING UnicodeEnv)
1027 {
1028  ULONG Dummy = 0;
1029 
1030  /* Clear the ANSI buffer since Rtl creates this for us */
1031  if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv);
1032 
1033  /* The Unicode buffer is build by hand, though */
1034  if (UnicodeEnv->Buffer)
1035  {
1036  /* So clear it through the API */
1038  (PVOID*)&UnicodeEnv->Buffer,
1039  &Dummy,
1040  MEM_RELEASE);
1041  }
1042 
1043  /* All done */
1044  return TRUE;
1045 }
1046 
1047 
1048 /* Check whether a file is an OS/2 or a very old Windows executable
1049  * by testing on import of KERNEL.
1050  *
1051  * FIXME: is reading the module imports the only way of discerning
1052  * old Windows binaries from OS/2 ones ? At least it seems so...
1053  */
1054 static DWORD WINAPI
1056 {
1057  DWORD CurPos;
1058  LPWORD modtab = NULL;
1059  LPSTR nametab = NULL;
1060  DWORD Read, Ret;
1061  int i;
1062 
1063  Ret = BINARY_OS216;
1064  CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1065 
1066  /* read modref table */
1068  (!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
1069  (!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
1070  (Read != (DWORD)ne->ne_cmod * sizeof(WORD)))
1071  {
1072  goto broken;
1073  }
1074 
1075  /* read imported names table */
1077  (!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
1078  (!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
1079  (Read != (DWORD)ne->ne_enttab - ne->ne_imptab))
1080  {
1081  goto broken;
1082  }
1083 
1084  for(i = 0; i < ne->ne_cmod; i++)
1085  {
1086  LPSTR module;
1087  module = &nametab[modtab[i]];
1088  if(!strncmp(&module[1], "KERNEL", module[0]))
1089  {
1090  /* very old windows file */
1091  Ret = BINARY_WIN16;
1092  goto done;
1093  }
1094  }
1095 
1096  broken:
1097  DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
1098 
1099  done:
1100  HeapFree(GetProcessHeap(), 0, modtab);
1101  HeapFree(GetProcessHeap(), 0, nametab);
1102  SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
1103  return Ret;
1104 }
1105 
1106 static DWORD WINAPI
1108 {
1109  union
1110  {
1111  struct
1112  {
1113  unsigned char magic[4];
1114  unsigned char ignored[12];
1115  unsigned short type;
1116  } elf;
1117  struct
1118  {
1119  unsigned long magic;
1120  unsigned long cputype;
1121  unsigned long cpusubtype;
1122  unsigned long filetype;
1123  } macho;
1124  IMAGE_DOS_HEADER mz;
1125  } Header;
1126  char magic[4];
1127  DWORD Read;
1128 
1130  (!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
1131  (Read != sizeof(Header))))
1132  {
1133  return BINARY_UNKNOWN;
1134  }
1135 
1136  if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
1137  {
1138  /* FIXME: we don't bother to check byte order, architecture, etc. */
1139  switch(Header.elf.type)
1140  {
1141  case 2:
1142  return BINARY_UNIX_EXE;
1143  case 3:
1144  return BINARY_UNIX_LIB;
1145  }
1146  return BINARY_UNKNOWN;
1147  }
1148 
1149  /* Mach-o File with Endian set to Big Endian or Little Endian*/
1150  if(Header.macho.magic == 0xFEEDFACE ||
1151  Header.macho.magic == 0xCEFAEDFE)
1152  {
1153  switch(Header.macho.filetype)
1154  {
1155  case 0x8:
1156  /* MH_BUNDLE */
1157  return BINARY_UNIX_LIB;
1158  }
1159  return BINARY_UNKNOWN;
1160  }
1161 
1162  /* Not ELF, try DOS */
1163  if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
1164  {
1165  /* We do have a DOS image so we will now try to seek into
1166  * the file by the amount indicated by the field
1167  * "Offset to extended header" and read in the
1168  * "magic" field information at that location.
1169  * This will tell us if there is more header information
1170  * to read or not.
1171  */
1172  if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
1173  (!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
1174  (Read != sizeof(magic))))
1175  {
1176  return BINARY_DOS;
1177  }
1178 
1179  /* Reading the magic field succeeded so
1180  * we will try to determine what type it is.
1181  */
1182  if(!memcmp(magic, "PE\0\0", sizeof(magic)))
1183  {
1184  IMAGE_FILE_HEADER FileHeader;
1185  if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
1186  (Read != sizeof(IMAGE_FILE_HEADER)))
1187  {
1188  return BINARY_DOS;
1189  }
1190 
1191  /* FIXME - detect 32/64 bit */
1192 
1193  if(FileHeader.Characteristics & IMAGE_FILE_DLL)
1194  return BINARY_PE_DLL32;
1195  return BINARY_PE_EXE32;
1196  }
1197 
1198  if(!memcmp(magic, "NE", 2))
1199  {
1200  /* This is a Windows executable (NE) header. This can
1201  * mean either a 16-bit OS/2 or a 16-bit Windows or even a
1202  * DOS program (running under a DOS extender). To decide
1203  * which, we'll have to read the NE header.
1204  */
1205  IMAGE_OS2_HEADER ne;
1206  if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
1207  !ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
1208  (Read != sizeof(IMAGE_OS2_HEADER)))
1209  {
1210  /* Couldn't read header, so abort. */
1211  return BINARY_DOS;
1212  }
1213 
1214  switch(ne.ne_exetyp)
1215  {
1216  case 2:
1217  return BINARY_WIN16;
1218  case 5:
1219  return BINARY_DOS;
1220  default:
1221  return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
1222  }
1223  }
1224  return BINARY_DOS;
1225  }
1226  return BINARY_UNKNOWN;
1227 }
1228 
1229 /*
1230  * @implemented
1231  */
1232 BOOL
1233 WINAPI
1235  LPCWSTR lpApplicationName,
1236  LPDWORD lpBinaryType
1237  )
1238 {
1239  HANDLE hFile;
1240  DWORD BinType;
1241 
1242  if(!lpApplicationName || !lpBinaryType)
1243  {
1245  return FALSE;
1246  }
1247 
1248  hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
1249  OPEN_EXISTING, 0, 0);
1250  if(hFile == INVALID_HANDLE_VALUE)
1251  {
1252  return FALSE;
1253  }
1254 
1255  BinType = InternalGetBinaryType(hFile);
1256  CloseHandle(hFile);
1257 
1258  switch(BinType)
1259  {
1260  case BINARY_UNKNOWN:
1261  {
1262  WCHAR *dot;
1263 
1264  /*
1265  * guess from filename
1266  */
1267  if(!(dot = wcsrchr(lpApplicationName, L'.')))
1268  {
1269  return FALSE;
1270  }
1271  if(!lstrcmpiW(dot, L".COM"))
1272  {
1273  *lpBinaryType = SCS_DOS_BINARY;
1274  return TRUE;
1275  }
1276  if(!lstrcmpiW(dot, L".PIF"))
1277  {
1278  *lpBinaryType = SCS_PIF_BINARY;
1279  return TRUE;
1280  }
1281  return FALSE;
1282  }
1283  case BINARY_PE_EXE32:
1284  case BINARY_PE_DLL32:
1285  {
1286  *lpBinaryType = SCS_32BIT_BINARY;
1287  return TRUE;
1288  }
1289  case BINARY_PE_EXE64:
1290  case BINARY_PE_DLL64:
1291  {
1292  *lpBinaryType = SCS_64BIT_BINARY;
1293  return TRUE;
1294  }
1295  case BINARY_WIN16:
1296  {
1297  *lpBinaryType = SCS_WOW_BINARY;
1298  return TRUE;
1299  }
1300  case BINARY_OS216:
1301  {
1302  *lpBinaryType = SCS_OS216_BINARY;
1303  return TRUE;
1304  }
1305  case BINARY_DOS:
1306  {
1307  *lpBinaryType = SCS_DOS_BINARY;
1308  return TRUE;
1309  }
1310  case BINARY_UNIX_EXE:
1311  case BINARY_UNIX_LIB:
1312  {
1313  return FALSE;
1314  }
1315  }
1316 
1317  DPRINT1("Invalid binary type %lu returned!\n", BinType);
1318  return FALSE;
1319 }
1320 
1321 /*
1322  * @implemented
1323  */
1324 BOOL
1325 WINAPI
1326 GetBinaryTypeA(IN LPCSTR lpApplicationName,
1327  OUT LPDWORD lpBinaryType)
1328 {
1329  ANSI_STRING ApplicationNameString;
1330  UNICODE_STRING ApplicationNameW;
1331  BOOL StringAllocated = FALSE, Result;
1332  NTSTATUS Status;
1333 
1334  RtlInitAnsiString(&ApplicationNameString, lpApplicationName);
1335 
1336  if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength)
1337  {
1338  StringAllocated = TRUE;
1339  Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE);
1340  }
1341  else
1342  {
1343  Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE);
1344  }
1345 
1346  if (!NT_SUCCESS(Status))
1347  {
1348  BaseSetLastNTError(Status);
1349  return FALSE;
1350  }
1351 
1352  if (StringAllocated)
1353  {
1354  Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType);
1355  RtlFreeUnicodeString(&ApplicationNameW);
1356  }
1357  else
1358  {
1359  Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
1360  }
1361 
1362  return Result;
1363 }
1364 
1365 /*
1366  * @unimplemented
1367  */
1368 BOOL
1369 WINAPI
1371  DWORD Unknown
1372  )
1373 {
1374  STUB;
1375  return FALSE;
1376 }
1377 
1378 /*
1379  * @implemented
1380  */
1381 VOID
1382 WINAPI
1383 ExitVDM(BOOL IsWow, ULONG iWowTask)
1384 {
1385  BASE_API_MESSAGE ApiMessage;
1386  PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest;
1387 
1388  /* Setup the input parameters */
1389  ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1390  ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */
1391  ExitVdm->WaitObjectForVDM = NULL;
1392 
1393  /* Call CSRSS */
1395  NULL,
1397  sizeof(*ExitVdm));
1398 
1399  /* Close the returned wait object handle, if any */
1400  if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL))
1401  {
1402  CloseHandle(ExitVdm->WaitObjectForVDM);
1403  }
1404 }
1405 
1406 /*
1407  * @implemented
1408  */
1409 BOOL
1410 WINAPI
1412 {
1413  BOOL Success = FALSE;
1414  NTSTATUS Status;
1415  BASE_API_MESSAGE ApiMessage;
1416  PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest;
1417  PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest;
1418  PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
1419  PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
1420  ULONG NumStrings = 0;
1421 
1422  /*
1423  * Special case to test whether the VDM is the first one.
1424  */
1425  if (CommandData == NULL)
1426  {
1427  /* Call CSRSS */
1429  NULL,
1431  sizeof(*IsFirstVdm));
1432  if (!NT_SUCCESS(ApiMessage.Status))
1433  {
1434  BaseSetLastNTError(ApiMessage.Status);
1435  return FALSE;
1436  }
1437 
1438  /* Return TRUE if this is the first VDM */
1439  return IsFirstVdm->FirstVDM;
1440  }
1441 
1442  /* CommandData != NULL */
1443 
1444  /*
1445  * Special case to increment or decrement the reentrancy count.
1446  */
1447  if ((CommandData->VDMState == VDM_INC_REENTER_COUNT) ||
1448  (CommandData->VDMState == VDM_DEC_REENTER_COUNT))
1449  {
1450  /* Setup the input parameters */
1451  SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1452  SetReenterCount->fIncDec = CommandData->VDMState;
1453 
1454  /* Call CSRSS */
1456  NULL,
1458  sizeof(*SetReenterCount));
1459  if (!NT_SUCCESS(ApiMessage.Status))
1460  {
1461  BaseSetLastNTError(ApiMessage.Status);
1462  return FALSE;
1463  }
1464 
1465  return TRUE;
1466  }
1467 
1468  /*
1469  * TODO!
1470  * Special case to retrieve or set WOW information.
1471  */
1472  // TODO: if CommandData->VDMState & (VDM_LIST_WOW_PROCESSES | VDM_LIST_WOW_TASKS | VDM_ADD_WOW_TASK)
1473  // then call BasepGetNextVDMCommand in a simpler way!
1474 
1475  /*
1476  * Regular case.
1477  */
1478 
1479  /* Clear the structure */
1480  RtlZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand));
1481 
1482  /* Setup the input parameters */
1483  GetNextVdmCommand->iTask = CommandData->TaskId;
1484  GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1485  GetNextVdmCommand->CmdLen = CommandData->CmdLen;
1486  GetNextVdmCommand->AppLen = CommandData->AppLen;
1487  GetNextVdmCommand->PifLen = CommandData->PifLen;
1488  GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen;
1489  GetNextVdmCommand->EnvLen = CommandData->EnvLen;
1490  GetNextVdmCommand->DesktopLen = CommandData->DesktopLen;
1491  GetNextVdmCommand->TitleLen = CommandData->TitleLen;
1492  GetNextVdmCommand->ReservedLen = CommandData->ReservedLen;
1493  GetNextVdmCommand->VDMState = CommandData->VDMState;
1494 
1495  /* Count the number of strings */
1496  if (CommandData->CmdLen) NumStrings++;
1497  if (CommandData->AppLen) NumStrings++;
1498  if (CommandData->PifLen) NumStrings++;
1499  if (CommandData->CurDirectoryLen) NumStrings++;
1500  if (CommandData->EnvLen) NumStrings++;
1501  if (CommandData->DesktopLen) NumStrings++;
1502  if (CommandData->TitleLen) NumStrings++;
1503  if (CommandData->ReservedLen) NumStrings++;
1504 
1505  /* Allocate the capture buffer */
1506  CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1,
1507  GetNextVdmCommand->CmdLen
1508  + GetNextVdmCommand->AppLen
1509  + GetNextVdmCommand->PifLen
1510  + GetNextVdmCommand->CurDirectoryLen
1511  + GetNextVdmCommand->EnvLen
1512  + GetNextVdmCommand->DesktopLen
1513  + GetNextVdmCommand->TitleLen
1514  + GetNextVdmCommand->ReservedLen
1515  + sizeof(*GetNextVdmCommand->StartupInfo));
1516  if (CaptureBuffer == NULL)
1517  {
1519  goto Cleanup;
1520  }
1521 
1522  /* Capture the data */
1523 
1524  CsrAllocateMessagePointer(CaptureBuffer,
1525  sizeof(*GetNextVdmCommand->StartupInfo),
1526  (PVOID*)&GetNextVdmCommand->StartupInfo);
1527 
1528  if (CommandData->CmdLen)
1529  {
1530  CsrAllocateMessagePointer(CaptureBuffer,
1531  CommandData->CmdLen,
1532  (PVOID*)&GetNextVdmCommand->CmdLine);
1533  }
1534 
1535  if (CommandData->AppLen)
1536  {
1537  CsrAllocateMessagePointer(CaptureBuffer,
1538  CommandData->AppLen,
1539  (PVOID*)&GetNextVdmCommand->AppName);
1540  }
1541 
1542  if (CommandData->PifLen)
1543  {
1544  CsrAllocateMessagePointer(CaptureBuffer,
1545  CommandData->PifLen,
1546  (PVOID*)&GetNextVdmCommand->PifFile);
1547  }
1548 
1549  if (CommandData->CurDirectoryLen)
1550  {
1551  CsrAllocateMessagePointer(CaptureBuffer,
1552  CommandData->CurDirectoryLen,
1553  (PVOID*)&GetNextVdmCommand->CurDirectory);
1554  }
1555 
1556  if (CommandData->EnvLen)
1557  {
1558  CsrAllocateMessagePointer(CaptureBuffer,
1559  CommandData->EnvLen,
1560  (PVOID*)&GetNextVdmCommand->Env);
1561  }
1562 
1563  if (CommandData->DesktopLen)
1564  {
1565  CsrAllocateMessagePointer(CaptureBuffer,
1566  CommandData->DesktopLen,
1567  (PVOID*)&GetNextVdmCommand->Desktop);
1568  }
1569 
1570  if (CommandData->TitleLen)
1571  {
1572  CsrAllocateMessagePointer(CaptureBuffer,
1573  CommandData->TitleLen,
1574  (PVOID*)&GetNextVdmCommand->Title);
1575  }
1576 
1577  if (CommandData->ReservedLen)
1578  {
1579  CsrAllocateMessagePointer(CaptureBuffer,
1580  CommandData->ReservedLen,
1581  (PVOID*)&GetNextVdmCommand->Reserved);
1582  }
1583 
1584  while (TRUE)
1585  {
1586  /* Call CSRSS */
1587  Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1588  CaptureBuffer,
1590  sizeof(*GetNextVdmCommand));
1591 
1592  /* Exit the waiting loop if we did not receive any event handle */
1593  if (GetNextVdmCommand->WaitObjectForVDM == NULL)
1594  break;
1595 
1596  /* Wait for the event to become signaled and try again */
1597  Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM,
1598  FALSE, NULL);
1599  if (Status != STATUS_SUCCESS)
1600  {
1601  /* Fail if we timed out, or if some other error happened */
1602  BaseSetLastNTError(Status);
1603  goto Cleanup;
1604  }
1605 
1606  /* Set the retry flag, clear the exit code, and retry a query */
1607  GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
1608  GetNextVdmCommand->ExitCode = 0;
1609  }
1610 
1611  if (!NT_SUCCESS(Status))
1612  {
1613  if (Status == STATUS_INVALID_PARAMETER)
1614  {
1615  /*
1616  * One of the buffer lengths was less than required. Store the correct ones.
1617  * Note that the status code is not STATUS_BUFFER_TOO_SMALL as one would expect,
1618  * in order to keep compatibility with Windows 2003 BASESRV.DLL.
1619  */
1620  CommandData->CmdLen = GetNextVdmCommand->CmdLen;
1621  CommandData->AppLen = GetNextVdmCommand->AppLen;
1622  CommandData->PifLen = GetNextVdmCommand->PifLen;
1623  CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
1624  CommandData->EnvLen = GetNextVdmCommand->EnvLen;
1625  CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
1626  CommandData->TitleLen = GetNextVdmCommand->TitleLen;
1627  CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
1628  }
1629  else
1630  {
1631  /* Any other failure */
1632  CommandData->CmdLen = 0;
1633  CommandData->AppLen = 0;
1634  CommandData->PifLen = 0;
1635  CommandData->CurDirectoryLen = 0;
1636  CommandData->EnvLen = 0;
1637  CommandData->DesktopLen = 0;
1638  CommandData->TitleLen = 0;
1639  CommandData->ReservedLen = 0;
1640  }
1641 
1642  BaseSetLastNTError(Status);
1643  goto Cleanup;
1644  }
1645 
1646  /* Write back the standard handles */
1647  CommandData->StdIn = GetNextVdmCommand->StdIn;
1648  CommandData->StdOut = GetNextVdmCommand->StdOut;
1649  CommandData->StdErr = GetNextVdmCommand->StdErr;
1650 
1651  /* Write back the startup info */
1652  RtlMoveMemory(&CommandData->StartupInfo,
1653  GetNextVdmCommand->StartupInfo,
1654  sizeof(*GetNextVdmCommand->StartupInfo));
1655 
1656  if (CommandData->CmdLen)
1657  {
1658  /* Write back the command line */
1659  RtlMoveMemory(CommandData->CmdLine,
1660  GetNextVdmCommand->CmdLine,
1661  GetNextVdmCommand->CmdLen);
1662 
1663  /* Set the actual length */
1664  CommandData->CmdLen = GetNextVdmCommand->CmdLen;
1665  }
1666 
1667  if (CommandData->AppLen)
1668  {
1669  /* Write back the application name */
1670  RtlMoveMemory(CommandData->AppName,
1671  GetNextVdmCommand->AppName,
1672  GetNextVdmCommand->AppLen);
1673 
1674  /* Set the actual length */
1675  CommandData->AppLen = GetNextVdmCommand->AppLen;
1676  }
1677 
1678  if (CommandData->PifLen)
1679  {
1680  /* Write back the PIF file name */
1681  RtlMoveMemory(CommandData->PifFile,
1682  GetNextVdmCommand->PifFile,
1683  GetNextVdmCommand->PifLen);
1684 
1685  /* Set the actual length */
1686  CommandData->PifLen = GetNextVdmCommand->PifLen;
1687  }
1688 
1689  if (CommandData->CurDirectoryLen)
1690  {
1691  /* Write back the current directory */
1692  RtlMoveMemory(CommandData->CurDirectory,
1693  GetNextVdmCommand->CurDirectory,
1694  GetNextVdmCommand->CurDirectoryLen);
1695 
1696  /* Set the actual length */
1697  CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
1698  }
1699 
1700  if (CommandData->EnvLen)
1701  {
1702  /* Write back the environment */
1703  RtlMoveMemory(CommandData->Env,
1704  GetNextVdmCommand->Env,
1705  GetNextVdmCommand->EnvLen);
1706 
1707  /* Set the actual length */
1708  CommandData->EnvLen = GetNextVdmCommand->EnvLen;
1709  }
1710 
1711  if (CommandData->DesktopLen)
1712  {
1713  /* Write back the desktop name */
1714  RtlMoveMemory(CommandData->Desktop,
1715  GetNextVdmCommand->Desktop,
1716  GetNextVdmCommand->DesktopLen);
1717 
1718  /* Set the actual length */
1719  CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
1720  }
1721 
1722  if (CommandData->TitleLen)
1723  {
1724  /* Write back the title */
1725  RtlMoveMemory(CommandData->Title,
1726  GetNextVdmCommand->Title,
1727  GetNextVdmCommand->TitleLen);
1728 
1729  /* Set the actual length */
1730  CommandData->TitleLen = GetNextVdmCommand->TitleLen;
1731  }
1732 
1733  if (CommandData->ReservedLen)
1734  {
1735  /* Write back the reserved parameter */
1736  RtlMoveMemory(CommandData->Reserved,
1737  GetNextVdmCommand->Reserved,
1738  GetNextVdmCommand->ReservedLen);
1739 
1740  /* Set the actual length */
1741  CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
1742  }
1743 
1744  /* Write the remaining output parameters */
1745  CommandData->TaskId = GetNextVdmCommand->iTask;
1746  CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags;
1747  CommandData->CodePage = GetNextVdmCommand->CodePage;
1748  CommandData->ExitCode = GetNextVdmCommand->ExitCode;
1749  CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive;
1750  CommandData->VDMState = GetNextVdmCommand->VDMState;
1751  CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat;
1752 
1753  /* It was successful */
1754  Success = TRUE;
1755 
1756 Cleanup:
1757  if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer);
1758  return Success;
1759 }
1760 
1761 
1762 /*
1763  * @implemented
1764  */
1765 DWORD
1766 WINAPI
1767 GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
1768 {
1769  BASE_API_MESSAGE ApiMessage;
1770  PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
1771  PCSR_CAPTURE_BUFFER CaptureBuffer;
1772 
1773  /* Allocate the capture buffer */
1774  CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
1775  if (CaptureBuffer == NULL)
1776  {
1778  return 0;
1779  }
1780 
1781  /* Setup the input parameters */
1782  VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
1783  CsrAllocateMessagePointer(CaptureBuffer,
1784  cchCurDirs,
1785  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
1786 
1787  /* Call CSRSS */
1789  CaptureBuffer,
1791  sizeof(*VDMCurrentDirsRequest));
1792 
1793  /* Set the last error */
1794  BaseSetLastNTError(ApiMessage.Status);
1795 
1796  if (NT_SUCCESS(ApiMessage.Status))
1797  {
1798  /* Copy the result */
1799  RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs);
1800  }
1801 
1802  /* Free the capture buffer */
1803  CsrFreeCaptureBuffer(CaptureBuffer);
1804 
1805  /* Return the size if it was successful, or if the buffer was too small */
1806  return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL))
1807  ? VDMCurrentDirsRequest->cchCurDirs : 0;
1808 }
1809 
1810 
1811 /*
1812  * @implemented (undocumented)
1813  */
1814 BOOL
1815 WINAPI
1816 RegisterConsoleVDM(IN DWORD dwRegisterFlags,
1817  IN HANDLE hStartHardwareEvent,
1818  IN HANDLE hEndHardwareEvent,
1819  IN HANDLE hErrorHardwareEvent,
1820  IN DWORD dwUnusedVar,
1821  OUT LPDWORD lpVideoStateLength,
1822  OUT PVOID* lpVideoState, // PVIDEO_HARDWARE_STATE_HEADER*
1823  IN PVOID lpUnusedBuffer,
1824  IN DWORD dwUnusedBufferLength,
1825  IN COORD dwVDMBufferSize,
1826  OUT PVOID* lpVDMBuffer)
1827 {
1828  BOOL Success;
1829  CONSOLE_API_MESSAGE ApiMessage;
1830  PCONSOLE_REGISTERVDM RegisterVDMRequest = &ApiMessage.Data.RegisterVDMRequest;
1831  PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
1832 
1833  /* Set up the data to send to the Console Server */
1834  RegisterVDMRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1835  RegisterVDMRequest->RegisterFlags = dwRegisterFlags;
1836 
1837  if (dwRegisterFlags != 0)
1838  {
1839  RegisterVDMRequest->StartHardwareEvent = hStartHardwareEvent;
1840  RegisterVDMRequest->EndHardwareEvent = hEndHardwareEvent;
1841  RegisterVDMRequest->ErrorHardwareEvent = hErrorHardwareEvent;
1842 
1843  RegisterVDMRequest->VDMBufferSize = dwVDMBufferSize;
1844 
1845 #if 0
1846  RegisterVDMRequest->UnusedBufferLength = dwUnusedBufferLength;
1847 
1848  /* Allocate a Capture Buffer */
1849  CaptureBuffer = CsrAllocateCaptureBuffer(1, dwUnusedBufferLength);
1850  if (CaptureBuffer == NULL)
1851  {
1852  DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1854  return FALSE;
1855  }
1856 
1857  /* Capture the buffer to write */
1858  CsrCaptureMessageBuffer(CaptureBuffer,
1859  (PVOID)lpUnusedBuffer,
1860  dwUnusedBufferLength,
1861  (PVOID*)&RegisterVDMRequest->UnusedBuffer);
1862 #endif
1863  }
1864  else
1865  {
1866  // CaptureBuffer = NULL;
1867  }
1868 
1869  /* Call the server */
1871  CaptureBuffer,
1873  sizeof(*RegisterVDMRequest));
1874 
1875  /* Check for success */
1876  Success = NT_SUCCESS(ApiMessage.Status);
1877 
1878  /* Release the capture buffer if needed */
1879  if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1880 
1881  /* Retrieve the results */
1882  if (Success)
1883  {
1884  if (dwRegisterFlags != 0)
1885  {
1886  _SEH2_TRY
1887  {
1888  *lpVideoStateLength = RegisterVDMRequest->VideoStateLength;
1889  *lpVideoState = RegisterVDMRequest->VideoState;
1890  *lpVDMBuffer = RegisterVDMRequest->VDMBuffer;
1891  }
1893  {
1895  Success = FALSE;
1896  }
1897  _SEH2_END;
1898  }
1899  }
1900  else
1901  {
1902  BaseSetLastNTError(ApiMessage.Status);
1903  }
1904 
1905  /* Return success status */
1906  return Success;
1907 }
1908 
1909 
1910 /*
1911  * @unimplemented
1912  */
1913 BOOL
1914 WINAPI
1916  DWORD Unknown0
1917  )
1918 {
1919  STUB;
1920  return FALSE;
1921 }
1922 
1923 
1924 /*
1925  * @unimplemented
1926  */
1927 BOOL
1928 WINAPI
1930  DWORD Unknown0
1931  )
1932 {
1933  STUB;
1934  return FALSE;
1935 }
1936 
1937 
1938 /*
1939  * @implemented
1940  */
1941 BOOL
1942 WINAPI
1943 SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
1944 {
1945  BASE_API_MESSAGE ApiMessage;
1946  PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
1947  PCSR_CAPTURE_BUFFER CaptureBuffer;
1948 
1949  /* Allocate the capture buffer */
1950  CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
1951  if (CaptureBuffer == NULL)
1952  {
1954  return FALSE;
1955  }
1956 
1957  /* Setup the input parameters */
1958  VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
1959  CsrCaptureMessageBuffer(CaptureBuffer,
1960  lpszzCurDirs,
1961  cchCurDirs,
1962  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
1963 
1964  /* Call CSRSS */
1966  CaptureBuffer,
1968  sizeof(*VDMCurrentDirsRequest));
1969 
1970  /* Free the capture buffer */
1971  CsrFreeCaptureBuffer(CaptureBuffer);
1972 
1973  /* Set the last error */
1974  BaseSetLastNTError(ApiMessage.Status);
1975 
1976  return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE;
1977 }
1978 
1979 /*
1980  * @unimplemented
1981  */
1982 DWORD
1983 WINAPI
1985  DWORD Unknown0,
1986  DWORD Unknown1
1987  )
1988 {
1989  STUB;
1990  return 0;
1991 }
1992 
1993 
1994 /*
1995  * @unimplemented
1996  */
1997 BOOL
1998 WINAPI
2000 {
2001  DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
2002 
2004  NULL,
2005  0,
2006  Unknown0);
2007 }
enum _ENV_NAME_TYPE ENV_NAME_TYPE
DWORD *typedef PVOID
Definition: winlogon.h:52
#define SCS_32BIT_BINARY
Definition: winbase.h:231
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
LPSTR Desktop
Definition: vdm.h:84
CONST WCHAR * PCWCH
Definition: ntbasedef.h:410
static UNICODE_STRING BaseDotExeSuffixName
Definition: vdm.c:60
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
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:1999
HANDLE StdOut
Definition: basemsg.h:125
#define IN
Definition: typedefs.h:39
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
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define CloseHandle
Definition: compat.h:398
DWORD WINAPI BaseSetLastNTError(IN NTSTATUS Status)
Definition: except.c:1026
ULONG DesktopLen
Definition: vdm.h:85
#define INVALID_SET_FILE_POINTER
Definition: winbase.h:113
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:785
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
Definition: bidi.c:75
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
#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
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE _In_opt_ PVOID _In_opt_ PVOID Environment
Definition: rtlfuncs.h:3939
HANDLE ConsoleHandle
Definition: conmsg.h:871
#define FILE_CURRENT
Definition: winbase.h:111
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:1025
HMODULE module
Definition: main.cpp:35
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define HandleToUlong(h)
Definition: basetsd.h:78
#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)
#define TRUE
Definition: numbers.c:17
PCHAR CurDirectory
Definition: basemsg.h:132
u32_t magic(void)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ARRAYSIZE(array)
Definition: filtermapper.c:28
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:1055
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1041
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:234
SIZE_T LPSTARTUPINFOW
Definition: cordebug.idl:85
USHORT PifLen
Definition: basemsg.h:144
#define SCS_64BIT_BINARY
Definition: winbase.h:232
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:55
_CRTIMP int __cdecl _snwprintf(wchar_t *_Dest, size_t _Count, const wchar_t *_Format,...)
BASE_EXIT_VDM ExitVDMRequest
Definition: basemsg.h:290
USHORT CmdLen
Definition: vdm.h:90
VOID WINAPI ExitVDM(BOOL IsWow, ULONG iWowTask)
Definition: vdm.c:1383
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:1234
DWORD DWORD
Definition: winlogon.h:75
#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:264
union _BASE_API_MESSAGE::@2988 Data
#define BINARY_UNIX_LIB
Definition: vdm.c:27
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:1767
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:233
VOID NTAPI CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer, IN PVOID MessageBuffer OPTIONAL, IN ULONG MessageLength, OUT PVOID *CapturedData)
Definition: capture.c:169
#define STATUS_BUFFER_TOO_SMALL
Definition: udferr_usr.h:146
static HANDLE hUserToken
Definition: umpnpmgr.c:66
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp: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:4732
BASE_IS_FIRST_VDM IsFirstVDMRequest
Definition: basemsg.h:291
#define _SEH2_END
Definition: pseh2_64.h:7
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:1816
HANDLE StdErr
Definition: basemsg.h:126
#define SCS_PIF_BINARY
Definition: winbase.h:235
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
HANDLE StdIn
Definition: vdm.h:74
#define SCS_WOW_BINARY
Definition: winbase.h:237
smooth NULL
Definition: ftsmooth.c:464
#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:1943
#define BINARY_OS216
Definition: vdm.c:24
DWORD WINAPI VDMConsoleOperation(DWORD Unknown0, DWORD Unknown1)
Definition: vdm.c:1984
#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:783
#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
union _CONSOLE_API_MESSAGE::@2990 Data
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 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:471
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
#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
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:1370
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
PCHAR PifFile
Definition: basemsg.h:131
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1326
HANDLE StdIn
Definition: basemsg.h:124
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
VOID UINTN Length
Definition: acefiex.h:718
Definition: vdm.c:37
static ENV_INFO BasepEnvNameType[]
Definition: vdm.c:49
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:411
BOOL WINAPI RegisterWowExec(DWORD Unknown0)
Definition: vdm.c:1929
#define ERROR_INVALID_ACCESS
Definition: winerror.h:115
#define GENERIC_READ
Definition: compat.h:124
static const WCHAR Cleanup[]
Definition: register.c:65
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:135
_In_ HANDLE hFile
Definition: mswsock.h:90
BOOL WINAPI RegisterWowBaseHandlers(DWORD Unknown0)
Definition: vdm.c:1915
#define WINAPI
Definition: msvc.h:20
Definition: bl.h:1258
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:55
USHORT EntryIndex
Definition: basemsg.h:157
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
#define FILE_BEGIN
Definition: winbase.h:110
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:52
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
LONG NTSTATUS
Definition: DriverTester.h:11
LPSTR lpDesktop
Definition: winbase.h:784
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
#define _SEH2_TRY
Definition: pseh2_64.h:5
static DWORD WINAPI InternalGetBinaryType(HANDLE hFile)
Definition: vdm.c:1107
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
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
signed char * PCHAR
Definition: retypes.h:7
#define OUT
Definition: typedefs.h:40
#define FALSE
Definition: numbers.c:16
uint32_t * LPDWORD
Definition: typedefs.h:58
unsigned int ULONG
Definition: retypes.h:1
ULONG CodePage
Definition: basemsg.h:127
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#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:643
PCHAR Reserved
Definition: basemsg.h:140
struct _ENV_INFO ENV_INFO
BOOL WINAPI GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
Definition: vdm.c:1411
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:5089
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)