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