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