1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/rtl/misc.c 5 * PURPOSE: Various functions 6 * 7 * PROGRAMMERS: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 extern ULONG NtGlobalFlag; 19 extern ULONG NtMajorVersion; 20 extern ULONG NtMinorVersion; 21 extern ULONG NtOSCSDVersion; 22 #define PRODUCT_TAG 'iPtR' 23 24 /* FUNCTIONS *****************************************************************/ 25 26 /* 27 * @implemented 28 */ 29 ULONG 30 NTAPI 31 RtlGetNtGlobalFlags(VOID) 32 { 33 return NtGlobalFlag; 34 } 35 36 /* 37 * @implemented 38 */ 39 NTSTATUS 40 NTAPI 41 RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation) 42 { 43 PAGED_CODE(); 44 45 /* Return the basics */ 46 lpVersionInformation->dwMajorVersion = NtMajorVersion; 47 lpVersionInformation->dwMinorVersion = NtMinorVersion; 48 lpVersionInformation->dwBuildNumber = NtBuildNumber & 0x3FFF; 49 lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT; 50 51 /* Check if this is the extended version */ 52 if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW)) 53 { 54 PRTL_OSVERSIONINFOEXW InfoEx = (PRTL_OSVERSIONINFOEXW)lpVersionInformation; 55 InfoEx->wServicePackMajor = (USHORT)(CmNtCSDVersion >> 8) & 0xFF; 56 InfoEx->wServicePackMinor = (USHORT)(CmNtCSDVersion & 0xFF); 57 InfoEx->wSuiteMask = (USHORT)(SharedUserData->SuiteMask & 0xFFFF); 58 InfoEx->wProductType = SharedUserData->NtProductType; 59 InfoEx->wReserved = 0; 60 } 61 62 /* Always succeed */ 63 return STATUS_SUCCESS; 64 } 65 66 /** 67 * @brief 68 * Retrieves the NT type product of the operating system. This is the kernel-mode variant 69 * of this function. 70 * 71 * @param[out] ProductType 72 * The NT type product enumeration value returned by the call. 73 * 74 * @return 75 * The function returns TRUE when the call successfully returned the type product of the system. 76 * It'll return FALSE on failure otherwise. In the latter case the function will return WinNT 77 * as the default product type. 78 * 79 * @remarks 80 * The call expects to be called at PASSIVE_LEVEL. The function firstly checks if the product type is 81 * actually valid by checking the "ProductTypeIsValid" member of _KUSER_SHARED_DATA structure. 82 * Currently we do not implement code that is responsible for the management of this member, yet. 83 * 84 */ 85 BOOLEAN 86 NTAPI 87 RtlGetNtProductType(OUT PNT_PRODUCT_TYPE ProductType) 88 { 89 HANDLE Key; 90 BOOLEAN Success; 91 ULONG ReturnedLength; 92 OBJECT_ATTRIBUTES ObjectAttributes; 93 NTSTATUS Status; 94 PKEY_VALUE_PARTIAL_INFORMATION BufferKey; 95 ULONG BufferKeyLength = sizeof(PKEY_VALUE_PARTIAL_INFORMATION) + (256 * sizeof(WCHAR)); 96 UNICODE_STRING NtProductType; 97 static UNICODE_STRING WorkstationProduct = RTL_CONSTANT_STRING(L"WinNT"); 98 static UNICODE_STRING LanManProduct = RTL_CONSTANT_STRING(L"LanmanNT"); 99 static UNICODE_STRING ServerProduct = RTL_CONSTANT_STRING(L"ServerNT"); 100 static UNICODE_STRING KeyProduct = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions"); 101 static UNICODE_STRING ValueNtProduct = RTL_CONSTANT_STRING(L"ProductType"); 102 103 PAGED_CODE(); 104 105 /* Before doing anything else we must allocate some buffer space in the pool */ 106 BufferKey = ExAllocatePoolWithTag(PagedPool, BufferKeyLength, PRODUCT_TAG); 107 if (!BufferKey) 108 { 109 /* We failed to allocate pool memory, bail out */ 110 DPRINT1("RtlGetNtProductType(): Memory pool allocation has failed!\n"); 111 Success = FALSE; 112 goto Exit; 113 } 114 115 /* Initialize the object attributes to open our key */ 116 InitializeObjectAttributes(&ObjectAttributes, 117 &KeyProduct, 118 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 119 NULL, 120 NULL); 121 122 /* Open the key */ 123 Status = ZwOpenKey(&Key, KEY_QUERY_VALUE, &ObjectAttributes); 124 if (!NT_SUCCESS(Status)) 125 { 126 DPRINT1("RtlGetNtProductType(): The ZwOpenKey() function has failed! (Status: 0x%lx)\n", Status); 127 Success = FALSE; 128 goto Exit; 129 } 130 131 /* Now it's time to query the value from the key to check what kind of product the OS is */ 132 Status = ZwQueryValueKey(Key, 133 &ValueNtProduct, 134 KeyValuePartialInformation, 135 BufferKey, 136 BufferKeyLength, 137 &ReturnedLength); 138 139 /* Free the key from the memory */ 140 ZwClose(Key); 141 142 if (!NT_SUCCESS(Status)) 143 { 144 DPRINT1("RtlGetNtProductType(): The ZwQueryValueKey() function has failed! (Status: 0x%lx)\n", Status); 145 Success = FALSE; 146 goto Exit; 147 } 148 149 /* 150 * Do a sanity check before we get the product type of the operating system 151 * so that we're sure the type of the value we've got is actually correct. 152 */ 153 if (BufferKey->Type != REG_SZ) 154 { 155 /* We've got something else, so bail out */ 156 DPRINT1("RtlGetNtProductType(): An invalid value type has been found!\n"); 157 Success = FALSE; 158 goto Exit; 159 } 160 161 /* Initialise the Unicode string with the data from the registry value */ 162 NtProductType.Length = NtProductType.MaximumLength = BufferKey->DataLength; 163 NtProductType.Buffer = (PWCHAR)BufferKey->Data; 164 165 if (NtProductType.Length > sizeof(WCHAR) && NtProductType.Buffer[NtProductType.Length / 166 sizeof(WCHAR) - 1] == UNICODE_NULL) 167 { 168 NtProductType.Length -= sizeof(WCHAR); 169 } 170 171 /* Now it's time to get the product based on the value data */ 172 if (RtlCompareUnicodeString(&NtProductType, &WorkstationProduct, TRUE) == 0) 173 { 174 /* The following product is an OS Workstation */ 175 *ProductType = NtProductWinNt; 176 Success = TRUE; 177 } 178 else if (RtlCompareUnicodeString(&NtProductType, &LanManProduct, TRUE) == 0) 179 { 180 /* The following product is an OS Advanced Server */ 181 *ProductType = NtProductLanManNt; 182 Success = TRUE; 183 } 184 else if (RtlCompareUnicodeString(&NtProductType, &ServerProduct, TRUE) == 0) 185 { 186 /* The following product is an OS Server */ 187 *ProductType = NtProductServer; 188 Success = TRUE; 189 } 190 else 191 { 192 /* None of the product types match so bail out */ 193 DPRINT1("RtlGetNtProductType(): Couldn't find a valid product type! Defaulting to WinNT...\n"); 194 Success = FALSE; 195 goto Exit; 196 } 197 198 Exit: 199 if (!Success) 200 { 201 *ProductType = NtProductWinNt; 202 } 203 204 ExFreePoolWithTag(BufferKey, PRODUCT_TAG); 205 return Success; 206 } 207 208 #if !defined(_M_IX86) 209 // 210 // Stub for architectures which don't have this implemented 211 // 212 VOID 213 FASTCALL 214 RtlPrefetchMemoryNonTemporal(IN PVOID Source, 215 IN SIZE_T Length) 216 { 217 // 218 // Do nothing 219 // 220 UNREFERENCED_PARAMETER(Source); 221 UNREFERENCED_PARAMETER(Length); 222 } 223 #endif 224 225 /* EOF */ 226