803558703a7d780e73d802867cddb0e4158435d7
[reactos.git] / dll / win32 / kernel32 / client / vdm.c
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 Machine (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 typedef struct _ENV_INFO
19 {
20 ULONG NameType;
21 ULONG NameLength;
22 PWCHAR Name;
23 } ENV_INFO, *PENV_INFO;
24
25 /* GLOBALS ********************************************************************/
26
27 ENV_INFO BasepEnvNameType[] =
28 {
29 {3, sizeof(L"PATH"), L"PATH"},
30 {2, sizeof(L"WINDIR"), L"WINDIR"},
31 {2, sizeof(L"SYSTEMROOT"), L"SYSTEMROOT"},
32 {3, sizeof(L"TEMP"), L"TEMP"},
33 {3, sizeof(L"TMP"), L"TMP"},
34 };
35
36 UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com");
37 UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif");
38 UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe");
39
40 /* FUNCTIONS ******************************************************************/
41
42 ULONG
43 WINAPI
44 BaseIsDosApplication(IN PUNICODE_STRING PathName,
45 IN NTSTATUS Status)
46 {
47 UNICODE_STRING String;
48
49 /* Is it a .com? */
50 String.Length = BaseDotComSuffixName.Length;
51 String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
52 if (RtlEqualUnicodeString(&String, &BaseDotComSuffixName, TRUE)) return 2;
53
54 /* Is it a .pif? */
55 String.Length = BaseDotPifSuffixName.Length;
56 String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
57 if (RtlEqualUnicodeString(&String, &BaseDotPifSuffixName, TRUE)) return 3;
58
59 /* Is it an exe? */
60 String.Length = BaseDotExeSuffixName.Length;
61 String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)];
62 if (RtlEqualUnicodeString(&String, &BaseDotExeSuffixName, TRUE)) return 1;
63 return 0;
64 }
65
66 BOOL
67 WINAPI
68 BaseCheckVDM(IN ULONG BinaryType,
69 IN PCWCH ApplicationName,
70 IN PCWCH CommandLine,
71 IN PCWCH CurrentDirectory,
72 IN PANSI_STRING AnsiEnvironment,
73 IN PCSR_API_MESSAGE Msg,
74 IN OUT PULONG iTask,
75 IN DWORD CreationFlags,
76 IN LPSTARTUPINFOW StartupInfo)
77 {
78 /* This is not supported */
79 UNIMPLEMENTED;
80 return FALSE;
81 }
82
83 BOOL
84 WINAPI
85 BaseUpdateVDMEntry(IN ULONG UpdateIndex,
86 IN OUT PHANDLE WaitHandle,
87 IN ULONG IndexInfo,
88 IN ULONG BinaryType)
89 {
90 NTSTATUS Status;
91 CSR_API_MESSAGE Msg;
92
93 /* Check what update is being sent */
94 switch (UpdateIndex)
95 {
96 /* VDM is being undone */
97 case VdmEntryUndo:
98
99 /* Tell the server how far we had gotten along */
100 Msg.Data.UpdateVdmEntry.iTask = (ULONG)*WaitHandle;
101 Msg.Data.UpdateVdmEntry.VDMCreationState = IndexInfo;
102 break;
103
104 /* VDM is ready with a new process handle */
105 case VdmEntryUpdateProcess:
106
107 /* Send it the process handle */
108 Msg.Data.UpdateVdmEntry.VDMProcessHandle = *WaitHandle;
109 Msg.Data.UpdateVdmEntry.iTask = IndexInfo;
110 break;
111 }
112
113 /* Also check what kind of binary this is for the console handle */
114 if (BinaryType == BINARY_TYPE_WOW)
115 {
116 /* Magic value for 16-bit apps */
117 Msg.Data.UpdateVdmEntry.ConsoleHandle = (HANDLE)-1;
118 }
119 else if (Msg.Data.UpdateVdmEntry.iTask)
120 {
121 /* No handle for true VDM */
122 Msg.Data.UpdateVdmEntry.ConsoleHandle = 0;
123 }
124 else
125 {
126 /* Otherwise, send the regular consoel handle */
127 Msg.Data.UpdateVdmEntry.ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
128 }
129
130 /* Finally write the index and binary type */
131 Msg.Data.UpdateVdmEntry.EntryIndex = UpdateIndex;
132 Msg.Data.UpdateVdmEntry.BinaryType = BinaryType;
133
134 /* Send the message to CSRSS */
135 Status = CsrClientCallServer(&Msg,
136 NULL,
137 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepUpdateVDMEntry),
138 sizeof(Msg));
139 if (!(NT_SUCCESS(Status)) || !(NT_SUCCESS(Msg.Status)))
140 {
141 /* Handle failure */
142 BaseSetLastNTError(Msg.Status);
143 return FALSE;
144 }
145
146 /* If this was an update, CSRSS returns a new wait handle */
147 if (UpdateIndex == VdmEntryUpdateProcess)
148 {
149 /* Return it to the caller */
150 *WaitHandle = Msg.Data.UpdateVdmEntry.WaitObjectForParent;
151 }
152
153 /* We made it */
154 return TRUE;
155 }
156
157 BOOL
158 WINAPI
159 BaseCheckForVDM(IN HANDLE ProcessHandle,
160 OUT LPDWORD ExitCode)
161 {
162 NTSTATUS Status;
163 EVENT_BASIC_INFORMATION EventBasicInfo;
164 CSR_API_MESSAGE Msg;
165
166 /* It's VDM if the process is actually a wait handle (an event) */
167 Status = NtQueryEvent(ProcessHandle,
168 EventBasicInformation,
169 &EventBasicInfo,
170 sizeof(EventBasicInfo),
171 NULL);
172 if (!NT_SUCCESS(Status)) return FALSE;
173
174 /* Setup the input parameters */
175 Msg.Data.GetVdmExitCode.ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
176 Msg.Data.GetVdmExitCode.hParent = ProcessHandle;
177
178 /* Call CSRSS */
179 Status = CsrClientCallServer(&Msg,
180 NULL,
181 CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCheckVDM /* BasepGetVDMExitCode */),
182 sizeof(Msg));
183 if (!NT_SUCCESS(Status)) return FALSE;
184
185 /* Get the exit code from the reply */
186 *ExitCode = Msg.Data.GetVdmExitCode.ExitCode;
187 return TRUE;
188 }
189
190 BOOL
191 WINAPI
192 BaseGetVdmConfigInfo(IN LPCWSTR Reserved,
193 IN ULONG DosSeqId,
194 IN ULONG BinaryType,
195 IN PUNICODE_STRING CmdLineString,
196 OUT PULONG VdmSize)
197 {
198 WCHAR Buffer[MAX_PATH];
199 WCHAR CommandLine[MAX_PATH * 2];
200 ULONG Length;
201
202 /* Clear the buffer in case we fail */
203 CmdLineString->Buffer = 0;
204
205 /* Always return the same size */
206 *VdmSize = 0x1000000;
207
208 /* Get the system directory */
209 Length = GetSystemDirectoryW(Buffer, MAX_PATH);
210 if (!(Length) || (Length >= MAX_PATH))
211 {
212 /* Eliminate no path or path too big */
213 SetLastError(ERROR_INVALID_NAME);
214 return FALSE;
215 }
216
217 /* Check if this is VDM with a DOS Sequence ID */
218 if (DosSeqId)
219 {
220 /* Build the VDM string for it */
221 _snwprintf(CommandLine,
222 sizeof(CommandLine),
223 L"\"%s\\ntvdm.exe\" -i%lx %s%c",
224 Buffer,
225 DosSeqId,
226 (BinaryType == 0x10) ? L" " : L"-w",
227 (BinaryType == 0x40) ? 's' : ' ');
228 }
229 else
230 {
231 /* Non-DOS, build the stirng for it without the task ID */
232 _snwprintf(CommandLine,
233 sizeof(CommandLine),
234 L"\"%s\\ntvdm.exe\" %s%c",
235 Buffer,
236 (BinaryType == 0x10) ? L" " : L"-w",
237 (BinaryType == 0x40) ? 's' : ' ');
238 }
239
240 /* Create the actual string */
241 return RtlCreateUnicodeString(CmdLineString, CommandLine);
242 }
243
244 UINT
245 WINAPI
246 BaseGetEnvNameType_U(IN PWCHAR Name,
247 IN ULONG NameLength)
248 {
249 PENV_INFO EnvInfo;
250 ULONG NameType, i;
251
252 /* Start by assuming unknown type */
253 NameType = 1;
254
255 /* Loop all the environment names */
256 for (i = 0; i < (sizeof(BasepEnvNameType) / sizeof(ENV_INFO)); i++)
257 {
258 /* Get this entry */
259 EnvInfo = &BasepEnvNameType[i];
260
261 /* Check if it matches the name */
262 if ((EnvInfo->NameLength == NameLength) &&
263 !(_wcsnicmp(EnvInfo->Name, Name, NameLength)))
264 {
265 /* It does, return the type */
266 NameType = EnvInfo->NameType;
267 break;
268 }
269 }
270
271 /* Return what we found, or unknown if nothing */
272 return NameType;
273 }
274
275 BOOL
276 NTAPI
277 BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv,
278 IN PUNICODE_STRING UnicodeEnv)
279 {
280 ULONG Dummy = 0;
281
282 /* Clear the ASCII buffer since Rtl creates this for us */
283 if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv);
284
285 /* The Unicode buffer is build by hand, though */
286 if (UnicodeEnv->Buffer)
287 {
288 /* So clear it through the API */
289 NtFreeVirtualMemory(NtCurrentProcess(),
290 (PVOID*)&UnicodeEnv->Buffer,
291 &Dummy,
292 MEM_RELEASE);
293 }
294
295 /* All done */
296 return TRUE;
297 }
298
299 BOOL
300 NTAPI
301 BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
302 IN PANSI_STRING AnsiEnv,
303 IN PUNICODE_STRING UnicodeEnv)
304 {
305 BOOL Result;
306 ULONG RegionSize, EnvironmentSize = 0;
307 PWCHAR p, Environment, NewEnvironment;
308 NTSTATUS Status;
309
310 /* Make sure we have both strings */
311 if (!(AnsiEnv) || !(UnicodeEnv))
312 {
313 /* Fail */
314 SetLastError(ERROR_INVALID_PARAMETER);
315 return FALSE;
316 }
317
318 /* Check if an environment was passed in */
319 if (!lpEnvironment)
320 {
321 /* Nope, create one */
322 Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment);
323 if (!NT_SUCCESS(Status)) goto Quickie;
324 }
325 else
326 {
327 /* Use the one we got */
328 Environment = lpEnvironment;
329 }
330
331 /* Do we have something now ? */
332 if (!Environment)
333 {
334 /* Still not, fail out */
335 SetLastError(ERROR_BAD_ENVIRONMENT);
336 goto Quickie;
337 }
338
339 /* Count how much space the whole environment takes */
340 p = Environment;
341 while ((*p++ != UNICODE_NULL) && (*p != UNICODE_NULL)) EnvironmentSize++;
342 EnvironmentSize += sizeof(UNICODE_NULL);
343
344 /* Allocate a new copy */
345 RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR);
346 if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(),
347 (PVOID*)&NewEnvironment,
348 0,
349 &RegionSize,
350 MEM_COMMIT,
351 PAGE_READWRITE)))
352 {
353 /* We failed, bail out */
354 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
355 NewEnvironment = NULL;
356 goto Quickie;
357 }
358
359 /* Begin parsing the new environment */
360 p = NewEnvironment;
361
362 /* FIXME: Code here */
363
364 /* Terminate it */
365 *p++ = UNICODE_NULL;
366
367 /* Initialize the unicode string to hold it */
368 EnvironmentSize = (p - NewEnvironment) * sizeof(WCHAR);
369 RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment, EnvironmentSize);
370 UnicodeEnv->Length = EnvironmentSize;
371
372 /* Create the ASCII version of it */
373 Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE);
374 if (!NT_SUCCESS(Status))
375 {
376 /* Set last error if conversion failure */
377 BaseSetLastNTError(Status);
378 }
379 else
380 {
381 /* Everything went okay, so return success */
382 Result = TRUE;
383 NewEnvironment = NULL;
384 }
385
386 Quickie:
387 /* Cleanup path starts here, start by destroying the envrionment copy */
388 if (!(lpEnvironment) && (Environment)) RtlDestroyEnvironment(Environment);
389
390 /* See if we are here due to failure */
391 if (NewEnvironment)
392 {
393 /* Initialize the paths to be empty */
394 RtlInitEmptyUnicodeString(UnicodeEnv, NULL, 0);
395 RtlInitEmptyAnsiString(AnsiEnv, NULL, 0);
396
397 /* Free the environment copy */
398 RegionSize = 0;
399 Status = NtFreeVirtualMemory(NtCurrentProcess(),
400 (PVOID*)&NewEnvironment,
401 &RegionSize,
402 MEM_RELEASE);
403 ASSERT(NT_SUCCESS(Status));
404 }
405
406 /* Return the result */
407 return Result;
408 }
409
410
411 /* Check whether a file is an OS/2 or a very old Windows executable
412 * by testing on import of KERNEL.
413 *
414 * FIXME: is reading the module imports the only way of discerning
415 * old Windows binaries from OS/2 ones ? At least it seems so...
416 */
417 static DWORD WINAPI
418 InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
419 {
420 DWORD CurPos;
421 LPWORD modtab = NULL;
422 LPSTR nametab = NULL;
423 DWORD Read, Ret;
424 int i;
425
426 Ret = BINARY_OS216;
427 CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
428
429 /* read modref table */
430 if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_modtab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
431 (!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
432 (!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
433 (Read != (DWORD)ne->ne_cmod * sizeof(WORD)))
434 {
435 goto broken;
436 }
437
438 /* read imported names table */
439 if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_imptab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
440 (!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
441 (!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
442 (Read != (DWORD)ne->ne_enttab - ne->ne_imptab))
443 {
444 goto broken;
445 }
446
447 for(i = 0; i < ne->ne_cmod; i++)
448 {
449 LPSTR module;
450 module = &nametab[modtab[i]];
451 if(!strncmp(&module[1], "KERNEL", module[0]))
452 {
453 /* very old windows file */
454 Ret = BINARY_WIN16;
455 goto done;
456 }
457 }
458
459 broken:
460 DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
461
462 done:
463 HeapFree(GetProcessHeap(), 0, modtab);
464 HeapFree(GetProcessHeap(), 0, nametab);
465 SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
466 return Ret;
467 }
468
469 static DWORD WINAPI
470 InternalGetBinaryType(HANDLE hFile)
471 {
472 union
473 {
474 struct
475 {
476 unsigned char magic[4];
477 unsigned char ignored[12];
478 unsigned short type;
479 } elf;
480 struct
481 {
482 unsigned long magic;
483 unsigned long cputype;
484 unsigned long cpusubtype;
485 unsigned long filetype;
486 } macho;
487 IMAGE_DOS_HEADER mz;
488 } Header;
489 char magic[4];
490 DWORD Read;
491
492 if((SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
493 (!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
494 (Read != sizeof(Header))))
495 {
496 return BINARY_UNKNOWN;
497 }
498
499 if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
500 {
501 /* FIXME: we don't bother to check byte order, architecture, etc. */
502 switch(Header.elf.type)
503 {
504 case 2:
505 return BINARY_UNIX_EXE;
506 case 3:
507 return BINARY_UNIX_LIB;
508 }
509 return BINARY_UNKNOWN;
510 }
511
512 /* Mach-o File with Endian set to Big Endian or Little Endian*/
513 if(Header.macho.magic == 0xFEEDFACE ||
514 Header.macho.magic == 0xCEFAEDFE)
515 {
516 switch(Header.macho.filetype)
517 {
518 case 0x8:
519 /* MH_BUNDLE */
520 return BINARY_UNIX_LIB;
521 }
522 return BINARY_UNKNOWN;
523 }
524
525 /* Not ELF, try DOS */
526 if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
527 {
528 /* We do have a DOS image so we will now try to seek into
529 * the file by the amount indicated by the field
530 * "Offset to extended header" and read in the
531 * "magic" field information at that location.
532 * This will tell us if there is more header information
533 * to read or not.
534 */
535 if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
536 (!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
537 (Read != sizeof(magic))))
538 {
539 return BINARY_DOS;
540 }
541
542 /* Reading the magic field succeeded so
543 * we will try to determine what type it is.
544 */
545 if(!memcmp(magic, "PE\0\0", sizeof(magic)))
546 {
547 IMAGE_FILE_HEADER FileHeader;
548 if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
549 (Read != sizeof(IMAGE_FILE_HEADER)))
550 {
551 return BINARY_DOS;
552 }
553
554 /* FIXME - detect 32/64 bit */
555
556 if(FileHeader.Characteristics & IMAGE_FILE_DLL)
557 return BINARY_PE_DLL32;
558 return BINARY_PE_EXE32;
559 }
560
561 if(!memcmp(magic, "NE", 1))
562 {
563 /* This is a Windows executable (NE) header. This can
564 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
565 * DOS program (running under a DOS extender). To decide
566 * which, we'll have to read the NE header.
567 */
568 IMAGE_OS2_HEADER ne;
569 if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
570 !ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
571 (Read != sizeof(IMAGE_OS2_HEADER)))
572 {
573 /* Couldn't read header, so abort. */
574 return BINARY_DOS;
575 }
576
577 switch(ne.ne_exetyp)
578 {
579 case 2:
580 return BINARY_WIN16;
581 case 5:
582 return BINARY_DOS;
583 default:
584 return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
585 }
586 }
587 return BINARY_DOS;
588 }
589 return BINARY_UNKNOWN;
590 }
591
592 /*
593 * @implemented
594 */
595 BOOL
596 WINAPI
597 GetBinaryTypeW (
598 LPCWSTR lpApplicationName,
599 LPDWORD lpBinaryType
600 )
601 {
602 HANDLE hFile;
603 DWORD BinType;
604
605 if(!lpApplicationName || !lpBinaryType)
606 {
607 SetLastError(ERROR_INVALID_PARAMETER);
608 return FALSE;
609 }
610
611 hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
612 OPEN_EXISTING, 0, 0);
613 if(hFile == INVALID_HANDLE_VALUE)
614 {
615 return FALSE;
616 }
617
618 BinType = InternalGetBinaryType(hFile);
619 CloseHandle(hFile);
620
621 switch(BinType)
622 {
623 case BINARY_UNKNOWN:
624 {
625 WCHAR *dot;
626
627 /*
628 * guess from filename
629 */
630 if(!(dot = wcsrchr(lpApplicationName, L'.')))
631 {
632 return FALSE;
633 }
634 if(!lstrcmpiW(dot, L".COM"))
635 {
636 *lpBinaryType = SCS_DOS_BINARY;
637 return TRUE;
638 }
639 if(!lstrcmpiW(dot, L".PIF"))
640 {
641 *lpBinaryType = SCS_PIF_BINARY;
642 return TRUE;
643 }
644 return FALSE;
645 }
646 case BINARY_PE_EXE32:
647 case BINARY_PE_DLL32:
648 {
649 *lpBinaryType = SCS_32BIT_BINARY;
650 return TRUE;
651 }
652 case BINARY_PE_EXE64:
653 case BINARY_PE_DLL64:
654 {
655 *lpBinaryType = SCS_64BIT_BINARY;
656 return TRUE;
657 }
658 case BINARY_WIN16:
659 {
660 *lpBinaryType = SCS_WOW_BINARY;
661 return TRUE;
662 }
663 case BINARY_OS216:
664 {
665 *lpBinaryType = SCS_OS216_BINARY;
666 return TRUE;
667 }
668 case BINARY_DOS:
669 {
670 *lpBinaryType = SCS_DOS_BINARY;
671 return TRUE;
672 }
673 case BINARY_UNIX_EXE:
674 case BINARY_UNIX_LIB:
675 {
676 return FALSE;
677 }
678 }
679
680 DPRINT1("Invalid binary type returned!\n", BinType);
681 return FALSE;
682 }
683
684 /*
685 * @implemented
686 */
687 BOOL
688 WINAPI
689 GetBinaryTypeA(IN LPCSTR lpApplicationName,
690 OUT LPDWORD lpBinaryType)
691 {
692 ANSI_STRING ApplicationNameString;
693 UNICODE_STRING ApplicationNameW;
694 BOOL StringAllocated = FALSE, Result;
695 NTSTATUS Status;
696
697 RtlInitAnsiString(&ApplicationNameString, lpApplicationName);
698
699 if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength)
700 {
701 StringAllocated = TRUE;
702 Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE);
703 }
704 else
705 {
706 Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE);
707 }
708
709 if (!NT_SUCCESS(Status))
710 {
711 BaseSetLastNTError(Status);
712 return FALSE;
713 }
714
715 if (StringAllocated)
716 {
717 Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType);
718 RtlFreeUnicodeString(&ApplicationNameW);
719 }
720 else
721 {
722 Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
723 }
724
725 return Result;
726 }
727
728 /*
729 * @unimplemented
730 */
731 BOOL
732 WINAPI
733 CmdBatNotification (
734 DWORD Unknown
735 )
736 {
737 STUB;
738 return FALSE;
739 }
740
741 /*
742 * @unimplemented
743 */
744 DWORD
745 WINAPI
746 ExitVDM (
747 DWORD Unknown0,
748 DWORD Unknown1
749 )
750 {
751 STUB;
752 return 0;
753 }
754
755
756 /*
757 * @unimplemented
758 */
759 DWORD
760 WINAPI
761 GetNextVDMCommand (
762 DWORD Unknown0
763 )
764 {
765 STUB;
766 return 0;
767 }
768
769
770 /*
771 * @unimplemented
772 */
773 DWORD
774 WINAPI
775 GetVDMCurrentDirectories (
776 DWORD Unknown0,
777 DWORD Unknown1
778 )
779 {
780 STUB;
781 return 0;
782 }
783
784
785 /*
786 * @unimplemented
787 */
788 BOOL
789 WINAPI
790 RegisterConsoleVDM (
791 DWORD Unknown0,
792 DWORD Unknown1,
793 DWORD Unknown2,
794 DWORD Unknown3,
795 DWORD Unknown4,
796 DWORD Unknown5,
797 DWORD Unknown6,
798 DWORD Unknown7,
799 DWORD Unknown8,
800 DWORD Unknown9,
801 DWORD Unknown10
802 )
803 {
804 STUB;
805 return FALSE;
806 }
807
808
809 /*
810 * @unimplemented
811 */
812 BOOL
813 WINAPI
814 RegisterWowBaseHandlers (
815 DWORD Unknown0
816 )
817 {
818 STUB;
819 return FALSE;
820 }
821
822
823 /*
824 * @unimplemented
825 */
826 BOOL
827 WINAPI
828 RegisterWowExec (
829 DWORD Unknown0
830 )
831 {
832 STUB;
833 return FALSE;
834 }
835
836
837 /*
838 * @unimplemented
839 */
840 BOOL
841 WINAPI
842 SetVDMCurrentDirectories (
843 DWORD Unknown0,
844 DWORD Unknown1
845 )
846 {
847 STUB;
848 return FALSE;
849 }
850
851 /*
852 * @unimplemented
853 */
854 DWORD
855 WINAPI
856 VDMConsoleOperation (
857 DWORD Unknown0,
858 DWORD Unknown1
859 )
860 {
861 STUB;
862 return 0;
863 }
864
865
866 /*
867 * @unimplemented
868 */
869 DWORD
870 WINAPI
871 VDMOperationStarted (
872 DWORD Unknown0
873 )
874 {
875 STUB;
876 return 0;
877 }