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