ReactOS 0.4.15-dev-5664-g3bf4ef6
osdetect.c File Reference
#include "precomp.h"
#include "ntverrsrc.h"
#include "bldrsup.h"
#include "filesup.h"
#include "genlist.h"
#include "partlist.h"
#include "arcname.h"
#include "osdetect.h"
#include <debug.h>
Include dependency graph for osdetect.c:

Go to the source code of this file.

Classes

struct  _ENUM_INSTALLS_DATA
 

Macros

#define NDEBUG
 

Typedefs

typedef struct _ENUM_INSTALLS_DATA ENUM_INSTALLS_DATA
 
typedef struct _ENUM_INSTALLS_DATAPENUM_INSTALLS_DATA
 

Functions

static BOOLEAN IsValidNTOSInstallation (IN PUNICODE_STRING SystemRootPath, OUT PUSHORT Machine OPTIONAL, OUT PUNICODE_STRING VendorName OPTIONAL)
 
static PNTOS_INSTALLATION FindExistingNTOSInstall (IN PGENERIC_LIST List, IN PCWSTR SystemRootArcPath OPTIONAL, IN PUNICODE_STRING SystemRootNtPath OPTIONAL)
 
static PNTOS_INSTALLATION AddNTOSInstallation (IN PGENERIC_LIST List, IN PCWSTR InstallationName, IN USHORT Machine, IN PCWSTR VendorName, IN PCWSTR SystemRootArcPath, IN PUNICODE_STRING SystemRootNtPath, IN PCWSTR PathComponent, IN ULONG DiskNumber, IN ULONG PartitionNumber, IN PPARTENTRY PartEntry OPTIONAL)
 
static NTSTATUS NTAPI EnumerateInstallations (IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
 
PCWSTR FindSubStrI (PCWSTR str, PCWSTR strSearch)
 
static BOOLEAN CheckForValidPEAndVendor (IN HANDLE RootDirectory OPTIONAL, IN PCWSTR PathNameToFile, OUT PUSHORT Machine, OUT PUNICODE_STRING VendorName)
 
static BOOLEAN IsValidNTOSInstallationByHandle (IN HANDLE SystemRootDirectory, OUT PUSHORT Machine OPTIONAL, OUT PUNICODE_STRING VendorName OPTIONAL)
 
static VOID FindNTOSInstallations (IN OUT PGENERIC_LIST List, IN PPARTLIST PartList, IN PPARTENTRY PartEntry)
 
FORCEINLINE BOOLEAN ShouldICheckThisPartition (IN PPARTENTRY PartEntry)
 
PGENERIC_LIST CreateNTOSInstallationsList (IN PPARTLIST PartList)
 

Variables

static const PCWSTR KnownVendors [] = { VENDOR_REACTOS, VENDOR_MICROSOFT }
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 22 of file osdetect.c.

Typedef Documentation

◆ ENUM_INSTALLS_DATA

◆ PENUM_INSTALLS_DATA

Function Documentation

◆ AddNTOSInstallation()

static PNTOS_INSTALLATION AddNTOSInstallation ( IN PGENERIC_LIST  List,
IN PCWSTR  InstallationName,
IN USHORT  Machine,
IN PCWSTR  VendorName,
IN PCWSTR  SystemRootArcPath,
IN PUNICODE_STRING  SystemRootNtPath,
IN PCWSTR  PathComponent,
IN ULONG  DiskNumber,
IN ULONG  PartitionNumber,
IN PPARTENTRY PartEntry  OPTIONAL 
)
static

Definition at line 609 of file osdetect.c.

620{
621 PNTOS_INSTALLATION NtOsInstall;
622 SIZE_T ArcPathLength, NtPathLength;
623
624 /* Is there already any installation with these settings? */
625 NtOsInstall = FindExistingNTOSInstall(List, SystemRootArcPath, SystemRootNtPath);
626 if (NtOsInstall)
627 {
628 DPRINT1("An NTOS installation with name \"%S\" from vendor \"%S\" already exists on disk #%d, partition #%d, in SystemRoot '%wZ'\n",
629 NtOsInstall->InstallationName, NtOsInstall->VendorName,
630 NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, &NtOsInstall->SystemNtPath);
631 //
632 // NOTE: We may use its "IsDefault" attribute, and only keep the entries that have IsDefault == TRUE...
633 // Setting IsDefault to TRUE would imply searching for the "Default" entry in the loader configuration file.
634 //
635 return NtOsInstall;
636 }
637
638 ArcPathLength = (wcslen(SystemRootArcPath) + 1) * sizeof(WCHAR);
639 // NtPathLength = ROUND_UP(SystemRootNtPath->Length + sizeof(UNICODE_NULL), sizeof(WCHAR));
640 NtPathLength = SystemRootNtPath->Length + sizeof(UNICODE_NULL);
641
642 /* None was found, so add a new one */
644 sizeof(*NtOsInstall) +
645 ArcPathLength + NtPathLength);
646 if (!NtOsInstall)
647 return NULL;
648
649 NtOsInstall->DiskNumber = DiskNumber;
650 NtOsInstall->PartitionNumber = PartitionNumber;
651 NtOsInstall->PartEntry = PartEntry;
652
653 NtOsInstall->Machine = Machine;
654
655 RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath,
656 (PWCHAR)(NtOsInstall + 1),
657 ArcPathLength);
658 RtlCopyMemory(NtOsInstall->SystemArcPath.Buffer, SystemRootArcPath, ArcPathLength);
659 NtOsInstall->SystemArcPath.Length = ArcPathLength - sizeof(UNICODE_NULL);
660
661 RtlInitEmptyUnicodeString(&NtOsInstall->SystemNtPath,
662 (PWCHAR)((ULONG_PTR)(NtOsInstall + 1) + ArcPathLength),
663 NtPathLength);
664 RtlCopyUnicodeString(&NtOsInstall->SystemNtPath, SystemRootNtPath);
665 NtOsInstall->PathComponent = NtOsInstall->SystemNtPath.Buffer +
666 (PathComponent - SystemRootNtPath->Buffer);
667
669 ARRAYSIZE(NtOsInstall->InstallationName),
670 InstallationName);
671
672 RtlStringCchCopyW(NtOsInstall->VendorName,
673 ARRAYSIZE(NtOsInstall->VendorName),
674 VendorName);
675
676 AppendGenericListEntry(List, NtOsInstall, FALSE);
677
678 return NtOsInstall;
679}
static const char VendorName[]
Definition: ParaNdis-Oid.c:36
HANDLE ProcessHeap
Definition: servman.c:15
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOLEAN AppendGenericListEntry(IN OUT PGENERIC_LIST List, IN PVOID Data, IN BOOLEAN Current)
Definition: genlist.c:62
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define UNICODE_NULL
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
static PNTOS_INSTALLATION FindExistingNTOSInstall(IN PGENERIC_LIST List, IN PCWSTR SystemRootArcPath OPTIONAL, IN PUNICODE_STRING SystemRootNtPath OPTIONAL)
Definition: osdetect.c:565
ULONG PartitionNumber
Definition: osdetect.h:24
WCHAR InstallationName[MAX_PATH]
Definition: osdetect.h:26
UNICODE_STRING SystemNtPath
Definition: osdetect.h:21
WCHAR VendorName[MAX_PATH]
Definition: osdetect.h:27
PPARTENTRY PartEntry
Definition: osdetect.h:25
UNICODE_STRING SystemArcPath
Definition: osdetect.h:20
PCWSTR PathComponent
Definition: osdetect.h:22
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by EnumerateInstallations().

