xref: /reactos/ntoskrnl/rtl/misc.c (revision 1734f297)
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