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
RtlGetNtGlobalFlags(VOID)31 RtlGetNtGlobalFlags(VOID)
32 {
33 return NtGlobalFlag;
34 }
35
36 /*
37 * @implemented
38 */
39 NTSTATUS
40 NTAPI
RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)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
RtlGetNtProductType(OUT PNT_PRODUCT_TYPE ProductType)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
RtlPrefetchMemoryNonTemporal(IN PVOID Source,IN SIZE_T Length)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