◆ CheckForValidPEAndVendor()

static BOOLEAN CheckForValidPEAndVendor ( IN HANDLE RootDirectory  OPTIONAL,
IN PCWSTR  PathNameToFile,
OUT PUSHORT  Machine,
OUT PUNICODE_STRING  VendorName 
)
static

Definition at line 243 of file osdetect.c.

248{
251 HANDLE FileHandle, SectionHandle;
252 // SIZE_T ViewSize;
253 PVOID ViewBase;
254 PIMAGE_NT_HEADERS NtHeader;
255 PVOID VersionBuffer = NULL; // Read-only
256 PVOID pvData = NULL;
257 UINT BufLen = 0;
258
259 if (VendorName->MaximumLength < sizeof(UNICODE_NULL))
260 return FALSE;
261
262 *VendorName->Buffer = UNICODE_NULL;
263 VendorName->Length = 0;
264
265 Status = OpenAndMapFile(RootDirectory, PathNameToFile,
266 &FileHandle, &SectionHandle, &ViewBase,
267 NULL, FALSE);
268 if (!NT_SUCCESS(Status))
269 {
270 DPRINT1("Failed to open and map file '%S', Status 0x%08lx\n", PathNameToFile, Status);
271 return FALSE; // Status;
272 }
273
274 /* Make sure it's a valid NT PE file */
275 NtHeader = RtlImageNtHeader(ViewBase);
276 if (!NtHeader)
277 {
278 DPRINT1("File '%S' does not seem to be a valid NT PE file, bail out\n", PathNameToFile);
280 goto UnmapCloseFile;
281 }
282
283 /* Retrieve the target architecture of this PE module */
284 *Machine = NtHeader->FileHeader.Machine;
285
286 /*
287 * Search for a valid executable version and vendor.
288 * NOTE: The module is loaded as a data file, it should be marked as such.
289 */
290 Status = NtGetVersionResource((PVOID)((ULONG_PTR)ViewBase | 1), &VersionBuffer, NULL);
291 if (!NT_SUCCESS(Status))
292 {
293 DPRINT1("Failed to get version resource for file '%S', Status 0x%08lx\n", PathNameToFile, Status);
294 goto UnmapCloseFile;
295 }
296
297 Status = NtVerQueryValue(VersionBuffer, L"\\VarFileInfo\\Translation", &pvData, &BufLen);
298 if (NT_SUCCESS(Status))
299 {
300 USHORT wCodePage = 0, wLangID = 0;
302
303 wCodePage = LOWORD(*(ULONG*)pvData);
304 wLangID = HIWORD(*(ULONG*)pvData);
305
307 L"StringFileInfo\\%04X%04X\\CompanyName",
308 wCodePage, wLangID);
309
310 Status = NtVerQueryValue(VersionBuffer, FileInfo, &pvData, &BufLen);
311
312 /* Fixup the Status in case pvData is NULL */
313 if (NT_SUCCESS(Status) && !pvData)
315
316 if (NT_SUCCESS(Status) /*&& pvData*/)
317 {
318 /* BufLen includes the NULL terminator count */
319 DPRINT("Found version vendor: \"%S\" for file '%S'\n", pvData, PathNameToFile);
320
321 RtlStringCbCopyNW(VendorName->Buffer, VendorName->MaximumLength,
322 pvData, BufLen * sizeof(WCHAR));
323 VendorName->Length = (USHORT)wcslen(VendorName->Buffer) * sizeof(WCHAR);
324
325 Success = TRUE;
326 }
327 }
328
329 if (!NT_SUCCESS(Status))
330 DPRINT("No version vendor found for file '%S'\n", PathNameToFile);
331
332UnmapCloseFile:
333 /* Finally, unmap and close the file */
334 UnMapAndCloseFile(FileHandle, SectionHandle, ViewBase);
335
336 return Success;
337}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define RtlImageNtHeader
Definition: compat.h:806
#define MAX_PATH
Definition: compat.h:34
@ Success
Definition: eventcreate.c:712
#define BufLen
Definition: fatfs.h:167
NTSTATUS OpenAndMapFile(IN HANDLE RootDirectory OPTIONAL, IN PCWSTR PathNameToFile, OUT PHANDLE FileHandle, OUT PHANDLE SectionHandle, OUT PVOID *BaseAddress, OUT PULONG FileSize OPTIONAL, IN BOOLEAN ReadWriteAccess)
Definition: filesup.c:858
#define UnMapAndCloseFile(FileHandle, SectionHandle, BaseAddress)
Definition: filesup.h:108
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
Status
Definition: gdiplustypes.h:25
unsigned int ULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
#define STATUS_INVALID_IMAGE_FORMAT
Definition: ntstatus.h:359
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
NTSTRSAFEAPI RtlStringCbCopyNW(_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cbToCopy)
Definition: ntstrsafe.h:416
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NtGetVersionResource(IN PVOID BaseAddress, OUT PVOID *Resource, OUT PULONG ResourceSize OPTIONAL)
Definition: ntverrsrc.c:26
NTSTATUS NtVerQueryValue(IN const VOID *pBlock, IN PCWSTR lpSubBlock, OUT PVOID *lplpBuffer, OUT PUINT puLen)
Definition: ntverrsrc.c:174
#define LOWORD(l)
Definition: pedump.c:82
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:71
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
#define HIWORD(l)
Definition: typedefs.h:247
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3749

