ReactOS 0.4.16-dev-753-g705a985
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)
 
static NTSTATUS NTAPI EnumerateInstallations (IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
 
PCWSTR NTAPI FindSubStrI (_In_ PCWSTR str, _In_ PCWSTR strSearch)
 Finds the first occurrence of a sub-string 'strSearch' inside 'str', using case-insensitive comparisons.
 
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 (_Inout_ PGENERIC_LIST List, _In_ PPARTLIST PartList, _In_ PVOLENTRY Volume)
 
PGENERIC_LIST NTAPI CreateNTOSInstallationsList (_In_ PPARTLIST PartList)
 Create a list of available NT OS installations on the computer, by searching for recognized ones on each recognized storage volume.
 

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 
)
static

Definition at line 613 of file osdetect.c.

623{
624 PNTOS_INSTALLATION NtOsInstall;
625 SIZE_T ArcPathLength, NtPathLength;
626
627 /* Is there already any installation with these settings? */
628 NtOsInstall = FindExistingNTOSInstall(List, SystemRootArcPath, SystemRootNtPath);
629 if (NtOsInstall)
630 {
631 DPRINT1("An NTOS installation with name \"%S\" from vendor \"%S\" already exists on disk #%d, partition #%d, in SystemRoot '%wZ'\n",
632 NtOsInstall->InstallationName, NtOsInstall->VendorName,
633 NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber, &NtOsInstall->SystemNtPath);
634 //
635 // NOTE: We may use its "IsDefault" attribute, and only keep the entries that have IsDefault == TRUE...
636 // Setting IsDefault to TRUE would imply searching for the "Default" entry in the loader configuration file.
637 //
638 return NtOsInstall;
639 }
640
641 ArcPathLength = (wcslen(SystemRootArcPath) + 1) * sizeof(WCHAR);
642 // NtPathLength = ROUND_UP(SystemRootNtPath->Length + sizeof(UNICODE_NULL), sizeof(WCHAR));
643 NtPathLength = SystemRootNtPath->Length + sizeof(UNICODE_NULL);
644
645 /* None was found, so add a new one */
647 sizeof(*NtOsInstall) +
648 ArcPathLength + NtPathLength);
649 if (!NtOsInstall)
650 return NULL;
651
652 NtOsInstall->DiskNumber = DiskNumber;
653 NtOsInstall->PartitionNumber = PartitionNumber;
654 NtOsInstall->Machine = Machine;
655
656 RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath,
657 (PWCHAR)(NtOsInstall + 1),
658 ArcPathLength);
659 RtlCopyMemory(NtOsInstall->SystemArcPath.Buffer, SystemRootArcPath, ArcPathLength);
660 NtOsInstall->SystemArcPath.Length = ArcPathLength - sizeof(UNICODE_NULL);
661
662 RtlInitEmptyUnicodeString(&NtOsInstall->SystemNtPath,
663 (PWCHAR)((ULONG_PTR)(NtOsInstall + 1) + ArcPathLength),
664 NtPathLength);
665 RtlCopyUnicodeString(&NtOsInstall->SystemNtPath, SystemRootNtPath);
666 NtOsInstall->PathComponent = NtOsInstall->SystemNtPath.Buffer +
667 (PathComponent - SystemRootNtPath->Buffer);
668
670 ARRAYSIZE(NtOsInstall->InstallationName),
671 InstallationName);
672
673 RtlStringCchCopyW(NtOsInstall->VendorName,
674 ARRAYSIZE(NtOsInstall->VendorName),
675 VendorName);
676
677 AppendGenericListEntry(List, NtOsInstall, FALSE);
678
679 return NtOsInstall;
680}
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:616
#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 NTAPI AppendGenericListEntry(IN OUT PGENERIC_LIST List, IN PVOID Data, IN BOOLEAN Current)
Definition: genlist.c:65
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:569
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
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 247 of file osdetect.c.

