ReactOS  0.4.14-dev-297-g23e575c
registry.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPL, see COPYING in the top level directory
3  * PROJECT: ReactOS win32 kernel mode subsystem server
4  * PURPOSE: Registry loading and storing
5  * FILE: win32ss/user/ntuser/misc/registry.c
6  * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
15 NTAPI
17  LPCWSTR pwszKeyName,
18  PHKEY phkey)
19 {
22  UNICODE_STRING ustrKeyName;
23  HKEY hkey;
24 
25  /* Initialize the key name */
26  RtlInitUnicodeString(&ustrKeyName, pwszKeyName);
27 
28  /* Initialize object attributes */
30  &ustrKeyName,
32  NULL,
33  NULL);
34 
35  /* Open the key */
36  Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes);
37  if (NT_SUCCESS(Status))
38  {
39  *phkey = hkey;
40  }
41 
42  return Status;
43 }
44 
46 NTAPI
48  IN HKEY hkey,
50  IN ULONG ulType,
52  IN OUT PULONG pcbValue)
53 {
55  UNICODE_STRING ustrValueName;
56  BYTE ajBuffer[100];
58  ULONG cbInfoSize, cbDataSize;
59 
60  /* Check if the local buffer is sufficient */
61  cbInfoSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[*pcbValue]);
62  if (cbInfoSize <= sizeof(ajBuffer))
63  {
64  pInfo = (PVOID)ajBuffer;
65  }
66  else
67  {
68  /* It's not, allocate a sufficient buffer */
69  pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
70  if (!pInfo)
71  {
73  }
74  }
75 
76  /* Query the value */
77  RtlInitUnicodeString(&ustrValueName, pwszValueName);
78  Status = ZwQueryValueKey(hkey,
79  &ustrValueName,
81  (PVOID)pInfo,
82  cbInfoSize,
83  &cbInfoSize);
84 
85  /* Note: STATUS_BUFFER_OVERFLOW is not a success */
86  if (NT_SUCCESS(Status))
87  {
88  cbDataSize = pInfo->DataLength;
89 
90  /* Did we get the right type */
91  if (pInfo->Type != ulType)
92  {
94  }
95  else if (cbDataSize > *pcbValue)
96  {
98  }
99  else
100  {
101  /* Copy the contents to the caller */
102  RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
103  }
104  }
106  {
107  _PRAGMA_WARNING_SUPPRESS(6102); /* cbInfoSize is initialized here! */
108  cbDataSize = cbInfoSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
109  }
110  else
111  {
112  cbDataSize = 0;
113  }
114 
115  /* Return the data size to the caller */
116  *pcbValue = cbDataSize;
117 
118  /* Cleanup */
119  if (pInfo != (PVOID)ajBuffer)
120  ExFreePoolWithTag(pInfo, TAG_TEMP);
121 
122  return Status;
123 
124 }
125 
126 VOID
127 NTAPI
128 RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
129 {
130  UNICODE_STRING ustrValue;
131  UNICODE_STRING ustrData;
132 
133  RtlInitUnicodeString(&ustrValue, pwszValue);
134  RtlInitUnicodeString(&ustrData, pwszData);
135  ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
136 }
137 
138 VOID
139 NTAPI
141 {
142  UNICODE_STRING ustrValue;
143 
144  RtlInitUnicodeString(&ustrValue, pwszValue);
145  ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
146 }
147 
148 BOOL
149 NTAPI
150 RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
151 {
153  ULONG cbSize = sizeof(DWORD);
154  Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
155  return NT_SUCCESS(Status);
156 }
157 
158 _Success_(return!=FALSE)
159 BOOL
160 NTAPI
161 RegReadUserSetting(
162  _In_z_ PCWSTR pwszKeyName,
164  _In_ ULONG ulType,
166  _In_ ULONG cbDataSize)
167 {
170  UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
171  WCHAR awcBuffer[MAX_PATH];
172  HKEY hkey;
174  ULONG cbInfoSize, cbReqSize;
175 
176  /* Get the path of the current user's profile */
177  Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
178  if (!NT_SUCCESS(Status))
179  {
180  return FALSE;
181  }
182 
183  /* Initialize empty key name */
184  RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
185 
186  /* Append the current user key name */
187  Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
188 
189  /* Free the current user key name */
190  RtlFreeUnicodeString(&usCurrentUserKey);
191 
192  /* Check for success */
193  if (!NT_SUCCESS(Status))
194  {
195  return FALSE;
196  }
197 
198  /* Append a '\', we can trust in enough space left. */
199  usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
200  usKeyName.Length += sizeof(WCHAR);
201 
202  /* Append the subkey name */
203  Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
204  if (!NT_SUCCESS(Status))
205  {
206  return FALSE;
207  }
208 
209  /* Initialize object attributes */
211  &usKeyName,
213  NULL,
214  NULL);
215 
216  /* Open the key */
217  Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes);
218  if (!NT_SUCCESS(Status))
219  {
220  return FALSE;
221  }
222 
223  /* Check if the local buffer is sufficient */
224  cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize;
225  if (cbInfoSize <= sizeof(awcBuffer))
226  {
227  pInfo = (PVOID)awcBuffer;
228  }
229  else
230  {
231  /* It's not, allocate a sufficient buffer */
232  pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
233  if (!pInfo)
234  {
235  ZwClose(hkey);
236  return FALSE;
237  }
238  }
239 
240  /* Query the value */
241  RtlInitUnicodeString(&usValueName, pwszValueName);
242  Status = ZwQueryValueKey(hkey,
243  &usValueName,
245  (PVOID)pInfo,
246  cbInfoSize,
247  &cbReqSize);
248  if (NT_SUCCESS(Status))
249  {
250  /* Did we get the right type */
251  if (pInfo->Type == ulType)
252  {
253  /* Copy the contents to the caller */
254  RtlCopyMemory(pvData, pInfo->Data, cbDataSize);
255  }
256  }
257 
258  /* Cleanup */
259  ZwClose(hkey);
260  if (pInfo != (PVOID)awcBuffer)
261  ExFreePoolWithTag(pInfo, TAG_TEMP);
262 
263  return NT_SUCCESS(Status);
264 }
265 
266 _Success_(return != FALSE)
267 BOOL
268 NTAPI
269 RegWriteUserSetting(
270  _In_z_ PCWSTR pwszKeyName,
272  _In_ ULONG ulType,
274  _In_ ULONG cbDataSize)
275 {
278  UNICODE_STRING usCurrentUserKey, usKeyName, usValueName;
279  WCHAR awcBuffer[MAX_PATH];
280  HKEY hkey;
281 
282  // FIXME: Logged in user versus current process user?
283  /* Get the path of the current user's profile */
284  Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey);
285  if (!NT_SUCCESS(Status))
286  {
287  DPRINT1("RtlFormatCurrentUserKeyPath failed\n");
288  return FALSE;
289  }
290 
291  /* Initialize empty key name */
292  RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer));
293 
294  /* Append the current user key name */
295  Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey);
296  if (!NT_SUCCESS(Status))
297  {
298  return FALSE;
299  }
300 
301  /* Free the current user key name */
302  RtlFreeUnicodeString(&usCurrentUserKey);
303 
304  /* Append a '\', we can trust in enough space left. */
305  usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\';
306  usKeyName.Length += sizeof(WCHAR);
307 
308  /* Append the subkey name */
309  Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
310  if (!NT_SUCCESS(Status))
311  {
312  DPRINT1("RtlAppendUnicodeToString failed with Status=0x%lx, buf:%u,%u\n",
313  Status, usKeyName.Length, usKeyName.MaximumLength);
314  return FALSE;
315  }
316 
317  /* Initialize object attributes */
319  &usKeyName,
321  NULL,
322  NULL);
323 
324  /* Open or create the key */
325  Status = ZwCreateKey((PHANDLE)&hkey,
328  0,
329  NULL,
330  0,
331  NULL);
332  if(!NT_SUCCESS(Status))
333  {
334  DPRINT1("Failed to create key: 0x%x\n", Status);
335  return FALSE;
336  }
337 
338  /* Initialize the value name string */
339  RtlInitUnicodeString(&usValueName, pwszValueName);
340 
341  Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, (PVOID)pvData, cbDataSize);
342  if(!NT_SUCCESS(Status))
343  {
344  DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n",
345  pwszKeyName, pwszValueName, Status);
346  }
347 
348  /* Cleanup */
349  ZwClose(hkey);
350 
351  return NT_SUCCESS(Status);
352 }
353 
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static DWORD
Definition: registry.c:44
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID NTAPI RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
Definition: registry.c:128
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
LONG NTSTATUS
Definition: precomp.h:26
LONG RegQueryValue(_In_ HKEY Key, _In_z_ PCWSTR ValueName, _Out_opt_ PULONG Type, _Out_opt_ PUCHAR Data, _Inout_opt_ PULONG DataSize)
Definition: registry.c:435
static HANDLE ULONG_PTR dwData
Definition: file.c:35
static PVOID
Definition: registry.c:44
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define _Out_writes_(size)
Definition: no_sal2.h:367
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned int BOOL
Definition: ntddk_ex.h:94
_In_z_ PCWSTR _In_ ULONG _Post_z_ PVOID _In_ ULONG cjDataSize
Definition: ntuser.h:38
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3748
smooth NULL
Definition: ftsmooth.c:416
_Success_(return!=NULL||BufferSize==0)
Definition: registry.c:427
NTSTATUS NTAPI RtlFormatCurrentUserKeyPath(OUT PUNICODE_STRING KeyPath)
Definition: registry.c:742
#define KEY_WRITE
Definition: nt_native.h:1031
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:259
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_z_ PCWSTR pwszValueName
Definition: ntuser.h:36
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
unsigned char BYTE
Definition: mem.h:68
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
Status
Definition: gdiplustypes.h:24
#define _Post_z_
Definition: no_sal2.h:469
#define _In_
Definition: no_sal2.h:204
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define _In_z_
Definition: no_sal2.h:239
struct _KEY_VALUE_PARTIAL_INFORMATION KEY_VALUE_PARTIAL_INFORMATION
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
#define _When_(expr, annos)
Definition: no_sal2.h:639
DWORD * PDWORD
Definition: pedump.c:68
#define DPRINT1
Definition: precomp.h:8
_In_z_ PCWSTR _In_ ULONG ulType
Definition: ntuser.h:36
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
BOOL NTAPI RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
Definition: registry.c:150
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define REG_DWORD
Definition: sdbapi.c:596
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
LONG RegOpenKey(_In_ HKEY ParentKey, _In_z_ PCWSTR KeyName, _Out_ PHKEY Key)
Definition: registry.c:292
#define TAG_TEMP
Definition: tags.h:43
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
VOID NTAPI RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData)
Definition: registry.c:140
#define REG_SZ
Definition: layer.c:22