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