252{
255 HANDLE FileHandle, SectionHandle;
256 // SIZE_T ViewSize;
257 PVOID ViewBase;
258 PIMAGE_NT_HEADERS NtHeader;
259 PVOID VersionBuffer = NULL; // Read-only
260 PVOID pvData = NULL;
261 UINT BufLen = 0;
262
263 if (VendorName->MaximumLength < sizeof(UNICODE_NULL))
264 return FALSE;
265
266 *VendorName->Buffer = UNICODE_NULL;
267 VendorName->Length = 0;
268
269 Status = OpenAndMapFile(RootDirectory, PathNameToFile,
271 &SectionHandle, &ViewBase, FALSE);
272 if (!NT_SUCCESS(Status))
273 {
274 DPRINT1("Failed to open and map file '%S', Status 0x%08lx\n", PathNameToFile, Status);
275 return FALSE; // Status;
276 }
277
278 /* Make sure it's a valid NT PE file */
279 NtHeader = RtlImageNtHeader(ViewBase);
280 if (!NtHeader)
281 {
282 DPRINT1("File '%S' does not seem to be a valid NT PE file, bail out\n", PathNameToFile);
284 goto UnmapCloseFile;
285 }
286
287 /* Retrieve the target architecture of this PE module */
288 *Machine = NtHeader->FileHeader.Machine;
289
290 /*
291 * Search for a valid executable version and vendor.
292 * NOTE: The module is loaded as a data file, it should be marked as such.
293 */
294 Status = NtGetVersionResource((PVOID)((ULONG_PTR)ViewBase | 1), &VersionBuffer, NULL);
295 if (!NT_SUCCESS(Status))
296 {
297 DPRINT1("Failed to get version resource for file '%S', Status 0x%08lx\n", PathNameToFile, Status);
298 goto UnmapCloseFile;
299 }
300
301 Status = NtVerQueryValue(VersionBuffer, L"\\VarFileInfo\\Translation", &pvData, &BufLen);
302 if (NT_SUCCESS(Status))
303 {
304 USHORT wCodePage = 0, wLangID = 0;
306
307 wCodePage = LOWORD(*(ULONG*)pvData);
308 wLangID = HIWORD(*(ULONG*)pvData);
309
311 L"StringFileInfo\\%04X%04X\\CompanyName",
312 wCodePage, wLangID);
313
314 Status = NtVerQueryValue(VersionBuffer, FileInfo, &pvData, &BufLen);
315
316 /* Fixup the Status in case pvData is NULL */
317 if (NT_SUCCESS(Status) && !pvData)
319
320 if (NT_SUCCESS(Status) /*&& pvData*/)
321 {
322 /* BufLen includes the NULL terminator count */
323 DPRINT("Found version vendor: \"%S\" for file '%S'\n", pvData, PathNameToFile);
324
325 RtlStringCbCopyNW(VendorName->Buffer, VendorName->MaximumLength,
326 pvData, BufLen * sizeof(WCHAR));
327 VendorName->Length = (USHORT)wcslen(VendorName->Buffer) * sizeof(WCHAR);
328
329 Success = TRUE;
330 }
331 }
332
333 if (!NT_SUCCESS(Status))
334 DPRINT("No version vendor found for file '%S'\n", PathNameToFile);
335
336UnmapCloseFile:
337 /* Finally, unmap and close the file */
338 UnMapAndCloseFile(FileHandle, SectionHandle, ViewBase);
339
340 return Success;
341}
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:33
#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_opt_ HANDLE RootDirectory, _In_ PCWSTR PathNameToFile, _Out_opt_ PHANDLE FileHandle, _Out_opt_ PULONG FileSize, _Out_ PHANDLE SectionHandle, _Out_ PVOID *BaseAddress, _In_ BOOLEAN ReadWriteAccess)
Opens and maps a file in memory.
Definition: filesup.c:879
#define UnMapAndCloseFile(FileHandle, SectionHandle, BaseAddress)
Definition: filesup.h:121
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
Status
Definition: gdiplustypes.h:25
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:73
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3749

Referenced by IsValidNTOSInstallationByHandle().

◆ CreateNTOSInstallationsList()

PGENERIC_LIST NTAPI CreateNTOSInstallationsList ( _In_ PPARTLIST  PartList)

Create a list of available NT OS installations on the computer, by searching for recognized ones on each recognized storage volume.

