+/////////////////////////////////////////
+ /*
+ * Inspect the image to determine executable flavour
+ */
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING ApplicationNameString;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ IMAGE_DOS_HEADER DosHeader;
+ IO_STATUS_BLOCK Iosb;
+ LARGE_INTEGER Offset;
+ HANDLE hFile = NULL;
+
+ DPRINT("Inspecting Image Header for image type id\n");
+
+ // Find the application name
+ if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpApplicationName,
+ &ApplicationNameString, NULL, NULL)) {
+ return FALSE;
+ }
+ DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ApplicationNameString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ SecurityDescriptor);
+
+ // Try to open the executable
+ Status = NtOpenFile(&hFile,
+ SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_DELETE|FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
+
+ RtlFreeUnicodeString(&ApplicationNameString);
+
+ if (!NT_SUCCESS(Status)) {
+ DPRINT("Failed to open file\n");
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+
+ // Read the dos header
+ Offset.QuadPart = 0;
+ Status = ZwReadFile(hFile,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &DosHeader,
+ sizeof(DosHeader),
+ &Offset,
+ 0);
+
+ if (!NT_SUCCESS(Status)) {
+ DPRINT("Failed to read from file\n");
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+ if (Iosb.Information != sizeof(DosHeader)) {
+ DPRINT("Failed to read dos header from file\n");
+ SetLastErrorByStatus(STATUS_INVALID_IMAGE_FORMAT);
+ return FALSE;
+ }
+
+ // Check the DOS signature
+ if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
+ DPRINT("Failed dos magic check\n");
+ SetLastErrorByStatus(STATUS_INVALID_IMAGE_FORMAT);
+ return FALSE;
+ }
+ NtClose(hFile);
+
+ DPRINT("Launching VDM...\n");
+ return CreateProcessW(L"ntvdm.exe",
+ (LPWSTR)lpApplicationName,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ lpStartupInfo,
+ lpProcessInformation);