Referenced by IsValidNTOSInstallationByHandle().

◆ CreateNTOSInstallationsList()

PGENERIC_LIST CreateNTOSInstallationsList ( IN PPARTLIST  PartList)

Definition at line 777 of file osdetect.c.

779{
781 PLIST_ENTRY Entry, Entry2;
782 PDISKENTRY DiskEntry;
783 PPARTENTRY PartEntry;
784
786 if (List == NULL)
787 return NULL;
788
789 /* Loop each available disk ... */
790 Entry = PartList->DiskListHead.Flink;
791 while (Entry != &PartList->DiskListHead)
792 {
793 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
794 Entry = Entry->Flink;
795
796 DPRINT("Disk #%d\n", DiskEntry->DiskNumber);
797
798 /* ... and for each disk, loop each available partition */
799
800 /* First, the primary partitions */
801 Entry2 = DiskEntry->PrimaryPartListHead.Flink;
802 while (Entry2 != &DiskEntry->PrimaryPartListHead)
803 {
804 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
805 Entry2 = Entry2->Flink;
806
807 ASSERT(PartEntry->DiskEntry == DiskEntry);
808
809 DPRINT(" Primary Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, AutoCreate = %s, FormatState = %lu -- Should I check it? %s\n",
810 PartEntry->PartitionNumber, PartEntry->PartitionIndex,
811 PartEntry->PartitionType, PartEntry->LogicalPartition ? "TRUE" : "FALSE",
812 PartEntry->IsPartitioned ? "TRUE" : "FALSE",
813 PartEntry->New ? "Yes" : "No",
814 PartEntry->AutoCreate ? "Yes" : "No",
815 PartEntry->FormatState,
816 ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!");
817
818 if (ShouldICheckThisPartition(PartEntry))
819 FindNTOSInstallations(List, PartList, PartEntry);
820 }
821
822 /* Then, the logical partitions (present in the extended partition) */
823 Entry2 = DiskEntry->LogicalPartListHead.Flink;
824 while (Entry2 != &DiskEntry->LogicalPartListHead)
825 {
826 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
827 Entry2 = Entry2->Flink;
828
829 ASSERT(PartEntry->DiskEntry == DiskEntry);
830
831 DPRINT(" Logical Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, AutoCreate = %s, FormatState = %lu -- Should I check it? %s\n",
832 PartEntry->PartitionNumber, PartEntry->PartitionIndex,
833 PartEntry->PartitionType, PartEntry->LogicalPartition ? "TRUE" : "FALSE",
834 PartEntry->IsPartitioned ? "TRUE" : "FALSE",
835 PartEntry->New ? "Yes" : "No",
836 PartEntry->AutoCreate ? "Yes" : "No",
837 PartEntry->FormatState,
838 ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!");
839
840 if (ShouldICheckThisPartition(PartEntry))
841 FindNTOSInstallations(List, PartList, PartEntry);
842 }
843 }
844
845#ifndef NDEBUG
846 /**** Debugging: List all the collected installations ****/
847 DumpNTOSInstalls(List);
848#endif
849
850 return List;
851}
PGENERIC_LIST CreateGenericList(VOID)
Definition: genlist.c:20
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE BOOLEAN ShouldICheckThisPartition(IN PPARTENTRY PartEntry)
Definition: osdetect.c:763
static VOID FindNTOSInstallations(IN OUT PGENERIC_LIST List, IN PPARTLIST PartList, IN PPARTENTRY PartEntry)
Definition: osdetect.c:682
base of all file and directory entries
Definition: entries.h:83
LIST_ENTRY LogicalPartListHead
Definition: partlist.h:132
ULONG DiskNumber
Definition: partlist.h:111
LIST_ENTRY PrimaryPartListHead
Definition: partlist.h:131
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOLEAN IsPartitioned
Definition: partlist.h:66
UCHAR PartitionType
Definition: partlist.h:53
BOOLEAN AutoCreate
Definition: partlist.h:74
BOOLEAN New
Definition: partlist.h:71
struct _DISKENTRY * DiskEntry
Definition: partlist.h:46
BOOLEAN LogicalPartition
Definition: partlist.h:63
FORMATSTATE FormatState
Definition: partlist.h:61
ULONG PartitionNumber
Definition: partlist.h:55
ULONG PartitionIndex
Definition: partlist.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by LoadSetupData(), and UpgradeRepairPage().

◆ EnumerateInstallations()

static NTSTATUS NTAPI EnumerateInstallations ( IN BOOT_STORE_TYPE  Type,
IN PBOOT_STORE_ENTRY  BootEntry,
IN PVOID Parameter  OPTIONAL 
)
static

Definition at line 70 of file osdetect.c.

74{
76 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
77 PNTOS_INSTALLATION NtOsInstall;
78
79 ULONG DiskNumber = 0, PartitionNumber = 0;
81 PDISKENTRY DiskEntry = NULL;
82 PPARTENTRY PartEntry = NULL;
83
84 UNICODE_STRING SystemRootPath;
86
87 USHORT Machine;
89 WCHAR VendorNameBuffer[MAX_PATH];
90
91
92 /* We have a boot entry */
93
94 /* Check for supported boot type "Windows2003" */
95 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
96 RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
100 {
101 /* This is not a ReactOS entry */
102 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
103 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
104 DPRINT(" An installation '%S' of unsupported type %lu\n",
105 BootEntry->FriendlyName, BootEntry->OsOptionsLength);
106 /* Continue the enumeration */
107 return STATUS_SUCCESS;
108 }
109
110 /* BootType is Windows2003, now check OsLoadPath */
111 if (!Options->OsLoadPath || !*Options->OsLoadPath)
112 {
113 /* Certainly not a ReactOS installation */
114 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
115 /* Continue the enumeration */
116 return STATUS_SUCCESS;
117 }
118
119 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
120 BootEntry->FriendlyName, Options->OsLoadPath);
121 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
122 // BootEntry->FriendlyName, Options->OsLoadPath);
123
124 // TODO: Normalize the ARC path.
125
126 /*
127 * Check whether we already have an installation with this ARC path.
128 * If this is the case, stop there.
129 */
130 NtOsInstall = FindExistingNTOSInstall(Data->List, Options->OsLoadPath, NULL);
131 if (NtOsInstall)
132 {
133 DPRINT(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
134 NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemArcPath);
135 /* Continue the enumeration */
136 return STATUS_SUCCESS;
137 }
138
139 /*
140 * Convert the ARC path into an NT path, from which we will deduce
141 * the real disk drive & partition on which the candidate installation
142 * resides, as well verifying whether it is indeed an NTOS installation.
143 */
144 RtlInitEmptyUnicodeString(&SystemRootPath, SystemRoot, sizeof(SystemRoot));
145 if (!ArcPathToNtPath(&SystemRootPath, Options->OsLoadPath, Data->PartList))
146 {
147 DPRINT1("ArcPathToNtPath(%S) failed, skip the installation.\n", Options->OsLoadPath);
148 /* Continue the enumeration */
149 return STATUS_SUCCESS;
150 }
151
152 DPRINT("ArcPathToNtPath() succeeded: '%S' --> '%wZ'\n",
153 Options->OsLoadPath, &SystemRootPath);
154
155 /*
156 * Check whether we already have an installation with this NT path.
157 * If this is the case, stop there.
158 */
159 NtOsInstall = FindExistingNTOSInstall(Data->List, NULL /*Options->OsLoadPath*/, &SystemRootPath);
160 if (NtOsInstall)
161 {
162 DPRINT1(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
163 NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemNtPath);
164 /* Continue the enumeration */
165 return STATUS_SUCCESS;
166 }
167
168 DPRINT("EnumerateInstallations: SystemRootPath: '%wZ'\n", &SystemRootPath);
169
170 /* Check if this is a valid NTOS installation; stop there if it isn't one */
171 RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
172 if (!IsValidNTOSInstallation(&SystemRootPath, &Machine, &VendorName))
173 {
174 /* Continue the enumeration */
175 return STATUS_SUCCESS;
176 }
177
178 DPRINT("Found a valid NTOS installation in SystemRoot ARC path '%S', NT path '%wZ'\n",
179 Options->OsLoadPath, &SystemRootPath);
180
181 /* From the NT path, compute the disk, partition and path components */
182 if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber, &PartitionNumber, &PathComponent))
183 {
184 DPRINT("SystemRootPath = '%wZ' points to disk #%d, partition #%d, path '%S'\n",
185 &SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
186
187 /* Retrieve the corresponding disk and partition */
188 if (!GetDiskOrPartition(Data->PartList, DiskNumber, PartitionNumber, &DiskEntry, &PartEntry))
189 {
190 DPRINT1("GetDiskOrPartition(disk #%d, partition #%d) failed\n",
191 DiskNumber, PartitionNumber);
192 }
193 }
194 else
195 {
196 DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n", &SystemRootPath);
197 }
198
199 /* Add the discovered NTOS installation into the list */
201 BootEntry->FriendlyName,
202 Machine,
203 VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
204 Options->OsLoadPath,
205 &SystemRootPath, PathComponent,
206 DiskNumber, PartitionNumber, PartEntry);
207
208 /* Continue the enumeration */
209 return STATUS_SUCCESS;
210}
BOOLEAN ArcPathToNtPath(OUT PUNICODE_STRING NtPath, IN PCWSTR ArcPath, IN PPARTLIST PartList OPTIONAL)
Definition: arcname.c:819
struct _NTOS_OPTIONS * PNTOS_OPTIONS
#define NTOS_OPTIONS_SIGNATURE
Definition: bldrsup.h:98
static const WCHAR SystemRoot[]
Definition: reg.c:38
static const WCHAR Signature[]
Definition: parser.c:141
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
BOOLEAN NtPathToDiskPartComponents(IN PCWSTR NtPath, OUT PULONG pDiskNumber, OUT PULONG pPartNumber, OUT PCWSTR *PathComponent OPTIONAL)
Definition: filesup.c:771
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:84
_In_ PVOID Parameter
Definition: ldrtypes.h:241
if(dx< 0)
Definition: linetemp.h:194
static PNTOS_INSTALLATION AddNTOSInstallation(IN PGENERIC_LIST List, IN PCWSTR InstallationName, IN USHORT Machine, IN PCWSTR VendorName, IN PCWSTR SystemRootArcPath, IN PUNICODE_STRING SystemRootNtPath, IN PCWSTR PathComponent, IN ULONG DiskNumber, IN ULONG PartitionNumber, IN PPARTENTRY PartEntry OPTIONAL)
Definition: osdetect.c:609
struct _ENUM_INSTALLS_DATA * PENUM_INSTALLS_DATA
static BOOLEAN IsValidNTOSInstallation(IN PUNICODE_STRING SystemRootPath, OUT PUSHORT Machine OPTIONAL, OUT PUNICODE_STRING VendorName OPTIONAL)
Definition: osdetect.c:500
BOOLEAN GetDiskOrPartition(IN PPARTLIST List, IN ULONG DiskNumber, IN ULONG PartitionNumber OPTIONAL, OUT PDISKENTRY *pDiskEntry, OUT PPARTENTRY *pPartEntry OPTIONAL)
Definition: partlist.c:2143
#define STATUS_SUCCESS
Definition: shellext.h:65
const uint16_t * PCWSTR
Definition: typedefs.h:57
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534