Definition at line 768 of file osdetect.c.

770{
775
777 if (!List)
778 return NULL;
779
780 /* Loop each available volume */
781 for (Entry = PartList->VolumesList.Flink;
782 Entry != &PartList->VolumesList;
783 Entry = Entry->Flink)
784 {
785 Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
786 /* Valid OS installations can be found only on basic volumes */
787 if (!Volume->PartEntry) // TODO: In the future: (!Volume->IsSimpleVolume)
788 continue;
789
790 CheckVolume = (!Volume->New && (Volume->FormatState == Formatted));
791
792#ifndef NDEBUG
793 {
794 PPARTENTRY PartEntry = Volume->PartEntry;
795 ASSERT(PartEntry->Volume == Volume);
796 DPRINT("Volume %S (%c%c) on Disk #%d, Partition #%d (%s), "
797 "index %d - Type 0x%02x, IsVolNew = %s, FormatState = %lu -- Should I check it? %s\n",
798 Volume->Info.DeviceName,
799 !Volume->Info.DriveLetter ? '-' : (CHAR)Volume->Info.DriveLetter,
800 !Volume->Info.DriveLetter ? '-' : ':',
801 PartEntry->DiskEntry->DiskNumber,
802 PartEntry->PartitionNumber,
803 PartEntry->LogicalPartition ? "Logical" : "Primary",
804 PartEntry->PartitionIndex,
805 PartEntry->PartitionType,
806 Volume->New ? "Yes" : "No",
807 Volume->FormatState,
808 CheckVolume ? "YES!" : "NO!");
809 }
810#endif
811
812 if (CheckVolume)
814 }
815
816#ifndef NDEBUG
817 /**** Debugging: List all the collected installations ****/
818 DumpNTOSInstalls(List);
819#endif
820
821 return List;
822}
static NTSTATUS CheckVolume(IN PCWSTR VolumePath, IN LONG TimeOut, IN BOOLEAN CheckOnlyIfDirty)
Definition: autochk.c:391
PGENERIC_LIST NTAPI CreateGenericList(VOID)
Definition: genlist.c:21
@ Formatted
Definition: partlist.h:37
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define ASSERT(a)
Definition: mode.c:44
static VOID FindNTOSInstallations(_Inout_ PGENERIC_LIST List, _In_ PPARTLIST PartList, _In_ PVOLENTRY Volume)
Definition: osdetect.c:683
base of all file and directory entries
Definition: entries.h:83
Definition: typedefs.h:120
UCHAR PartitionType
Definition: partlist.h:73
PVOLENTRY Volume
Definition: partlist.h:95
struct _DISKENTRY * DiskEntry
Definition: partlist.h:66
BOOLEAN LogicalPartition
Definition: partlist.h:79
ULONG PartitionNumber
Definition: partlist.h:75
ULONG PartitionIndex
Definition: partlist.h:76
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
char CHAR
Definition: xmlstorage.h:175

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 68 of file osdetect.c.

