ReactOS  0.4.15-dev-2985-g54406bf
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? */
73  String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
75 
76  /* Is it a .pif? */
78  String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
80 
81  /* Is it an exe? */
83  String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
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  SIZE_T Length;
109  PCHAR AnsiCmdLine = NULL;
110  PCHAR AnsiAppName = NULL;
111  PCHAR AnsiCurDirectory = NULL;
112  PCHAR AnsiDesktop = NULL;
113  PCHAR AnsiTitle = NULL;
114  PCHAR AnsiReserved = NULL;
115  STARTUPINFOA AnsiStartupInfo;
116  ULONG NumStrings = 5;
117 
118  /* Parameters validation */
119  if (ApplicationName == NULL || CommandLine == NULL)
120  {
122  }
123 
124  /* Trim leading whitespace from ApplicationName */
125  while (*ApplicationName == L' ' || *ApplicationName == L'\t')
126  ++ApplicationName;
127 
128  /* Calculate the size of the short application name */
130  if (Length == 0)
131  {
133  goto Cleanup;
134  }
135 
136  /* Allocate memory for the short application name */
137  ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
139  Length * sizeof(WCHAR));
140  if (!ShortAppName)
141  {
143  goto Cleanup;
144  }
145 
146  /* Get the short application name */
147  if (GetShortPathNameW(ApplicationName, ShortAppName, Length) == 0)
148  {
149  /* Try to determine which error occurred */
150  switch (GetLastError())
151  {
153  {
155  break;
156  }
157 
159  {
161  break;
162  }
163 
164  default:
165  {
167  }
168  }
169 
170  goto Cleanup;
171  }
172 
173  /* Trim leading whitespace from CommandLine */
174  while (*CommandLine == L' ' || *CommandLine == L'\t')
175  ++CommandLine;
176 
177  /*
178  * CommandLine is usually formatted as: 'ApplicationName param0 ...'.
179  * So we want to strip the first token (ApplicationName) from it.
180  * Two cases are in fact possible:
181  * - either the first token is indeed ApplicationName, so we just skip it;
182  * - or the first token is not exactly ApplicationName, because it happened
183  * that somebody else already preprocessed CommandLine. Therefore we
184  * suppose that the first token corresponds to an application name and
185  * we skip it. Care should be taken when quotes are present in this token.
186  */
187  if (*CommandLine)
188  {
189  /* The first part of CommandLine should be the ApplicationName... */
191  if (Length <= wcslen(CommandLine) &&
192  _wcsnicmp(ApplicationName, CommandLine, Length) == 0)
193  {
194  /* Skip it */
195  CommandLine += Length;
196  }
197  /*
198  * ... but it is not, however we still have a token. We suppose that
199  * it corresponds to some sort of application name, so we skip it too.
200  */
201  else
202  {
203  /* Get rid of the first token. We stop when we see whitespace. */
204  while (*CommandLine && !(*CommandLine == L' ' || *CommandLine == L'\t'))
205  {
206  if (*CommandLine == L'\"')
207  {
208  /* We enter a quoted part, skip it */
209  ++CommandLine;
210  while (*CommandLine && *CommandLine++ != L'\"') ;
211  }
212  else
213  {
214  /* Go to the next character */
215  ++CommandLine;
216  }
217  }
218  }
219  }
220 
221  /*
222  * Trim remaining whitespace from CommandLine that may be
223  * present between the application name and the parameters.
224  */
225  while (*CommandLine == L' ' || *CommandLine == L'\t')
226  ++CommandLine;
227 
228  /* Get the current directory */
229  if (CurrentDirectory == NULL)
230  {
231  /* Allocate memory for the current directory path */
233  CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
235  Length * sizeof(WCHAR));
236  if (CurrentDir == NULL)
237  {
239  goto Cleanup;
240  }
241 
242  /* Get the current directory */
243  GetCurrentDirectoryW(Length, CurrentDir);
244  CurrentDirectory = CurrentDir;
245  }
246 
247  /* Calculate the size of the short current directory path */
249 
250  /* Allocate memory for the short current directory path */
251  ShortCurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
253  Length * sizeof(WCHAR));
254  if (!ShortCurrentDir)
255  {
257  goto Cleanup;
258  }
259 
260  /* Get the short current directory path */
261  if (!GetShortPathNameW(CurrentDirectory, ShortCurrentDir, Length))
262  {
263  /* Try to determine which error occurred */
264  switch (GetLastError())
265  {
267  {
269  break;
270  }
271 
273  {
275  break;
276  }
277 
278  default:
279  {
281  }
282  }
283  goto Cleanup;
284  }
285 
286  /* Make sure that the command line isn't too long */
287  Length = wcslen(CommandLine);
289  {
291  goto Cleanup;
292  }
293 
294  /* Setup the input parameters */
295  CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
296  CheckVdm->BinaryType = BinaryType;
297  CheckVdm->CodePage = CP_ACP;
298  CheckVdm->dwCreationFlags = CreationFlags;
299  CheckVdm->CurDrive = CurrentDirectory[0] - L'A';
300  CheckVdm->CmdLen = (USHORT)Length + 1;
301  CheckVdm->AppLen = (USHORT)wcslen(ShortAppName) + 1;
302  CheckVdm->PifLen = 0; // TODO: PIF file support!
303  CheckVdm->CurDirectoryLen = (USHORT)wcslen(ShortCurrentDir) + 1;
304  CheckVdm->EnvLen = AnsiEnvironment->Length;
305  CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0;
306  CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0;
307  CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0;
308 
309  if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
310  {
311  /* Set the standard handles */
312  CheckVdm->StdIn = StartupInfo->hStdInput;
313  CheckVdm->StdOut = StartupInfo->hStdOutput;
314  CheckVdm->StdErr = StartupInfo->hStdError;
315  }
316 
317  /* Allocate memory for the ANSI strings */
318  // We need to add the newline characters '\r\n' to the command line
319  AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen + 2);
320  AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
321  AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
322  if (StartupInfo->lpDesktop)
323  AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
325  CheckVdm->DesktopLen);
326  if (StartupInfo->lpTitle)
327  AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
329  CheckVdm->TitleLen);
330  if (StartupInfo->lpReserved)
331  AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
333  CheckVdm->ReservedLen);
334 
335  if (!AnsiCmdLine
336  || !AnsiAppName
337  || !AnsiCurDirectory
338  || (StartupInfo->lpDesktop && !AnsiDesktop)
339  || (StartupInfo->lpTitle && !AnsiTitle)
340  || (StartupInfo->lpReserved && !AnsiReserved))
341  {
343  goto Cleanup;
344  }
345 
346  /* Convert the command line into an ANSI string */
348  0,
349  CommandLine,
350  CheckVdm->CmdLen,
351  AnsiCmdLine,
352  CheckVdm->CmdLen,
353  NULL,
354  NULL);
355  /* Add the needed newline and NULL-terminate */
356  CheckVdm->CmdLen--; // Rewind back to the NULL character
357  AnsiCmdLine[CheckVdm->CmdLen++] = '\r';
358  AnsiCmdLine[CheckVdm->CmdLen++] = '\n';
359  AnsiCmdLine[CheckVdm->CmdLen++] = 0;
360 
361  /* Convert the short application name into an ANSI string */
363  0,
364  ShortAppName,
365  CheckVdm->AppLen,
366  AnsiAppName,
367  CheckVdm->AppLen,
368  NULL,
369  NULL);
370 
371  /* Convert the short current directory path into an ANSI string */
373  0,
374  ShortCurrentDir,
375  CheckVdm->CurDirectoryLen,
376  AnsiCurDirectory,
377  CheckVdm->CurDirectoryLen,
378  NULL,
379  NULL);
380 
381  if (StartupInfo->lpDesktop)
382  {
383  /* Convert the desktop name into an ANSI string */
385  0,
386  StartupInfo->lpDesktop,
387  CheckVdm->DesktopLen,
388  AnsiDesktop,
389  CheckVdm->DesktopLen,
390  NULL,
391  NULL);
392  NumStrings++;
393  }
394 
395  if (StartupInfo->lpTitle)
396  {
397  /* Convert the title into an ANSI string */
399  0,
400  StartupInfo->lpTitle,
401  CheckVdm->TitleLen,
402  AnsiTitle,
403  CheckVdm->TitleLen,
404  NULL,
405  NULL);
406  NumStrings++;
407  }
408 
409  if (StartupInfo->lpReserved)
410  {
411  /* Convert the reserved value into an ANSI string */
413  0,
414  StartupInfo->lpReserved,
415  CheckVdm->ReservedLen,
416  AnsiReserved,
417  CheckVdm->ReservedLen,
418  NULL,
419  NULL);
420  NumStrings++;
421  }
422 
423  /* Fill the ANSI startup info structure */
424  RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(AnsiStartupInfo));
425  AnsiStartupInfo.lpReserved = AnsiReserved;
426  AnsiStartupInfo.lpDesktop = AnsiDesktop;
427  AnsiStartupInfo.lpTitle = AnsiTitle;
428 
429  /* Allocate the capture buffer */
430  CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings,
431  CheckVdm->CmdLen
432  + CheckVdm->AppLen
433  + CheckVdm->PifLen
434  + CheckVdm->CurDirectoryLen
435  + CheckVdm->DesktopLen
436  + CheckVdm->TitleLen
437  + CheckVdm->ReservedLen
438  + CheckVdm->EnvLen
439  + sizeof(*CheckVdm->StartupInfo));
440  if (CaptureBuffer == NULL)
441  {
443  goto Cleanup;
444  }
445 
446  /* Capture the command line */
447  CsrCaptureMessageBuffer(CaptureBuffer,
448  AnsiCmdLine,
449  CheckVdm->CmdLen,
450  (PVOID*)&CheckVdm->CmdLine);
451 
452  /* Capture the application name */
453  CsrCaptureMessageBuffer(CaptureBuffer,
454  AnsiAppName,
455  CheckVdm->AppLen,
456  (PVOID*)&CheckVdm->AppName);
457 
458  CheckVdm->PifFile = NULL; // TODO: PIF file support!
459 
460  /* Capture the current directory */
461  CsrCaptureMessageBuffer(CaptureBuffer,
462  AnsiCurDirectory,
463  CheckVdm->CurDirectoryLen,
464  (PVOID*)&CheckVdm->CurDirectory);
465 
466  /* Capture the environment */
467  CsrCaptureMessageBuffer(CaptureBuffer,
468  AnsiEnvironment->Buffer,
469  CheckVdm->EnvLen,
470  (PVOID*)&CheckVdm->Env);
471 
472  /* Capture the startup info structure */
473  CsrCaptureMessageBuffer(CaptureBuffer,
474  &AnsiStartupInfo,
475  sizeof(*CheckVdm->StartupInfo),
476  (PVOID*)&CheckVdm->StartupInfo);
477 
478  if (StartupInfo->lpDesktop)
479  {
480  /* Capture the desktop name */
481  CsrCaptureMessageBuffer(CaptureBuffer,
482  AnsiDesktop,
483  CheckVdm->DesktopLen,
484  (PVOID*)&CheckVdm->Desktop);
485  }
486  else CheckVdm->Desktop = NULL;
487 
488  if (StartupInfo->lpTitle)
489  {
490  /* Capture the title */
491  CsrCaptureMessageBuffer(CaptureBuffer,
492  AnsiTitle,
493  CheckVdm->TitleLen,
494  (PVOID*)&CheckVdm->Title);
495  }
496  else CheckVdm->Title = NULL;
497 
498  if (StartupInfo->lpReserved)
499  {
500  /* Capture the reserved parameter */
501  CsrCaptureMessageBuffer(CaptureBuffer,
502  AnsiReserved,
503  CheckVdm->ReservedLen,
504  (PVOID*)&CheckVdm->Reserved);
505  }
506  else CheckVdm->Reserved = NULL;
507 
508  /* Send the message to CSRSS */
510  CaptureBuffer,
512  sizeof(*CheckVdm));
513 
514  /* Write back the task ID */
515  *iTask = CheckVdm->iTask;
516 
517 Cleanup:
518 
519  /* Free the ANSI strings */
520  if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine);
521  if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName);
522  if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory);
523  if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop);
524  if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle);
525  if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved);
526 
527  /* Free the capture buffer */
528  if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
529 
530  /* Free the current directory, if it was allocated here, and its short path */
531  if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
532  if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
533 
534  /* Free the short app name */
535  if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
536 
537  return Status;
538 }
539 
540 BOOL
541 WINAPI
543  IN OUT PHANDLE WaitHandle,
544  IN ULONG IndexInfo,
545  IN ULONG BinaryType)
546 {
547  BASE_API_MESSAGE ApiMessage;
548  PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest;
549 
550  /* Check what update is being sent */
551  switch (UpdateIndex)
552  {
553  /* VDM is being undone */
554  case VdmEntryUndo:
555  {
556  /* Tell the server how far we had gotten along */
557  UpdateVdmEntry->iTask = HandleToUlong(*WaitHandle);
558  UpdateVdmEntry->VDMCreationState = IndexInfo;
559  break;
560  }
561 
562  /* VDM is ready with a new process handle */
564  {
565  /* Send it the process handle */
566  UpdateVdmEntry->VDMProcessHandle = *WaitHandle;
567  UpdateVdmEntry->iTask = IndexInfo;
568  break;
569  }
570  }
571 
572  /* Also check what kind of binary this is for the console handle */
573  if (BinaryType == BINARY_TYPE_WOW)
574  {
575  /* Magic value for 16-bit apps */
576  UpdateVdmEntry->ConsoleHandle = (HANDLE)-1;
577  }
578  else if (UpdateVdmEntry->iTask)
579  {
580  /* No handle for true VDM */
581  UpdateVdmEntry->ConsoleHandle = NULL;
582  }
583  else
584  {
585  /* Otherwise, use the regular console handle */
586  UpdateVdmEntry->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
587  }
588 
589  /* Finally write the index and binary type */
590  UpdateVdmEntry->EntryIndex = UpdateIndex;
591  UpdateVdmEntry->BinaryType = BinaryType;
592 
593  /* Send the message to CSRSS */
595  NULL,
597  sizeof(*UpdateVdmEntry));
598  if (!NT_SUCCESS(ApiMessage.Status))
599  {
600  /* Handle failure */
601  BaseSetLastNTError(ApiMessage.Status);
602  return FALSE;
603  }
604 
605  /* If this was an update, CSRSS returns a new wait handle */
606  if (UpdateIndex == VdmEntryUpdateProcess)
607  {
608  /* Return it to the caller */
609  *WaitHandle = UpdateVdmEntry->WaitObjectForParent;
610  }
611 
612  /* We made it */
613  return TRUE;
614 }
615 
616 BOOL
617 WINAPI
619  OUT LPDWORD ExitCode)
620 {
622  EVENT_BASIC_INFORMATION EventBasicInfo;
623  BASE_API_MESSAGE ApiMessage;
624  PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest;
625 
626  /* It's VDM if the process is actually a wait handle (an event) */
629  &EventBasicInfo,
630  sizeof(EventBasicInfo),
631  NULL);
632  if (!NT_SUCCESS(Status)) return FALSE;
633 
634  /* Setup the input parameters */
635  GetVdmExitCode->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
636  GetVdmExitCode->hParent = ProcessHandle;
637 
638  /* Call CSRSS */
640  NULL,
642  sizeof(*GetVdmExitCode));
643  if (!NT_SUCCESS(Status)) return FALSE;
644 
645  /* Get the exit code from the reply */
646  *ExitCode = GetVdmExitCode->ExitCode;
647  return TRUE;
648 }
649 
650 BOOL
651 WINAPI
652 BaseGetVdmConfigInfo(IN LPCWSTR CommandLineReserved,
653  IN ULONG DosSeqId,
654  IN ULONG BinaryType,
655  IN PUNICODE_STRING CmdLineString,
656  OUT PULONG VdmSize)
657 {
659  WCHAR CommandLine[MAX_PATH * 2];
660  ULONG Length;
661 
662  /* Clear the buffer in case we fail */
663  CmdLineString->Buffer = 0;
664 
665  /* Always return the same size: 16 Mb */
666  *VdmSize = 0x1000000;
667 
668  /* Get the system directory */
670  if (!(Length) || (Length >= MAX_PATH))
671  {
672  /* Eliminate no path or path too big */
674  return FALSE;
675  }
676 
677  /* Check if this is VDM with a DOS Sequence ID */
678  if (DosSeqId)
679  {
680  /*
681  * Build the VDM string for it:
682  * -i%lx : Gives the DOS Sequence ID;
683  * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
684  */
685  _snwprintf(CommandLine,
686  ARRAYSIZE(CommandLine),
687  L"\"%s\\ntvdm.exe\" -i%lx %s%c",
688  Buffer,
689  DosSeqId,
690  (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
691  (BinaryType == BINARY_TYPE_SEPARATE_WOW) ? L's' : L' ');
692  }
693  else
694  {
695  /*
696  * Build the string for it without the DOS Sequence ID:
697  * %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
698  */
699  _snwprintf(CommandLine,
700  ARRAYSIZE(CommandLine),
701  L"\"%s\\ntvdm.exe\" %s%c",
702  Buffer,
703  (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
704  (BinaryType == BINARY_TYPE_SEPARATE_WOW) ? L's' : L' ');
705  }
706 
707  /* Create the actual string */
708  return RtlCreateUnicodeString(CmdLineString, CommandLine);
709 }
710 
712 WINAPI
714  IN ULONG NameLength)
715 {
716  PENV_INFO EnvInfo;
718  ULONG i;
719 
720  /* Start by assuming the environment variable doesn't describe paths */
722 
723  /* Loop all the environment names */
724  for (i = 0; i < ARRAYSIZE(BasepEnvNameType); i++)
725  {
726  /* Get this entry */
727  EnvInfo = &BasepEnvNameType[i];
728 
729  /* Check if it matches the name */
730  if ((EnvInfo->NameLength == NameLength) &&
731  (_wcsnicmp(EnvInfo->Name, Name, NameLength) == 0))
732  {
733  /* It does, return the type */
734  NameType = EnvInfo->NameType;
735  break;
736  }
737  }
738 
739  return NameType;
740 }
741 
742 BOOL
743 NTAPI
745  OUT PANSI_STRING AnsiEnv,
746  OUT PUNICODE_STRING UnicodeEnv)
747 {
748 #define IS_ALPHA(x) \
749  ( ((x) >= L'A' && (x) <= L'Z') || ((x) >= L'a' && (x) <= L'z') )
750 
751 // From lib/rtl/path.c :
752 // Can be put in some .h ??
753 #define IS_PATH_SEPARATOR(x) ((x) == L'\\' || (x) == L'/')
754 
755  BOOL Success = FALSE;
757  ULONG EnvironmentSize = 0;
759  PWCHAR Environment, NewEnvironment = NULL;
761  ULONG NameLength, NumChars, Remaining;
762  PWCHAR SourcePtr, DestPtr, StartPtr;
763 
764  /* Make sure we have both strings */
765  if (!AnsiEnv || !UnicodeEnv)
766  {
767  /* Fail */
769  return FALSE;
770  }
771 
772  /* Check if an environment was passed in */
773  if (!lpEnvironment)
774  {
775  /* Nope, create one */
777  if (!NT_SUCCESS(Status)) goto Cleanup;
778  }
779  else
780  {
781  /* Use the one we got */
782  Environment = lpEnvironment;
783  }
784 
785  /* Do we have something now ? */
786  if (!Environment)
787  {
788  /* Still not, bail out */
790  goto Cleanup;
791  }
792 
793  /*
794  * Count how much space the whole environment takes. The environment block is
795  * doubly NULL-terminated (NULL from last string and final NULL terminator).
796  */
797  SourcePtr = Environment;
798  while (!(*SourcePtr++ == UNICODE_NULL && *SourcePtr == UNICODE_NULL))
799  ++EnvironmentSize;
800  EnvironmentSize += 2; // Add the two terminating NULLs
801 
802  /*
803  * Allocate a new copy large enough to hold all the environment with paths
804  * in their short form. Since the short form of a path can be a bit longer
805  * than its long form, for example in the case where characters that are
806  * invalid in the 8.3 representation are present in the long path name:
807  * 'C:\\a+b' --> 'C:\\A_B~1', or:
808  * 'C:\\a b' --> 'C:\\AB2761~1' (with checksum inserted),
809  * we suppose that the possible total number of extra characters needed to
810  * convert the long paths into their short form is at most equal to MAX_PATH.
811  */
812  RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR);
814  (PVOID*)&NewEnvironment,
815  0,
816  &RegionSize,
817  MEM_COMMIT,
819  if (!NT_SUCCESS(Status))
820  {
821  /* We failed, bail out */
823  NewEnvironment = NULL;
824  goto Cleanup;
825  }
826 
827  /* Parse the environment block */
828  Remaining = MAX_PATH - 2; // '-2': remove the last two NULLs. FIXME: is it really needed??
829  SourcePtr = Environment;
830  DestPtr = NewEnvironment;
831 
832  /* Loop through all the environment strings */
833  while (*SourcePtr != UNICODE_NULL)
834  {
835  /*
836  * 1. Check the type of the environment variable and copy its name.
837  */
838 
839  /* Regular environment variable */
840  if (*SourcePtr != L'=')
841  {
842  StartPtr = SourcePtr;
843 
844  /* Copy the environment variable name, including the '=' */
845  while (*SourcePtr != UNICODE_NULL)
846  {
847  *DestPtr++ = *SourcePtr;
848  if (*SourcePtr++ == L'=') break;
849  }
850 
851  /* Guess the type of the environment variable */
852  NameType = BaseGetEnvNameType_U(StartPtr, SourcePtr - StartPtr - 1);
853  }
854  /* 'Current directory' environment variable (i.e. of '=X:=' form) */
855  else // if (*SourcePtr == L'=')
856  {
857  /* First assume we have a possibly malformed environment variable */
859 
860  /* Check for a valid 'Current directory' environment variable */
861  if (IS_ALPHA(SourcePtr[1]) && SourcePtr[2] == L':' && SourcePtr[3] == L'=')
862  {
863  /*
864  * Small optimization: convert the path to short form only if
865  * the current directory is not the root directory (i.e. not
866  * of the '=X:=Y:\' form), otherwise just do a simple copy.
867  */
868  if ( wcslen(SourcePtr) >= ARRAYSIZE("=X:=Y:\\")-1 &&
869  !( IS_ALPHA(SourcePtr[4]) && SourcePtr[5] == L':' &&
870  IS_PATH_SEPARATOR(SourcePtr[6]) && SourcePtr[7] == UNICODE_NULL ) )
871  {
873 
874  /* Copy the '=X:=' prefix */
875  *DestPtr++ = SourcePtr[0];
876  *DestPtr++ = SourcePtr[1];
877  *DestPtr++ = SourcePtr[2];
878  *DestPtr++ = SourcePtr[3];
879  SourcePtr += 4;
880  }
881  }
882  else
883  {
884  /*
885  * Invalid stuff starting with '=', i.e.:
886  * =? (with '?' not being a letter)
887  * =X??? (with '?' not being ":=" and not followed by something longer than 3 characters)
888  * =X:=??? (with '?' not being "X:\\")
889  *
890  * 'NameType' is already set to 'EnvNameNotAPath'.
891  */
892  }
893  }
894 
895 
896  /*
897  * 2. Copy the environment value and perform conversions accordingly.
898  */
899 
900  if (NameType == EnvNameNotAPath)
901  {
902  /* Copy everything, including the NULL terminator */
903  do
904  {
905  *DestPtr++ = *SourcePtr;
906  } while (*SourcePtr++ != UNICODE_NULL);
907  }
908  else if (NameType == EnvNameSinglePath)
909  {
910  /* Convert the path to its short form */
911  NameLength = wcslen(SourcePtr);
912  NumChars = GetShortPathNameW(SourcePtr, DestPtr, NameLength + 1 + Remaining);
913  if (NumChars == 0 || NumChars > NameLength + Remaining)
914  {
915  /* If the conversion failed, just copy the original value */
916  RtlCopyMemory(DestPtr, SourcePtr, NameLength * sizeof(WCHAR));
917  NumChars = NameLength;
918  }
919  DestPtr += NumChars;
920  if (NumChars > NameLength)
921  Remaining -= (NumChars - NameLength);
922 
923  SourcePtr += NameLength;
924 
925  /* Copy the NULL terminator */
926  *DestPtr++ = *SourcePtr++;
927  }
928  else // if (NameType == EnvNameMultiplePath)
929  {
930  WCHAR Delimiter;
931 
932  /* Loop through the list of paths (delimited by ';') and convert each path to its short form */
933  do
934  {
935  /* Copy any trailing ';' before going to the next path */
936  while (*SourcePtr == L';')
937  {
938  *DestPtr++ = *SourcePtr++;
939  }
940 
941  StartPtr = SourcePtr;
942 
943  /* Find the next path list delimiter or the NULL terminator */
944  while (*SourcePtr != UNICODE_NULL && *SourcePtr != L';')
945  {
946  ++SourcePtr;
947  }
948  Delimiter = *SourcePtr;
949 
950  NameLength = SourcePtr - StartPtr;
951  if (NameLength)
952  {
953  /*
954  * Temporarily replace the possible path list delimiter by NULL.
955  * 'lpEnvironment' must point to a read+write memory buffer!
956  */
957  *SourcePtr = UNICODE_NULL;
958 
959  NumChars = GetShortPathNameW(StartPtr, DestPtr, NameLength + 1 + Remaining);
960  if ( NumChars == 0 ||
961  (Delimiter == L';' ? NumChars > NameLength + Remaining
962  : NumChars > NameLength /* + Remaining ?? */) )
963  {
964  /* If the conversion failed, just copy the original value */
965  RtlCopyMemory(DestPtr, StartPtr, NameLength * sizeof(WCHAR));
966  NumChars = NameLength;
967  }
968  DestPtr += NumChars;
969  if (NumChars > NameLength)
970  Remaining -= (NumChars - NameLength);
971 
972  /* If removed, restore the path list delimiter in the source environment value and copy it */
973  if (Delimiter != UNICODE_NULL)
974  {
975  *SourcePtr = Delimiter;
976  *DestPtr++ = *SourcePtr++;
977  }
978  }
979  } while (*SourcePtr != UNICODE_NULL);
980 
981  /* Copy the NULL terminator */
982  *DestPtr++ = *SourcePtr++;
983  }
984  }
985 
986  /* NULL-terminate the environment block */
987  *DestPtr++ = UNICODE_NULL;
988 
989  /* Initialize the Unicode string to hold it */
990  RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment,
991  (DestPtr - NewEnvironment) * sizeof(WCHAR));
992  UnicodeEnv->Length = UnicodeEnv->MaximumLength;
993 
994  /* Create its ANSI version */
995  Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE);
996  if (!NT_SUCCESS(Status))
997  {
998  /* Set last error if conversion failure */
1000  }
1001  else
1002  {
1003  /* Everything went okay, so return success */
1004  Success = TRUE;
1005  NewEnvironment = NULL;
1006  }
1007 
1008 Cleanup:
1009  /* Cleanup path starts here, start by destroying the environment copy */
1010  if (!lpEnvironment && Environment) RtlDestroyEnvironment(Environment);
1011 
1012  /* See if we are here due to failure */
1013  if (NewEnvironment)
1014  {
1015  /* Initialize the paths to be empty */
1016  RtlInitEmptyUnicodeString(UnicodeEnv, NULL, 0);
1017  RtlInitEmptyAnsiString(AnsiEnv, NULL, 0);
1018 
1019  /* Free the environment copy */
1020  RegionSize = 0;
1022  (PVOID*)&NewEnvironment,
1023  &RegionSize,
1024  MEM_RELEASE);
1026  }
1027 
1028  /* Return the result */
1029  return Success;
1030 }
1031 
1032 BOOL
1033 NTAPI
1035  IN PUNICODE_STRING UnicodeEnv)
1036 {
1037  SIZE_T Dummy = 0;
1038 
1039  /* Clear the ANSI buffer since Rtl creates this for us */
1040  if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv);
1041 
1042  /* The Unicode buffer is build by hand, though */
1043  if (UnicodeEnv->Buffer)
1044  {
1045  /* So clear it through the API */
1047  (PVOID*)&UnicodeEnv->Buffer,
1048  &Dummy,
1049  MEM_RELEASE);
1050  }
1051 
1052  /* All done */
1053  return TRUE;
1054 }
1055 
1056 
1057 /* Check whether a file is an OS/2 or a very old Windows executable
1058  * by testing on import of KERNEL.
1059  *
1060  * FIXME: is reading the module imports the only way of discerning
1061  * old Windows binaries from OS/2 ones ? At least it seems so...
1062  */
1063 static DWORD WINAPI
1065 {
1066  DWORD CurPos;
1067  LPWORD modtab = NULL;
1068  LPSTR nametab = NULL;
1069  DWORD Read, Ret;
1070  int i;
1071 
1072  Ret = BINARY_OS216;
1073  CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
1074 
1075  /* read modref table */
1077  (!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
1078  (!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
1079  (Read != (DWORD)ne->ne_cmod * sizeof(WORD)))
1080  {
1081  goto broken;
1082  }
1083 
1084  /* read imported names table */
1086  (!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
1087  (!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
1088  (Read != (DWORD)ne->ne_enttab - ne->ne_imptab))
1089  {
1090  goto broken;
1091  }
1092 
1093  for(i = 0; i < ne->ne_cmod; i++)
1094  {
1095  LPSTR module;
1096  module = &nametab[modtab[i]];
1097  if(!strncmp(&module[1], "KERNEL", module[0]))
1098  {
1099  /* very old windows file */
1100  Ret = BINARY_WIN16;
1101  goto done;
1102  }
1103  }
1104 
1105  broken:
1106  DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
1107 
1108  done:
1109  HeapFree(GetProcessHeap(), 0, modtab);
1110  HeapFree(GetProcessHeap(), 0, nametab);
1111  SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
1112  return Ret;
1113 }
1114 
1115 static DWORD WINAPI
1117 {
1118  union
1119  {
1120  struct
1121  {
1122  unsigned char magic[4];
1123  unsigned char ignored[12];
1124  unsigned short type;
1125  } elf;
1126  struct
1127  {
1128  unsigned long magic;
1129  unsigned long cputype;
1130  unsigned long cpusubtype;
1131  unsigned long filetype;
1132  } macho;
1133  IMAGE_DOS_HEADER mz;
1134  } Header;
1135  char magic[4];
1136  DWORD Read;
1137 
1139  (!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
1140  (Read != sizeof(Header))))
1141  {
1142  return BINARY_UNKNOWN;
1143  }
1144 
1145  if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
1146  {
1147  /* FIXME: we don't bother to check byte order, architecture, etc. */
1148  switch(Header.elf.type)
1149  {
1150  case 2:
1151  return BINARY_UNIX_EXE;
1152  case 3:
1153  return BINARY_UNIX_LIB;
1154  }
1155  return BINARY_UNKNOWN;
1156  }
1157 
1158  /* Mach-o File with Endian set to Big Endian or Little Endian*/
1159  if(Header.macho.magic == 0xFEEDFACE ||
1160  Header.macho.magic == 0xCEFAEDFE)
1161  {
1162  switch(Header.macho.filetype)
1163  {
1164  case 0x8:
1165  /* MH_BUNDLE */
1166  return BINARY_UNIX_LIB;
1167  }
1168  return BINARY_UNKNOWN;
1169  }
1170 
1171  /* Not ELF, try DOS */
1172  if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
1173  {
1174  /* We do have a DOS image so we will now try to seek into
1175  * the file by the amount indicated by the field
1176  * "Offset to extended header" and read in the
1177  * "magic" field information at that location.
1178  * This will tell us if there is more header information
1179  * to read or not.
1180  */
1182  (!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
1183  (Read != sizeof(magic))))
1184  {
1185  return BINARY_DOS;
1186  }
1187 
1188  /* Reading the magic field succeeded so
1189  * we will try to determine what type it is.
1190  */
1191  if(!memcmp(magic, "PE\0\0", sizeof(magic)))
1192  {
1193  IMAGE_FILE_HEADER FileHeader;
1194  if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
1195  (Read != sizeof(IMAGE_FILE_HEADER)))
1196  {
1197  return BINARY_DOS;
1198  }
1199 
1200  /* FIXME - detect 32/64 bit */
1201 
1202  if(FileHeader.Characteristics & IMAGE_FILE_DLL)
1203  return BINARY_PE_DLL32;
1204  return BINARY_PE_EXE32;
1205  }
1206 
1207  if(!memcmp(magic, "NE", 2))
1208  {
1209  /* This is a Windows executable (NE) header. This can
1210  * mean either a 16-bit OS/2 or a 16-bit Windows or even a
1211  * DOS program (running under a DOS extender). To decide
1212  * which, we'll have to read the NE header.
1213  */
1214  IMAGE_OS2_HEADER ne;
1215  if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
1216  !ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
1217  (Read != sizeof(IMAGE_OS2_HEADER)))
1218  {
1219  /* Couldn't read header, so abort. */
1220  return BINARY_DOS;
1221  }
1222 
1223  switch(ne.ne_exetyp)
1224  {
1225  case 2:
1226  return BINARY_WIN16;
1227  case 5:
1228  return BINARY_DOS;
1229  default:
1230  return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
1231  }
1232  }
1233  return BINARY_DOS;
1234  }
1235  return BINARY_UNKNOWN;
1236 }
1237 
1238 /*
1239  * @implemented
1240  */
1241 BOOL
1242 WINAPI
1244  LPCWSTR lpApplicationName,
1245  LPDWORD lpBinaryType
1246  )
1247 {
1248  HANDLE hFile;
1249  DWORD BinType;
1250 
1251  if(!lpApplicationName || !lpBinaryType)
1252  {
1254  return FALSE;
1255  }
1256 
1257  hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
1258  OPEN_EXISTING, 0, 0);
1260  {
1261  return FALSE;
1262  }
1263 
1264  BinType = InternalGetBinaryType(hFile);
1265  CloseHandle(hFile);
1266 
1267  switch(BinType)
1268  {
1269  case BINARY_UNKNOWN:
1270  {
1271  WCHAR *dot;
1272 
1273  /*
1274  * guess from filename
1275  */
1276  if(!(dot = wcsrchr(lpApplicationName, L'.')))
1277  {
1278  return FALSE;
1279  }
1280  if(!lstrcmpiW(dot, L".COM"))
1281  {
1282  *lpBinaryType = SCS_DOS_BINARY;
1283  return TRUE;
1284  }
1285  if(!lstrcmpiW(dot, L".PIF"))
1286  {
1287  *lpBinaryType = SCS_PIF_BINARY;
1288  return TRUE;
1289  }
1290  return FALSE;
1291  }
1292  case BINARY_PE_EXE32:
1293  case BINARY_PE_DLL32:
1294  {
1295  *lpBinaryType = SCS_32BIT_BINARY;
1296  return TRUE;
1297  }
1298  case BINARY_PE_EXE64:
1299  case BINARY_PE_DLL64:
1300  {
1301  *lpBinaryType = SCS_64BIT_BINARY;
1302  return TRUE;
1303  }
1304  case BINARY_WIN16:
1305  {
1306  *lpBinaryType = SCS_WOW_BINARY;
1307  return TRUE;
1308  }
1309  case BINARY_OS216:
1310  {
1311  *lpBinaryType = SCS_OS216_BINARY;
1312  return TRUE;
1313  }
1314  case BINARY_DOS:
1315  {
1316  *lpBinaryType = SCS_DOS_BINARY;
1317  return TRUE;
1318  }
1319  case BINARY_UNIX_EXE:
1320  case BINARY_UNIX_LIB:
1321  {
1322  return FALSE;
1323  }
1324  }
1325 
1326  DPRINT1("Invalid binary type %lu returned!\n", BinType);
1327  return FALSE;
1328 }
1329 
1330 /*
1331  * @implemented
1332  */
1333 BOOL
1334 WINAPI
1335 GetBinaryTypeA(IN LPCSTR lpApplicationName,
1336  OUT LPDWORD lpBinaryType)
1337 {
1338  ANSI_STRING ApplicationNameString;
1339  UNICODE_STRING ApplicationNameW;
1340  BOOL StringAllocated = FALSE, Result;
1341  NTSTATUS Status;
1342 
1343  RtlInitAnsiString(&ApplicationNameString, lpApplicationName);
1344 
1345  if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength)
1346  {
1347  StringAllocated = TRUE;
1348  Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE);
1349  }
1350  else
1351  {
1352  Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE);
1353  }
1354 
1355  if (!NT_SUCCESS(Status))
1356  {
1358  return FALSE;
1359  }
1360 
1361  if (StringAllocated)
1362  {
1363  Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType);
1364  RtlFreeUnicodeString(&ApplicationNameW);
1365  }
1366  else
1367  {
1368  Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
1369  }
1370 
1371  return Result;
1372 }
1373 
1374 /*
1375  * @unimplemented
1376  */
1377 BOOL
1378 WINAPI
1380  DWORD Unknown
1381  )
1382 {
1383  STUB;
1384  return FALSE;
1385 }
1386 
1387 /*
1388  * @implemented
1389  */
1390 VOID
1391 WINAPI
1392 ExitVDM(BOOL IsWow, ULONG iWowTask)
1393 {
1394  BASE_API_MESSAGE ApiMessage;
1395  PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest;
1396 
1397  /* Setup the input parameters */
1398  ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1399  ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */
1400  ExitVdm->WaitObjectForVDM = NULL;
1401 
1402  /* Call CSRSS */
1404  NULL,
1406  sizeof(*ExitVdm));
1407 
1408  /* Close the returned wait object handle, if any */
1409  if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL))
1410  {
1411  CloseHandle(ExitVdm->WaitObjectForVDM);
1412  }
1413 }
1414 
1415 /*
1416  * @implemented
1417  */
1418 BOOL
1419 WINAPI
1421 {
1422  BOOL Success = FALSE;
1423  NTSTATUS Status;
1424  BASE_API_MESSAGE ApiMessage;
1425  PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest;
1426  PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest;
1427  PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
1428  PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
1429  ULONG NumStrings = 0;
1430 
1431  /*
1432  * Special case to test whether the VDM is the first one.
1433  */
1434  if (CommandData == NULL)
1435  {
1436  /* Call CSRSS */
1438  NULL,
1440  sizeof(*IsFirstVdm));
1441  if (!NT_SUCCESS(ApiMessage.Status))
1442  {
1443  BaseSetLastNTError(ApiMessage.Status);
1444  return FALSE;
1445  }
1446 
1447  /* Return TRUE if this is the first VDM */
1448  return IsFirstVdm->FirstVDM;
1449  }
1450 
1451  /* CommandData != NULL */
1452 
1453  /*
1454  * Special case to increment or decrement the reentrancy count.
1455  */
1456  if ((CommandData->VDMState == VDM_INC_REENTER_COUNT) ||
1457  (CommandData->VDMState == VDM_DEC_REENTER_COUNT))
1458  {
1459  /* Setup the input parameters */
1460  SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1461  SetReenterCount->fIncDec = CommandData->VDMState;
1462 
1463  /* Call CSRSS */
1465  NULL,
1467  sizeof(*SetReenterCount));
1468  if (!NT_SUCCESS(ApiMessage.Status))
1469  {
1470  BaseSetLastNTError(ApiMessage.Status);
1471  return FALSE;
1472  }
1473 
1474  return TRUE;
1475  }
1476 
1477  /*
1478  * TODO!
1479  * Special case to retrieve or set WOW information.
1480  */
1481  // TODO: if CommandData->VDMState & (VDM_LIST_WOW_PROCESSES | VDM_LIST_WOW_TASKS | VDM_ADD_WOW_TASK)
1482  // then call BasepGetNextVDMCommand in a simpler way!
1483 
1484  /*
1485  * Regular case.
1486  */
1487 
1488  /* Clear the structure */
1489  RtlZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand));
1490 
1491  /* Setup the input parameters */
1492  GetNextVdmCommand->iTask = CommandData->TaskId;
1493  GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1494  GetNextVdmCommand->CmdLen = CommandData->CmdLen;
1495  GetNextVdmCommand->AppLen = CommandData->AppLen;
1496  GetNextVdmCommand->PifLen = CommandData->PifLen;
1497  GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen;
1498  GetNextVdmCommand->EnvLen = CommandData->EnvLen;
1499  GetNextVdmCommand->DesktopLen = CommandData->DesktopLen;
1500  GetNextVdmCommand->TitleLen = CommandData->TitleLen;
1501  GetNextVdmCommand->ReservedLen = CommandData->ReservedLen;
1502  GetNextVdmCommand->VDMState = CommandData->VDMState;
1503 
1504  /* Count the number of strings */
1505  if (CommandData->CmdLen) NumStrings++;
1506  if (CommandData->AppLen) NumStrings++;
1507  if (CommandData->PifLen) NumStrings++;
1508  if (CommandData->CurDirectoryLen) NumStrings++;
1509  if (CommandData->EnvLen) NumStrings++;
1510  if (CommandData->DesktopLen) NumStrings++;
1511  if (CommandData->TitleLen) NumStrings++;
1512  if (CommandData->ReservedLen) NumStrings++;
1513 
1514  /* Allocate the capture buffer */
1515  CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1,
1516  GetNextVdmCommand->CmdLen
1517  + GetNextVdmCommand->AppLen
1518  + GetNextVdmCommand->PifLen
1519  + GetNextVdmCommand->CurDirectoryLen
1520  + GetNextVdmCommand->EnvLen
1521  + GetNextVdmCommand->DesktopLen
1522  + GetNextVdmCommand->TitleLen
1523  + GetNextVdmCommand->ReservedLen
1524  + sizeof(*GetNextVdmCommand->StartupInfo));
1525  if (CaptureBuffer == NULL)
1526  {
1528  goto Cleanup;
1529  }
1530 
1531  /* Capture the data */
1532 
1533  CsrAllocateMessagePointer(CaptureBuffer,
1534  sizeof(*GetNextVdmCommand->StartupInfo),
1535  (PVOID*)&GetNextVdmCommand->StartupInfo);
1536 
1537  if (CommandData->CmdLen)
1538  {
1539  CsrAllocateMessagePointer(CaptureBuffer,
1540  CommandData->CmdLen,
1541  (PVOID*)&GetNextVdmCommand->CmdLine);
1542  }
1543 
1544  if (CommandData->AppLen)
1545  {
1546  CsrAllocateMessagePointer(CaptureBuffer,
1547  CommandData->AppLen,
1548  (PVOID*)&GetNextVdmCommand->AppName);
1549  }
1550 
1551  if (CommandData->PifLen)
1552  {
1553  CsrAllocateMessagePointer(CaptureBuffer,
1554  CommandData->PifLen,
1555  (PVOID*)&GetNextVdmCommand->PifFile);
1556  }
1557 
1558  if (CommandData->CurDirectoryLen)
1559  {
1560  CsrAllocateMessagePointer(CaptureBuffer,
1561  CommandData->CurDirectoryLen,
1562  (PVOID*)&GetNextVdmCommand->CurDirectory);
1563  }
1564 
1565  if (CommandData->EnvLen)
1566  {
1567  CsrAllocateMessagePointer(CaptureBuffer,
1568  CommandData->EnvLen,
1569  (PVOID*)&GetNextVdmCommand->Env);
1570  }
1571 
1572  if (CommandData->DesktopLen)
1573  {
1574  CsrAllocateMessagePointer(CaptureBuffer,
1575  CommandData->DesktopLen,
1576  (PVOID*)&GetNextVdmCommand->Desktop);
1577  }
1578 
1579  if (CommandData->TitleLen)
1580  {
1581  CsrAllocateMessagePointer(CaptureBuffer,
1582  CommandData->TitleLen,
1583  (PVOID*)&GetNextVdmCommand->Title);
1584  }
1585 
1586  if (CommandData->ReservedLen)
1587  {
1588  CsrAllocateMessagePointer(CaptureBuffer,
1589  CommandData->ReservedLen,
1590  (PVOID*)&GetNextVdmCommand->Reserved);
1591  }
1592 
1593  while (TRUE)
1594  {
1595  /* Call CSRSS */
1597  CaptureBuffer,
1599  sizeof(*GetNextVdmCommand));
1600 
1601  /* Exit the waiting loop if we did not receive any event handle */
1602  if (GetNextVdmCommand->WaitObjectForVDM == NULL)
1603  break;
1604 
1605  /* Wait for the event to become signaled and try again */
1606  Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM,
1607  FALSE, NULL);
1608  if (Status != STATUS_SUCCESS)
1609  {
1610  /* Fail if we timed out, or if some other error happened */
1612  goto Cleanup;
1613  }
1614 
1615  /* Set the retry flag, clear the exit code, and retry a query */
1616  GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
1617  GetNextVdmCommand->ExitCode = 0;
1618  }
1619 
1620  if (!NT_SUCCESS(Status))
1621  {
1623  {
1624  /*
1625  * One of the buffer lengths was less than required. Store the correct ones.
1626  * Note that the status code is not STATUS_BUFFER_TOO_SMALL as one would expect,
1627  * in order to keep compatibility with Windows 2003 BASESRV.DLL.
1628  */
1629  CommandData->CmdLen = GetNextVdmCommand->CmdLen;
1630  CommandData->AppLen = GetNextVdmCommand->AppLen;
1631  CommandData->PifLen = GetNextVdmCommand->PifLen;
1632  CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
1633  CommandData->EnvLen = GetNextVdmCommand->EnvLen;
1634  CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
1635  CommandData->TitleLen = GetNextVdmCommand->TitleLen;
1636  CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
1637  }
1638  else
1639  {
1640  /* Any other failure */
1641  CommandData->CmdLen = 0;
1642  CommandData->AppLen = 0;
1643  CommandData->PifLen = 0;
1644  CommandData->CurDirectoryLen = 0;
1645  CommandData->EnvLen = 0;
1646  CommandData->DesktopLen = 0;
1647  CommandData->TitleLen = 0;
1648  CommandData->ReservedLen = 0;
1649  }
1650 
1652  goto Cleanup;
1653  }
1654 
1655  /* Write back the standard handles */
1656  CommandData->StdIn = GetNextVdmCommand->StdIn;
1657  CommandData->StdOut = GetNextVdmCommand->StdOut;
1658  CommandData->StdErr = GetNextVdmCommand->StdErr;
1659 
1660  /* Write back the startup info */
1661  RtlMoveMemory(&CommandData->StartupInfo,
1662  GetNextVdmCommand->StartupInfo,
1663  sizeof(*GetNextVdmCommand->StartupInfo));
1664 
1665  if (CommandData->CmdLen)
1666  {
1667  /* Write back the command line */
1668  RtlMoveMemory(CommandData->CmdLine,
1669  GetNextVdmCommand->CmdLine,
1670  GetNextVdmCommand->CmdLen);
1671 
1672  /* Set the actual length */
1673  CommandData->CmdLen = GetNextVdmCommand->CmdLen;
1674  }
1675 
1676  if (CommandData->AppLen)
1677  {
1678  /* Write back the application name */
1679  RtlMoveMemory(CommandData->AppName,
1680  GetNextVdmCommand->AppName,
1681  GetNextVdmCommand->AppLen);
1682 
1683  /* Set the actual length */
1684  CommandData->AppLen = GetNextVdmCommand->AppLen;
1685  }
1686 
1687  if (CommandData->PifLen)
1688  {
1689  /* Write back the PIF file name */
1690  RtlMoveMemory(CommandData->PifFile,
1691  GetNextVdmCommand->PifFile,
1692  GetNextVdmCommand->PifLen);
1693 
1694  /* Set the actual length */
1695  CommandData->PifLen = GetNextVdmCommand->PifLen;
1696  }
1697 
1698  if (CommandData->CurDirectoryLen)
1699  {
1700  /* Write back the current directory */
1701  RtlMoveMemory(CommandData->CurDirectory,
1702  GetNextVdmCommand->CurDirectory,
1703  GetNextVdmCommand->CurDirectoryLen);
1704 
1705  /* Set the actual length */
1706  CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
1707  }
1708 
1709  if (CommandData->EnvLen)
1710  {
1711  /* Write back the environment */
1712  RtlMoveMemory(CommandData->Env,
1713  GetNextVdmCommand->Env,
1714  GetNextVdmCommand->EnvLen);
1715 
1716  /* Set the actual length */
1717  CommandData->EnvLen = GetNextVdmCommand->EnvLen;
1718  }
1719 
1720  if (CommandData->DesktopLen)
1721  {
1722  /* Write back the desktop name */
1723  RtlMoveMemory(CommandData->Desktop,
1724  GetNextVdmCommand->Desktop,
1725  GetNextVdmCommand->DesktopLen);
1726 
1727  /* Set the actual length */
1728  CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
1729  }
1730 
1731  if (CommandData->TitleLen)
1732  {
1733  /* Write back the title */
1734  RtlMoveMemory(CommandData->Title,
1735  GetNextVdmCommand->Title,
1736  GetNextVdmCommand->TitleLen);
1737 
1738  /* Set the actual length */
1739  CommandData->TitleLen = GetNextVdmCommand->TitleLen;
1740  }
1741 
1742  if (CommandData->ReservedLen)
1743  {
1744  /* Write back the reserved parameter */
1745  RtlMoveMemory(CommandData->Reserved,
1746  GetNextVdmCommand->Reserved,
1747  GetNextVdmCommand->ReservedLen);
1748 
1749  /* Set the actual length */
1750  CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
1751  }
1752 
1753  /* Write the remaining output parameters */
1754  CommandData->TaskId = GetNextVdmCommand->iTask;
1755  CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags;
1756  CommandData->CodePage = GetNextVdmCommand->CodePage;
1757  CommandData->ExitCode = GetNextVdmCommand->ExitCode;
1758  CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive;
1759  CommandData->VDMState = GetNextVdmCommand->VDMState;
1760  CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat;
1761 
1762  /* It was successful */
1763  Success = TRUE;
1764 
1765 Cleanup:
1766  if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer);
1767  return Success;
1768 }
1769 
1770 
1771 /*
1772  * @implemented
1773  */
1774 DWORD
1775 WINAPI
1776 GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
1777 {
1778  BASE_API_MESSAGE ApiMessage;
1779  PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
1780  PCSR_CAPTURE_BUFFER CaptureBuffer;
1781 
1782  /* Allocate the capture buffer */
1783  CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
1784  if (CaptureBuffer == NULL)
1785  {
1787  return 0;
1788  }
1789 
1790  /* Setup the input parameters */
1791  VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
1792  CsrAllocateMessagePointer(CaptureBuffer,
1793  cchCurDirs,
1794  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
1795 
1796  /* Call CSRSS */
1798  CaptureBuffer,
1800  sizeof(*VDMCurrentDirsRequest));
1801 
1802  /* Set the last error */
1803  BaseSetLastNTError(ApiMessage.Status);
1804 
1805  if (NT_SUCCESS(ApiMessage.Status))
1806  {
1807  /* Copy the result */
1808  RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs);
1809  }
1810 
1811  /* Free the capture buffer */
1812  CsrFreeCaptureBuffer(CaptureBuffer);
1813 
1814  /* Return the size if it was successful, or if the buffer was too small */
1815  return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL))
1816  ? VDMCurrentDirsRequest->cchCurDirs : 0;
1817 }
1818 
1819 
1820 /*
1821  * @implemented (undocumented)
1822  */
1823 BOOL
1824 WINAPI
1825 RegisterConsoleVDM(IN DWORD dwRegisterFlags,
1826  IN HANDLE hStartHardwareEvent,
1827  IN HANDLE hEndHardwareEvent,
1828  IN HANDLE hErrorHardwareEvent,
1829  IN DWORD dwUnusedVar,
1830  OUT LPDWORD lpVideoStateLength,
1831  OUT PVOID* lpVideoState, // PVIDEO_HARDWARE_STATE_HEADER*
1832  IN PVOID lpUnusedBuffer,
1833  IN DWORD dwUnusedBufferLength,
1834  IN COORD dwVDMBufferSize,
1835  OUT PVOID* lpVDMBuffer)
1836 {
1837  BOOL Success;
1838  CONSOLE_API_MESSAGE ApiMessage;
1839  PCONSOLE_REGISTERVDM RegisterVDMRequest = &ApiMessage.Data.RegisterVDMRequest;
1840  PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
1841 
1842  /* Set up the data to send to the Console Server */
1843  RegisterVDMRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1844  RegisterVDMRequest->RegisterFlags = dwRegisterFlags;
1845 
1846  if (dwRegisterFlags != 0)
1847  {
1848  RegisterVDMRequest->StartHardwareEvent = hStartHardwareEvent;
1849  RegisterVDMRequest->EndHardwareEvent = hEndHardwareEvent;
1850  RegisterVDMRequest->ErrorHardwareEvent = hErrorHardwareEvent;
1851 
1852  RegisterVDMRequest->VDMBufferSize = dwVDMBufferSize;
1853 
1854 #if 0
1855  RegisterVDMRequest->UnusedBufferLength = dwUnusedBufferLength;
1856 
1857  /* Allocate a Capture Buffer */
1858  CaptureBuffer = CsrAllocateCaptureBuffer(1, dwUnusedBufferLength);
1859  if (CaptureBuffer == NULL)
1860  {
1861  DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1863  return FALSE;
1864  }
1865 
1866  /* Capture the buffer to write */
1867  CsrCaptureMessageBuffer(CaptureBuffer,
1868  (PVOID)lpUnusedBuffer,
1869  dwUnusedBufferLength,
1870  (PVOID*)&RegisterVDMRequest->UnusedBuffer);
1871 #endif
1872  }
1873  else
1874  {
1875  // CaptureBuffer = NULL;
1876  }
1877 
1878  /* Call the server */
1880  CaptureBuffer,
1882  sizeof(*RegisterVDMRequest));
1883 
1884  /* Check for success */
1885  Success = NT_SUCCESS(ApiMessage.Status);
1886 
1887  /* Release the capture buffer if needed */
1888  if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1889 
1890  /* Retrieve the results */
1891  if (Success)
1892  {
1893  if (dwRegisterFlags != 0)
1894  {
1895  _SEH2_TRY
1896  {
1897  *lpVideoStateLength = RegisterVDMRequest->VideoStateLength;
1898  *lpVideoState = RegisterVDMRequest->VideoState;
1899  *lpVDMBuffer = RegisterVDMRequest->VDMBuffer;
1900  }
1902  {
1904  Success = FALSE;
1905  }
1906  _SEH2_END;
1907  }
1908  }
1909  else
1910  {
1911  BaseSetLastNTError(ApiMessage.Status);
1912  }
1913 
1914  /* Return success status */
1915  return Success;
1916 }
1917 
1918 
1919 /*
1920  * @unimplemented
1921  */
1922 BOOL
1923 WINAPI
1925  DWORD Unknown0
1926  )
1927 {
1928  STUB;
1929  return FALSE;
1930 }
1931 
1932 
1933 /*
1934  * @unimplemented
1935  */
1936 BOOL
1937 WINAPI
1939  DWORD Unknown0
1940  )
1941 {
1942  STUB;
1943  return FALSE;
1944 }
1945 
1946 
1947 /*
1948  * @implemented
1949  */
1950 BOOL
1951 WINAPI
1952 SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
1953 {
1954  BASE_API_MESSAGE ApiMessage;
1955  PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
1956  PCSR_CAPTURE_BUFFER CaptureBuffer;
1957 
1958  /* Allocate the capture buffer */
1959  CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
1960  if (CaptureBuffer == NULL)
1961  {
1963  return FALSE;
1964  }
1965 
1966  /* Setup the input parameters */
1967  VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
1968  CsrCaptureMessageBuffer(CaptureBuffer,
1969  lpszzCurDirs,
1970  cchCurDirs,
1971  (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
1972 
1973  /* Call CSRSS */
1975  CaptureBuffer,
1977  sizeof(*VDMCurrentDirsRequest));
1978 
1979  /* Free the capture buffer */
1980  CsrFreeCaptureBuffer(CaptureBuffer);
1981 
1982  /* Set the last error */
1983  BaseSetLastNTError(ApiMessage.Status);
1984 
1985  return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE;
1986 }
1987 
1988 /*
1989  * @unimplemented
1990  */
1991 DWORD
1992 WINAPI
1994  DWORD Unknown0,
1995  DWORD Unknown1
1996  )
1997 {
1998  STUB;
1999  return 0;
2000 }
2001 
2002 
2003 /*
2004  * @unimplemented
2005  */
2006 BOOL
2007 WINAPI
2009 {
2010  DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
2011 
2013  NULL,
2014  0,
2015  Unknown0);
2016 }
union _BASE_API_MESSAGE::@3469 Data
enum _ENV_NAME_TYPE ENV_NAME_TYPE
#define SCS_32BIT_BINARY
Definition: winbase.h:233
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
LPSTR Desktop
Definition: vdm.h:84
CONST WCHAR * PCWCH
Definition: ntbasedef.h:411
static UNICODE_STRING BaseDotExeSuffixName
Definition: vdm.c:60
VOID NTAPI CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
Definition: capture.c:210
#define ERROR_BAD_ENVIRONMENT
Definition: winerror.h:113
BOOL WINAPI VDMOperationStarted(IN ULONG Unknown0)
Definition: vdm.c:2008
HANDLE StdOut
Definition: basemsg.h:125
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#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
ENV_NAME_TYPE NameType
Definition: vdm.c:39
#define CloseHandle
Definition: compat.h:598
HMODULE module
Definition: main.cpp:47
ULONG DesktopLen
Definition: vdm.h:85
ULONG ExitCode
Definition: vdm.h:72
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
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:828
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:111
#define IS_PATH_SEPARATOR(x)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#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:542
#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:154
PCHAR CmdLine
Definition: basemsg.h:129
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
PCSR_CAPTURE_BUFFER NTAPI CsrAllocateCaptureBuffer(IN ULONG ArgumentCount, IN ULONG BufferSize)
Definition: capture.c:90
BASE_UPDATE_VDM_ENTRY UpdateVDMEntryRequest
Definition: basemsg.h:288
HANDLE StdErr
Definition: vdm.h:76
#define TRUE
Definition: types.h:120
#define BINARY_DOS
Definition: vdm.c:25
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSYSAPI VOID NTAPI RtlDestroyEnvironment(_In_ PWSTR Environment)
BOOL NTAPI BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment, OUT PANSI_STRING AnsiEnv, OUT PUNICODE_STRING UnicodeEnv)
Definition: vdm.c:744
_ENV_NAME_TYPE
Definition: vdm.c:30
#define CP_ACP
Definition: compat.h:109
ULONG DesktopLen
Definition: basemsg.h:137
NTSTATUS NTAPI CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage, IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, IN CSR_API_NUMBER ApiNumber, IN ULONG DataLength)
Definition: connect.c:365
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:652
BOOL NTAPI BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv, IN PUNICODE_STRING UnicodeEnv)
Definition: vdm.c:1034
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define HandleToUlong(h)
Definition: basetsd.h:79
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:615
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
PCHAR CurDirectory
Definition: basemsg.h:132
u32_t magic(void)
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define BINARY_WIN16
Definition: vdm.c:23
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
static DWORD WINAPI InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
Definition: vdm.c:1064
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
USHORT PifLen
Definition: vdm.h:92
BOOL WINAPI BaseCheckForVDM(IN HANDLE ProcessHandle, OUT LPDWORD ExitCode)
Definition: vdm.c:618
#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:713
#define BINARY_PE_DLL64
Definition: vdm.c:22
#define FILE_BEGIN
Definition: compat.h:620
uint16_t * PWCHAR
Definition: typedefs.h:56
BASE_EXIT_VDM ExitVDMRequest
Definition: basemsg.h:290
USHORT CmdLen
Definition: vdm.h:90
VOID WINAPI ExitVDM(BOOL IsWow, ULONG iWowTask)
Definition: vdm.c:1392
char * LPSTR
Definition: xmlstorage.h:182
#define MEM_COMMIT
Definition: nt_native.h:1313
BOOL WINAPI GetBinaryTypeW(LPCWSTR lpApplicationName, LPDWORD lpBinaryType)
Definition: vdm.c:1243
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define FILE_SHARE_READ
Definition: compat.h:136
ULONG BinaryType
Definition: basemsg.h:153
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define BINARY_UNIX_LIB
Definition: vdm.c:27
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_SEH2_TRY
Definition: create.c:4226
BOOLEAN ComingFromBat
Definition: vdm.h:96
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
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:1776
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:190
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2430
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
unsigned int BOOL
Definition: ntddk_ex.h:94
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT NumStrings
Definition: ndis.h:4751
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:1825
HANDLE StdErr
Definition: basemsg.h:126
#define SCS_PIF_BINARY
Definition: winbase.h:237
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,...)
#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:1952
#define BINARY_OS216
Definition: vdm.c:24
_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
DWORD WINAPI VDMConsoleOperation(DWORD Unknown0, DWORD Unknown1)
Definition: vdm.c:1993
#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:313
Definition: bufpool.h:45
USHORT VDMState
Definition: vdm.h:94
LPSTR lpReserved
Definition: winbase.h:826
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:634
#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:588
Status
Definition: gdiplustypes.h:24
HANDLE hUserToken
Definition: install.c:39
#define STARTF_USESTDHANDLES
Definition: winbase.h:496
ULONG CreationFlags
Definition: vdm.h:71
LPSTARTUPINFOA StartupInfo
Definition: basemsg.h:178
LPSTR CurDirectory
Definition: vdm.h:80
#define UNICODE_STRING_MAX_CHARS
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
ULONG iWowTask
Definition: basemsg.h:197
#define BINARY_PE_EXE64
Definition: vdm.c:21
#define ASSERT(a)
Definition: mode.c:44
BASE_SET_REENTER_COUNT SetReenterCountRequest
Definition: basemsg.h:293
#define BASESRV_SERVERDLL_INDEX
Definition: basemsg.h:15
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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:34
#define WINAPI
Definition: msvc.h:6
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:1379
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
unsigned short WORD
Definition: ntddk_ex.h:93
PVOID HANDLE
Definition: typedefs.h:73
unsigned long DWORD
Definition: ntddk_ex.h:95
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define SetLastError(x)
Definition: compat.h:611
#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:1335
HANDLE StdIn
Definition: basemsg.h:124
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
static const WCHAR L[]
Definition: oid.c:1250
Definition: vdm.c:37
static ENV_INFO BasepEnvNameType[]
Definition: vdm.c:49
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
BOOL WINAPI RegisterWowExec(DWORD Unknown0)
Definition: vdm.c:1938
#define ERROR_INVALID_ACCESS
Definition: winerror.h:115
#define GENERIC_READ
Definition: compat.h:135
#define wcsrchr
Definition: compat.h:16
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:1924
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
static UNICODE_STRING BaseDotPifSuffixName
Definition: vdm.c:59
NTSYSAPI NTSTATUS NTAPI RtlCreateEnvironment(_In_ BOOLEAN Inherit, _Out_ PWSTR *Environment)
uint16_t * LPWORD
Definition: typedefs.h:56
USHORT EntryIndex
Definition: basemsg.h:157
ULONG_PTR SIZE_T
Definition: typedefs.h:80
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
PVOID PVOID PWCHAR ApplicationName
Definition: env.c:47
_SEH2_END
Definition: create.c:4400
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:4481
LPSTR lpDesktop
Definition: winbase.h:827
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
#define INVALID_SET_FILE_POINTER
Definition: compat.h:591
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG BinaryType
Definition: basemsg.h:122
#define NtCurrentPeb()
Definition: FLS.c:22
#define STUB
Definition: kernel32.h:27
unsigned short USHORT
Definition: pedump.c:61
__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:260
static DWORD WINAPI InternalGetBinaryType(HANDLE hFile)
Definition: vdm.c:1116
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2312
#define ReadFile(a, b, c, d, e)
Definition: compat.h:601
unsigned int * PULONG
Definition: retypes.h:1
#define STATUS_OBJECT_PATH_INVALID
Definition: ntstatus.h:293
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
HANDLE ConsoleHandle
Definition: basemsg.h:154
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
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:600
#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:40
uint32_t * LPDWORD
Definition: typedefs.h:59
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:103
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 RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
HANDLE StdOut
Definition: vdm.h:75
ULONG ReservedLen
Definition: vdm.h:89
#define STATUS_SUCCESS
Definition: shellext.h:65
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 NameType
Definition: acpixf.h:654
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
PCHAR Reserved
Definition: basemsg.h:140
struct _ENV_INFO ENV_INFO
BOOL WINAPI GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
Definition: vdm.c:1420
ULONG TitleLen
Definition: vdm.h:87
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
struct _ENV_INFO * PENV_INFO
ULONG CodePage
Definition: vdm.h:73
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define HeapFree(x, y, z)
Definition: compat.h:594
union _CONSOLE_API_MESSAGE::@3471 Data
ULONG TaskId
Definition: vdm.h:70
ULONG UnusedBufferLength
Definition: conmsg.h:885
#define SetFilePointer
Definition: compat.h:602
USHORT AppLen
Definition: basemsg.h:143
#define BINARY_TYPE_EXE
Definition: vdm.h:35
#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:5204
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)