Referenced by FindNTOSInstallations().

◆ FindExistingNTOSInstall()

static PNTOS_INSTALLATION FindExistingNTOSInstall ( IN PGENERIC_LIST  List,
IN PCWSTR SystemRootArcPath  OPTIONAL,
IN PUNICODE_STRING SystemRootNtPath  OPTIONAL 
)
static

Definition at line 565 of file osdetect.c.

570{
572 PNTOS_INSTALLATION NtOsInstall;
573 UNICODE_STRING SystemArcPath;
574
575 /*
576 * We search either via ARC path or NT path.
577 * If both pointers are NULL then we fail straight away.
578 */
579 if (!SystemRootArcPath && !SystemRootNtPath)
580 return NULL;
581
582 RtlInitUnicodeString(&SystemArcPath, SystemRootArcPath);
583
585 {
587
588 /*
589 * Note that if both ARC paths are equal, then the corresponding
590 * NT paths must be the same. However, two ARC paths may be different
591 * but resolve into the same NT path.
592 */
593 if ( (SystemRootArcPath &&
595 &SystemArcPath, TRUE)) ||
596 (SystemRootNtPath &&
598 SystemRootNtPath, TRUE)) )
599 {
600 /* Found it! */
601 return NtOsInstall;
602 }
603 }
604
605 return NULL;
606}
PGENERIC_LIST_ENTRY GetFirstListEntry(IN PGENERIC_LIST List)
Definition: genlist.c:104
PVOID GetListEntryData(IN PGENERIC_LIST_ENTRY Entry)
Definition: genlist.c:126
PGENERIC_LIST_ENTRY GetNextListEntry(IN PGENERIC_LIST_ENTRY Entry)
Definition: genlist.c:114
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
struct _NTOS_INSTALLATION * PNTOS_INSTALLATION
Definition: genlist.h:11