72{
74 PNTOS_OPTIONS Options = (PNTOS_OPTIONS)&BootEntry->OsOptions;
75 PNTOS_INSTALLATION NtOsInstall;
76
77 ULONG DiskNumber = 0, PartitionNumber = 0;
79
80 UNICODE_STRING SystemRootPath;
82
83 USHORT Machine;
85 WCHAR VendorNameBuffer[MAX_PATH];
86
87
88 /* We have a boot entry */
89
90 /* Check for supported boot type "Windows2003" */
91 if (BootEntry->OsOptionsLength < sizeof(NTOS_OPTIONS) ||
92 RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
96 {
97 /* This is not a ReactOS entry */
98 // DPRINT(" An installation '%S' of unsupported type '%S'\n",
99 // BootEntry->FriendlyName, BootEntry->Version ? BootEntry->Version : L"n/a");
100 DPRINT(" An installation '%S' of unsupported type %lu\n",
101 BootEntry->FriendlyName, BootEntry->OsOptionsLength);
102 /* Continue the enumeration */
103 return STATUS_SUCCESS;
104 }
105
106 /* BootType is Windows2003, now check OsLoadPath */
107 if (!Options->OsLoadPath || !*Options->OsLoadPath)
108 {
109 /* Certainly not a ReactOS installation */
110 DPRINT1(" A Win2k3 install '%S' without an ARC path?!\n", BootEntry->FriendlyName);
111 /* Continue the enumeration */
112 return STATUS_SUCCESS;
113 }
114
115 DPRINT(" Found a candidate Win2k3 install '%S' with ARC path '%S'\n",
116 BootEntry->FriendlyName, Options->OsLoadPath);
117 // DPRINT(" Found a Win2k3 install '%S' with ARC path '%S'\n",
118 // BootEntry->FriendlyName, Options->OsLoadPath);
119
120 // TODO: Normalize the ARC path.
121
122 /*
123 * Check whether we already have an installation with this ARC path.
124 * If this is the case, stop there.
125 */
126 NtOsInstall = FindExistingNTOSInstall(Data->List, Options->OsLoadPath, NULL);
127 if (NtOsInstall)
128 {
129 DPRINT(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
130 NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemArcPath);
131 /* Continue the enumeration */
132 return STATUS_SUCCESS;
133 }
134
135 /*
136 * Convert the ARC path into an NT path, from which we will deduce the
137 * real disk & partition on which the candidate installation resides,
138 * as well as verifying whether it is indeed an NTOS installation.
139 */
140 RtlInitEmptyUnicodeString(&SystemRootPath, SystemRoot, sizeof(SystemRoot));
141 if (!ArcPathToNtPath(&SystemRootPath, Options->OsLoadPath, Data->PartList))
142 {
143 DPRINT1("ArcPathToNtPath(%S) failed, skip the installation.\n", Options->OsLoadPath);
144 /* Continue the enumeration */
145 return STATUS_SUCCESS;
146 }
147
148 DPRINT("ArcPathToNtPath() succeeded: '%S' --> '%wZ'\n",
149 Options->OsLoadPath, &SystemRootPath);
150
151 /*
152 * Check whether we already have an installation with this NT path.
153 * If this is the case, stop there.
154 */
155 NtOsInstall = FindExistingNTOSInstall(Data->List, NULL /*Options->OsLoadPath*/, &SystemRootPath);
156 if (NtOsInstall)
157 {
158 DPRINT1(" An NTOS installation with name \"%S\" from vendor \"%S\" already exists in SystemRoot '%wZ'\n",
159 NtOsInstall->InstallationName, NtOsInstall->VendorName, &NtOsInstall->SystemNtPath);
160 /* Continue the enumeration */
161 return STATUS_SUCCESS;
162 }
163
164 DPRINT("EnumerateInstallations: SystemRootPath: '%wZ'\n", &SystemRootPath);
165
166 /* Check if this is a valid NTOS installation; stop there if it isn't one */
167 RtlInitEmptyUnicodeString(&VendorName, VendorNameBuffer, sizeof(VendorNameBuffer));
168 if (!IsValidNTOSInstallation(&SystemRootPath, &Machine, &VendorName))
169 {
170 /* Continue the enumeration */
171 return STATUS_SUCCESS;
172 }
173
174 DPRINT("Found a valid NTOS installation in SystemRoot ARC path '%S', NT path '%wZ'\n",
175 Options->OsLoadPath, &SystemRootPath);
176
177 /* From the NT path, compute the disk, partition and path components */
178 if (NtPathToDiskPartComponents(SystemRootPath.Buffer, &DiskNumber, &PartitionNumber, &PathComponent))
179 {
180 DPRINT("SystemRootPath = '%wZ' points to disk #%d, partition #%d, path '%S'\n",
181 &SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
182 }
183 else
184 {
185 DPRINT1("NtPathToDiskPartComponents(%wZ) failed\n", &SystemRootPath);
186 }
187
188 /* Add the discovered NTOS installation into the list */
189 NtOsInstall = AddNTOSInstallation(Data->List,
190 BootEntry->FriendlyName,
191 Machine,
192 VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
193 Options->OsLoadPath,
194 &SystemRootPath, PathComponent,
195 DiskNumber, PartitionNumber);
196 if (NtOsInstall)
197 {
198 /* Retrieve the volume corresponding to the disk and partition numbers */
199 PPARTENTRY PartEntry = SelectPartition(Data->PartList, DiskNumber, PartitionNumber);
200 if (!PartEntry)
201 {
202 DPRINT1("SelectPartition(disk #%d, partition #%d) failed\n",
203 DiskNumber, PartitionNumber);
204 }
205 NtOsInstall->Volume = (PartEntry ? PartEntry->Volume : NULL);
206 }
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:102
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:763
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:86
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)
Definition: osdetect.c:613
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:504
PPARTENTRY SelectPartition(_In_ PPARTLIST List, _In_ ULONG DiskNumber, _In_ ULONG PartitionNumber)
Definition: partlist.c:2268
#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
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336

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 569 of file osdetect.c.

574{
576 PNTOS_INSTALLATION NtOsInstall;
577 UNICODE_STRING SystemArcPath;
578
579 /*
580 * We search either via ARC path or NT path.
581 * If both pointers are NULL then we fail straight away.
582 */
583 if (!SystemRootArcPath && !SystemRootNtPath)
584 return NULL;
585
586 RtlInitUnicodeString(&SystemArcPath, SystemRootArcPath);
587
589 {
591
592 /*
593 * Note that if both ARC paths are equal, then the corresponding
594 * NT paths must be the same. However, two ARC paths may be different
595 * but resolve into the same NT path.
596 */
597 if ( (SystemRootArcPath &&
599 &SystemArcPath, TRUE)) ||
600 (SystemRootNtPath &&
602 SystemRootNtPath, TRUE)) )
603 {
604 /* Found it! */
605 return NtOsInstall;
606 }
607 }
608
609 return NULL;
610}
PGENERIC_LIST_ENTRY NTAPI GetFirstListEntry(IN PGENERIC_LIST List)
Definition: genlist.c:110
PGENERIC_LIST_ENTRY NTAPI GetNextListEntry(IN PGENERIC_LIST_ENTRY Entry)
Definition: genlist.c:121
PVOID NTAPI GetListEntryData(IN PGENERIC_LIST_ENTRY Entry)
Definition: genlist.c:134
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 ( _Inout_ PGENERIC_LIST  List,
_In_ PPARTLIST  PartList,
_In_ PVOLENTRY  Volume 
)
static

