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