Referenced by AddNTOSInstallation(), and EnumerateInstallations().

◆ FindNTOSInstallations()

static VOID FindNTOSInstallations ( IN OUT PGENERIC_LIST  List,
IN PPARTLIST  PartList,
IN PPARTENTRY  PartEntry 
)
static

Definition at line 682 of file osdetect.c.

686{
688 ULONG DiskNumber = PartEntry->DiskEntry->DiskNumber;
689 ULONG PartitionNumber = PartEntry->PartitionNumber;
690 HANDLE PartitionDirectoryHandle;
693 UNICODE_STRING PartitionRootPath;
695 PVOID BootStoreHandle;
698 WCHAR PathBuffer[MAX_PATH];
699
700 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
701
702 /* Set PartitionRootPath */
703 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
704 L"\\Device\\Harddisk%lu\\Partition%lu\\",
705 DiskNumber, PartitionNumber);
706 RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
707 DPRINT("FindNTOSInstallations: PartitionRootPath: '%wZ'\n", &PartitionRootPath);
708
709 /* Open the partition */
711 &PartitionRootPath,
713 NULL,
714 NULL);
715 Status = NtOpenFile(&PartitionDirectoryHandle,
721 if (!NT_SUCCESS(Status))
722 {
723 DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", &PartitionRootPath, Status);
724 return;
725 }
726
727 Data.List = List;
728 Data.PartList = PartList;
729
730 /* Try to see whether we recognize some NT boot loaders */
731 for (Type = FreeLdr; Type < BldrTypeMax; ++Type)
732 {
733 Status = FindBootStore(PartitionDirectoryHandle, Type, &Version);
734 if (!NT_SUCCESS(Status))
735 {
736 /* The loader does not exist, continue with another one */
737 DPRINT("Loader type '%d' does not exist, or an error happened (Status 0x%08lx), continue with another one...\n",
738 Type, Status);
739 continue;
740 }
741
742 /* The loader exists, try to enumerate its boot entries */
743 DPRINT("Analyze the OS installations for loader type '%d' in disk #%d, partition #%d\n",
744 Type, DiskNumber, PartitionNumber);
745
746 Status = OpenBootStoreByHandle(&BootStoreHandle, PartitionDirectoryHandle, Type, FALSE);
747 if (!NT_SUCCESS(Status))
748 {
749 DPRINT1("Could not open the NTOS boot store of type '%d' (Status 0x%08lx), continue with another one...\n",
750 Type, Status);
751 continue;
752 }
754 CloseBootStore(BootStoreHandle);
755 }
756
757 /* Close the partition */
758 NtClose(PartitionDirectoryHandle);
759}
Type
Definition: Type.h:7
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
NTSTATUS OpenBootStoreByHandle(OUT PVOID *Handle, IN HANDLE PartitionDirectoryHandle, IN BOOT_STORE_TYPE Type, IN BOOLEAN CreateNew)
Definition: bldrsup.c:664
NTSTATUS EnumerateBootStoreEntries(IN PVOID Handle, IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine, IN PVOID Parameter OPTIONAL)
Definition: bldrsup.c:1486
NTSTATUS FindBootStore(IN HANDLE PartitionDirectoryHandle, IN BOOT_STORE_TYPE Type, OUT PULONG VersionNumber OPTIONAL)
Definition: bldrsup.c:137
NTSTATUS CloseBootStore(IN PVOID Handle)
Definition: bldrsup.c:754
@ BldrTypeMax
Definition: bldrsup.h:18
@ FreeLdr
Definition: bldrsup.h:15
enum _BOOT_STORE_TYPE BOOT_STORE_TYPE
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define FILE_SHARE_READ
Definition: compat.h:136
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3952
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
#define FILE_TRAVERSE
Definition: nt_native.h:643
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
static NTSTATUS NTAPI EnumerateInstallations(IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
Definition: osdetect.c:70
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469

Referenced by CreateNTOSInstallationsList().

◆ FindSubStrI()

PCWSTR FindSubStrI ( PCWSTR  str,
PCWSTR  strSearch 
)

Definition at line 217 of file osdetect.c.

218{
219 PCWSTR cp = str;
220 PCWSTR s1, s2;
221
222 if (!*strSearch)
223 return str;
224
225 while (*cp)
226 {
227 s1 = cp;
228 s2 = strSearch;
229
230 while (*s1 && *s2 && (towupper(*s1) == towupper(*s2)))
231 ++s1, ++s2;
232
233 if (!*s2)
234 return cp;
235
236 ++cp;
237 }
238
239 return NULL;
240}
POINT cp
Definition: magnifier.c:59
struct S1 s1
struct S2 s2
const WCHAR * str
#define towupper(c)
Definition: wctype.h:99

Referenced by IsValidNTOSInstallationByHandle().

◆ IsValidNTOSInstallation()

static BOOLEAN IsValidNTOSInstallation ( IN PUNICODE_STRING  SystemRootPath,
OUT PUSHORT Machine  OPTIONAL,
OUT PUNICODE_STRING VendorName  OPTIONAL 
)
static

Definition at line 500 of file osdetect.c.

504{
508 HANDLE SystemRootDirectory;
510
511 /* Open SystemRootPath */
513 SystemRootPath,
515 NULL,
516 NULL);
517 Status = NtOpenFile(&SystemRootDirectory,
523 if (!NT_SUCCESS(Status))
524 {
525 DPRINT1("Failed to open SystemRoot '%wZ', Status 0x%08lx\n", SystemRootPath, Status);
526 return FALSE;
527 }
528
529 Success = IsValidNTOSInstallationByHandle(SystemRootDirectory,
530 Machine, VendorName);
531
532 /* Done! */
533 NtClose(SystemRootDirectory);
534 return Success;
535}
static BOOLEAN IsValidNTOSInstallationByHandle(IN HANDLE SystemRootDirectory, OUT PUSHORT Machine OPTIONAL, OUT PUNICODE_STRING VendorName OPTIONAL)
Definition: osdetect.c:346

Referenced by EnumerateInstallations().

◆ IsValidNTOSInstallationByHandle()

static BOOLEAN IsValidNTOSInstallationByHandle ( IN HANDLE  SystemRootDirectory,
OUT PUSHORT Machine  OPTIONAL,
OUT PUNICODE_STRING VendorName  OPTIONAL 
)
static

Definition at line 346 of file osdetect.c.

350{
352 PCWSTR PathName;
353 USHORT i;
354 USHORT LocalMachine;
355 UNICODE_STRING LocalVendorName;
356 WCHAR VendorNameBuffer[MAX_PATH];
357
358 /* Check for VendorName validity */
359 if (VendorName->MaximumLength < sizeof(UNICODE_NULL))
360 {
361 /* Don't use it, invalidate the pointer */
363 }
364 else
365 {
366 /* Zero it out */
367 *VendorName->Buffer = UNICODE_NULL;
368 VendorName->Length = 0;
369 }
370
371 /* Check for the existence of \SystemRoot\System32 */
372 PathName = L"System32\\";
373 if (!DoesDirExist(SystemRootDirectory, PathName))
374 {
375 // DPRINT1("Failed to open directory '%S', Status 0x%08lx\n", PathName, Status);
376 return FALSE;
377 }
378
379 /* Check for the existence of \SystemRoot\System32\drivers */
380 PathName = L"System32\\drivers\\";
381 if (!DoesDirExist(SystemRootDirectory, PathName))
382 {
383 // DPRINT1("Failed to open directory '%S', Status 0x%08lx\n", PathName, Status);
384 return FALSE;
385 }
386
387 /* Check for the existence of \SystemRoot\System32\config */
388 PathName = L"System32\\config\\";
389 if (!DoesDirExist(SystemRootDirectory, PathName))
390 {
391 // DPRINT1("Failed to open directory '%S', Status 0x%08lx\n", PathName, Status);
392 return FALSE;
393 }
394
395#if 0
396 /*
397 * Check for the existence of SYSTEM and SOFTWARE hives in \SystemRoot\System32\config
398 * (but we don't check here whether they are actually valid).
399 */
400 PathName = L"System32\\config\\SYSTEM";
401 if (!DoesFileExist(SystemRootDirectory, PathName))
402 {
403 // DPRINT1("Failed to open file '%S', Status 0x%08lx\n", PathName, Status);
404 return FALSE;
405 }
406 PathName = L"System32\\config\\SOFTWARE";
407 if (!DoesFileExist(SystemRootDirectory, PathName))
408 {
409 // DPRINT1("Failed to open file '%S', Status 0x%08lx\n", PathName, Status);
410 return FALSE;
411 }
412#endif
413
414 RtlInitEmptyUnicodeString(&LocalVendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
415
416 /* Check for the existence of \SystemRoot\System32\ntoskrnl.exe and retrieves its vendor name */
417 PathName = L"System32\\ntoskrnl.exe";
418 Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalMachine, &LocalVendorName);
419 if (!Success)
420 DPRINT1("Kernel executable '%S' is either not a PE file, or does not have any vendor?\n", PathName);
421
422 /*
423 * The kernel gives the OS its flavour. If we failed due to the absence of
424 * ntoskrnl.exe this might be due to the fact this particular installation
425 * uses a custom kernel that has a different name, overridden in the boot
426 * parameters. We then rely on the existence of ntdll.dll, which cannot be
427 * renamed on a valid NT system.
428 */
429 if (Success)
430 {
431 for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
432 {
433 Success = !!FindSubStrI(LocalVendorName.Buffer, KnownVendors[i]);
434 if (Success)
435 {
436 /* We have found a correct vendor combination */
437 DPRINT("IsValidNTOSInstallation: We've got an NTOS installation from %S !\n", KnownVendors[i]);
438 break;
439 }
440 }
441
442 /* Return the target architecture */
443 if (Machine)
444 {
445 /* Copy the value and invalidate the pointer */
446 *Machine = LocalMachine;
447 Machine = NULL;
448 }
449
450 /* Return the vendor name */
451 if (VendorName)
452 {
453 /* Copy the string and invalidate the pointer */
454 RtlCopyUnicodeString(VendorName, &LocalVendorName);
456 }
457 }
458
459 /* OPTIONAL: Check for the existence of \SystemRoot\System32\ntkrnlpa.exe */
460
461 /* Check for the existence of \SystemRoot\System32\ntdll.dll and retrieves its vendor name */
462 PathName = L"System32\\ntdll.dll";
463 Success = CheckForValidPEAndVendor(SystemRootDirectory, PathName, &LocalMachine, &LocalVendorName);
464 if (!Success)
465 DPRINT1("User-mode DLL '%S' is either not a PE file, or does not have any vendor?\n", PathName);
466
467 if (Success)
468 {
469 for (i = 0; i < ARRAYSIZE(KnownVendors); ++i)
470 {
471 if (!!FindSubStrI(LocalVendorName.Buffer, KnownVendors[i]))
472 {
473 /* We have found a correct vendor combination */
474 DPRINT("IsValidNTOSInstallation: The user-mode DLL '%S' is from %S\n", PathName, KnownVendors[i]);
475 break;
476 }
477 }
478
479 /* Return the target architecture if not already obtained */
480 if (Machine)
481 {
482 /* Copy the value and invalidate the pointer */
483 *Machine = LocalMachine;
484 Machine = NULL;
485 }
486
487 /* Return the vendor name if not already obtained */
488 if (VendorName)
489 {
490 /* Copy the string and invalidate the pointer */
491 RtlCopyUnicodeString(VendorName, &LocalVendorName);
493 }
494 }
495
496 return Success;
497}
#define DoesDirExist(RootDirectory, DirName)
Definition: filesup.h:74
#define DoesFileExist(RootDirectory, FileName)
Definition: filesup.h:77
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const PCWSTR KnownVendors[]
Definition: osdetect.c:29
static BOOLEAN CheckForValidPEAndVendor(IN HANDLE RootDirectory OPTIONAL, IN PCWSTR PathNameToFile, OUT PUSHORT Machine, OUT PUNICODE_STRING VendorName)
Definition: osdetect.c:243
PCWSTR FindSubStrI(PCWSTR str, PCWSTR strSearch)
Definition: osdetect.c:217

Referenced by IsValidNTOSInstallation().

◆ ShouldICheckThisPartition()

FORCEINLINE BOOLEAN ShouldICheckThisPartition ( IN PPARTENTRY  PartEntry)

Definition at line 763 of file osdetect.c.

765{
766 if (!PartEntry)
767 return FALSE;
768
769 return PartEntry->IsPartitioned &&
770 !IsContainerPartition(PartEntry->PartitionType) /* alternatively: PartEntry->PartitionNumber != 0 */ &&
771 !PartEntry->New &&
772 (PartEntry->FormatState == Preformatted /* || PartEntry->FormatState == Formatted */);
773}
@ Preformatted
Definition: partlist.h:37
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:316

Referenced by CreateNTOSInstallationsList().

Variable Documentation

◆ KnownVendors

const PCWSTR KnownVendors[] = { VENDOR_REACTOS, VENDOR_MICROSOFT }
static

Definition at line 29 of file osdetect.c.

Referenced by IsValidNTOSInstallationByHandle().