xref: /reactos/dll/ntdll/rtl/version.c (revision 4561998a)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            lib/ntdll/rtl/process.c
5  * PURPOSE:         Process functions
6  * PROGRAMMER:      Ariadne (ariadne@xs4all.nl)
7  * UPDATE HISTORY:
8  *                  Created 01/11/98
9  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include <ntdll.h>
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 /* FUNCTIONS ******************************************************************/
19 
20 /* HACK: ReactOS specific changes, see bug-reports CORE-6611 and CORE-4620 (aka. #5003) */
21 static VOID NTAPI
22 SetRosSpecificInfo(IN OUT PRTL_OSVERSIONINFOEXW VersionInformation)
23 {
24     CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
25     PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer;
26     OBJECT_ATTRIBUTES ObjectAttributes;
27     ULONG ReportAsWorkstation = 0;
28     HANDLE hKey;
29     ULONG Length;
30     NTSTATUS Status;
31     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
32     UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation");
33 
34     InitializeObjectAttributes(&ObjectAttributes,
35                                &KeyName,
36                                OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
37                                NULL,
38                                NULL);
39 
40     /* Don't change anything if the key doesn't exist */
41     Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
42     if (NT_SUCCESS(Status))
43     {
44         /* Get the value from the registry and make sure it's a 32-bit value */
45         Status = NtQueryValueKey(hKey,
46                                  &ValName,
47                                  KeyValuePartialInformation,
48                                  kvpInfo,
49                                  sizeof(Buffer),
50                                  &Length);
51         if (NT_SUCCESS(Status) &&
52             (kvpInfo->Type == REG_DWORD) &&
53             (kvpInfo->DataLength == sizeof(ULONG)))
54         {
55             /* Is the value set? */
56             ReportAsWorkstation = *(PULONG)kvpInfo->Data;
57             if ((VersionInformation->wProductType == VER_NT_SERVER) &&
58                 (ReportAsWorkstation != 0))
59             {
60                 /* It is, modify the product type to report a workstation */
61                 VersionInformation->wProductType = VER_NT_WORKSTATION;
62                 DPRINT1("We modified the reported OS from NtProductServer to NtProductWinNt\n");
63             }
64         }
65 
66         /* Close the handle */
67         NtClose(hKey);
68     }
69 }
70 
71 /**********************************************************************
72  * NAME                         EXPORTED
73  *  RtlGetNtProductType
74  *
75  * DESCRIPTION
76  *  Retrieves the OS product type.
77  *
78  * ARGUMENTS
79  *  ProductType Pointer to the product type variable.
80  *
81  * RETURN VALUE
82  *  TRUE if successful, otherwise FALSE
83  *
84  * NOTE
85  *  ProductType can be one of the following values:
86  *    1 Workstation (WinNT)
87  *    2 Server (LanmanNT)
88  *    3 Advanced Server (ServerNT)
89  *
90  * REVISIONS
91  *  2000-08-10 ekohl
92  *
93  * @implemented
94  */
95 BOOLEAN NTAPI
96 RtlGetNtProductType(PNT_PRODUCT_TYPE ProductType)
97 {
98     *ProductType = SharedUserData->NtProductType;
99     return TRUE;
100 }
101 
102 /**********************************************************************
103  * NAME                         EXPORTED
104  *  RtlGetNtVersionNumbers
105  *
106  * DESCRIPTION
107  *  Get the version numbers of the run time library.
108  *
109  * ARGUMENTS
110  *  pMajorVersion [OUT] Destination for the Major version
111  *  pMinorVersion [OUT] Destination for the Minor version
112  *  pBuildNumber  [OUT] Destination for the Build version
113  *
114  * RETURN VALUE
115  *  Nothing.
116  *
117  * NOTES
118  *  - Introduced in Windows XP (NT 5.1)
119  *  - Since this call didn't exist before XP, we report at least the version
120  *    5.1. This fixes the loading of msvcrt.dll as released with XP Home,
121  *    which fails in DLLMain() if the major version isn't 5.
122  *
123  * @implemented
124  */
125 VOID NTAPI
126 RtlGetNtVersionNumbers(OUT PULONG pMajorVersion,
127                        OUT PULONG pMinorVersion,
128                        OUT PULONG pBuildNumber)
129 {
130     PPEB pPeb = NtCurrentPeb();
131 
132     if (pMajorVersion)
133     {
134         *pMajorVersion = pPeb->OSMajorVersion < 5 ? 5 : pPeb->OSMajorVersion;
135     }
136 
137     if (pMinorVersion)
138     {
139         if ( (pPeb->OSMajorVersion  < 5) ||
140             ((pPeb->OSMajorVersion == 5) && (pPeb->OSMinorVersion < 1)) )
141             *pMinorVersion = 1;
142         else
143             *pMinorVersion = pPeb->OSMinorVersion;
144     }
145 
146     if (pBuildNumber)
147     {
148         /* Windows really does this! */
149         *pBuildNumber = (0xF0000000 | pPeb->OSBuildNumber);
150     }
151 }
152 
153 /*
154  * @implemented
155  * @note User-mode version of RtlGetVersion in ntoskrnl/rtl/misc.c
156  */
157 NTSTATUS NTAPI
158 RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
159 {
160     ULONG Length;
161     PPEB Peb = NtCurrentPeb();
162 
163     if (lpVersionInformation->dwOSVersionInfoSize != sizeof(RTL_OSVERSIONINFOW) &&
164         lpVersionInformation->dwOSVersionInfoSize != sizeof(RTL_OSVERSIONINFOEXW))
165     {
166         return STATUS_INVALID_PARAMETER;
167     }
168 
169     lpVersionInformation->dwMajorVersion = Peb->OSMajorVersion;
170     lpVersionInformation->dwMinorVersion = Peb->OSMinorVersion;
171     lpVersionInformation->dwBuildNumber = Peb->OSBuildNumber;
172     lpVersionInformation->dwPlatformId = Peb->OSPlatformId;
173     RtlZeroMemory(lpVersionInformation->szCSDVersion, sizeof(lpVersionInformation->szCSDVersion));
174 
175     /* If we have a CSD version string, initialized by Application Compatibility... */
176     if (Peb->CSDVersion.Length && Peb->CSDVersion.Buffer && Peb->CSDVersion.Buffer[0] != UNICODE_NULL)
177     {
178         /* ... copy it... */
179         Length = min(wcslen(Peb->CSDVersion.Buffer), ARRAYSIZE(lpVersionInformation->szCSDVersion) - 1);
180         wcsncpy(lpVersionInformation->szCSDVersion, Peb->CSDVersion.Buffer, Length);
181     }
182     else
183     {
184         /* ... otherwise we just null-terminate it */
185         Length = 0;
186     }
187 
188     /* Always null-terminate the user CSD version string */
189     lpVersionInformation->szCSDVersion[Length] = UNICODE_NULL;
190 
191     if (lpVersionInformation->dwOSVersionInfoSize == sizeof(RTL_OSVERSIONINFOEXW))
192     {
193         PRTL_OSVERSIONINFOEXW InfoEx = (PRTL_OSVERSIONINFOEXW)lpVersionInformation;
194         InfoEx->wServicePackMajor = (Peb->OSCSDVersion >> 8) & 0xFF;
195         InfoEx->wServicePackMinor = Peb->OSCSDVersion & 0xFF;
196         InfoEx->wSuiteMask = SharedUserData->SuiteMask & 0xFFFF;
197         InfoEx->wProductType = SharedUserData->NtProductType;
198         InfoEx->wReserved = 0;
199 
200         /* HACK: ReactOS specific changes, see bug-reports CORE-6611 and CORE-4620 (aka. #5003) */
201         SetRosSpecificInfo(InfoEx);
202     }
203 
204     return STATUS_SUCCESS;
205 }
206 
207 /* EOF */
208