Definition at line 683 of file osdetect.c.

687{
689 HANDLE VolumeRootDirHandle;
692 UNICODE_STRING VolumeRootPath;
694 PVOID BootStoreHandle;
698
699 /* Set VolumeRootPath */
700 RtlStringCchPrintfW(PathBuffer, _countof(PathBuffer),
701 L"%s\\", Volume->Info.DeviceName);
702 RtlInitUnicodeString(&VolumeRootPath, PathBuffer);
703 DPRINT("FindNTOSInstallations(%wZ)\n", &VolumeRootPath);
704
705 /* Open the volume */
707 &VolumeRootPath,
709 NULL,
710 NULL);
711 Status = NtOpenFile(&VolumeRootDirHandle,
717 if (!NT_SUCCESS(Status))
718 {
719 DPRINT1("Failed to open volume '%wZ', Status 0x%08lx\n", &VolumeRootPath, Status);
720 return;
721 }
722
723 Data.List = List;
724 Data.PartList = PartList;
725
726 /* Try to see whether we recognize some NT boot loaders */
727 for (Type = FreeLdr; Type < BldrTypeMax; ++Type)
728 {
729 Status = FindBootStore(VolumeRootDirHandle, Type, &Version);
730 if (!NT_SUCCESS(Status))
731 {
732 /* The loader does not exist, continue with another one */
733 DPRINT("Loader type '%d' does not exist, or an error happened (Status 0x%08lx), continue with another one...\n",
734 Type, Status);
735 continue;
736 }
737
738 /* The loader exists, try to enumerate its boot entries */
739 DPRINT("Analyze the OS installations for loader type '%d' in Volume %wZ (Disk #%d, Partition #%d)\n",
740 Type, &VolumeRootPath,
741 Volume->PartEntry->DiskEntry->DiskNumber,
742 Volume->PartEntry->PartitionNumber);
743
744 Status = OpenBootStoreByHandle(&BootStoreHandle, VolumeRootDirHandle, Type,
746 if (!NT_SUCCESS(Status))
747 {
748 DPRINT1("Could not open the NTOS boot store of type '%d' (Status 0x%08lx), continue with another one...\n",
749 Type, Status);
750 continue;
751 }
753 CloseBootStore(BootStoreHandle);
754 }
755
756 /* Close the volume */
757 NtClose(VolumeRootDirHandle);
758}
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_ BOOT_STORE_OPENMODE OpenMode, _In_ BOOT_STORE_ACCESS Access)
Definition: bldrsup.c:897
NTSTATUS CloseBootStore(_In_ PVOID Handle)
Definition: bldrsup.c:1014
NTSTATUS EnumerateBootStoreEntries(IN PVOID Handle, IN PENUM_BOOT_ENTRIES_ROUTINE EnumBootEntriesRoutine, IN PVOID Parameter OPTIONAL)
Definition: bldrsup.c:1703
NTSTATUS FindBootStore(IN HANDLE PartitionDirectoryHandle, IN BOOT_STORE_TYPE Type, OUT PULONG VersionNumber OPTIONAL)
Definition: bldrsup.c:151
@ BS_ReadAccess
Definition: bldrsup.h:144
@ BldrTypeMax
Definition: bldrsup.h:18
@ FreeLdr
Definition: bldrsup.h:15
@ BS_OpenExisting
Definition: bldrsup.h:135
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:3953
#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
#define RTL_NUMBER_OF_FIELD(type, field)
Definition: ntbasedef.h:711
static NTSTATUS NTAPI EnumerateInstallations(IN BOOT_STORE_TYPE Type, IN PBOOT_STORE_ENTRY BootEntry, IN PVOID Parameter OPTIONAL)
Definition: osdetect.c:68
#define _countof(array)
Definition: sndvol32.h:70
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE _In_ USHORT _In_ USHORT Version
Definition: wdffdo.h:469

Referenced by CreateNTOSInstallationsList().

◆ FindSubStrI()

PCWSTR NTAPI FindSubStrI ( _In_ PCWSTR  str,
_In_ PCWSTR  strSearch 
)

Finds the first occurrence of a sub-string 'strSearch' inside 'str', using case-insensitive comparisons.

Definition at line 219 of file osdetect.c.

222{
223 PCWSTR cp = str;
224 PCWSTR s1, s2;
225
226 if (!*strSearch)
227 return str;
228
229 while (*cp)
230 {
231 s1 = cp;
232 s2 = strSearch;
233
234 while (*s1 && *s2 && (towupper(*s1) == towupper(*s2)))
235 ++s1, ++s2;
236
237 if (!*s2)
238 return cp;
239
240 ++cp;
241 }
242
243 return NULL;
244}
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 504 of file osdetect.c.

508{
512 HANDLE SystemRootDirectory;
514
515 /* Open SystemRootPath */
517 SystemRootPath,
519 NULL,
520 NULL);
521 Status = NtOpenFile(&SystemRootDirectory,
527 if (!NT_SUCCESS(Status))
528 {
529 DPRINT1("Failed to open SystemRoot '%wZ', Status 0x%08lx\n", SystemRootPath, Status);
530 return FALSE;
531 }
532
533 Success = IsValidNTOSInstallationByHandle(SystemRootDirectory,
534 Machine, VendorName);
535
536 /* Done! */
537 NtClose(SystemRootDirectory);
538 return Success;
539}
static BOOLEAN IsValidNTOSInstallationByHandle(IN HANDLE SystemRootDirectory, OUT PUSHORT Machine OPTIONAL, OUT PUNICODE_STRING VendorName OPTIONAL)
Definition: osdetect.c:350

Referenced by EnumerateInstallations().

◆ IsValidNTOSInstallationByHandle()

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

Definition at line 350 of file osdetect.c.

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

Referenced by IsValidNTOSInstallation().

Variable Documentation

◆ KnownVendors

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

Definition at line 29 of file osdetect.c.

Referenced by IsValidNTOSInstallationByHandle().