* Sync up to trunk head (r65074).
[reactos.git] / base / setup / usetup / registry.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/registry.c
23 * PURPOSE: Registry creation functions
24 * PROGRAMMER: Eric Kohl
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "usetup.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 #ifdef __REACTOS__
35 #define FLG_ADDREG_BINVALUETYPE 0x00000001
36 #define FLG_ADDREG_NOCLOBBER 0x00000002
37 #define FLG_ADDREG_DELVAL 0x00000004
38 #define FLG_ADDREG_APPEND 0x00000008
39 #define FLG_ADDREG_KEYONLY 0x00000010
40 #define FLG_ADDREG_OVERWRITEONLY 0x00000020
41 #define FLG_ADDREG_TYPE_SZ 0x00000000
42 #define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
43 #define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
44 #define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
45 #define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
46 #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
47 #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
48 #endif
49
50 #ifdef _M_IX86
51 #define Architecture L"x86"
52 #elif defined(_M_AMD64)
53 #define Architecture L"amd64"
54 #elif defined(_M_IA64)
55 #define Architecture L"ia64"
56 #elif defined(_M_ARM)
57 #define Architecture L"arm"
58 #elif defined(_M_PPC)
59 #define Architecture L"ppc"
60 #endif
61
62 #include <pshpack1.h>
63
64 typedef struct _REG_DISK_MOUNT_INFO
65 {
66 ULONG Signature;
67 LARGE_INTEGER StartingOffset;
68 } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
69
70 #include <poppack.h>
71
72 /* FUNCTIONS ****************************************************************/
73
74 static
75 BOOLEAN
76 GetRootKey(
77 PWCHAR Name)
78 {
79 if (!_wcsicmp (Name, L"HKCR"))
80 {
81 wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\");
82 return TRUE;
83 }
84
85 if (!_wcsicmp (Name, L"HKCU"))
86 {
87 wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\");
88 return TRUE;
89 }
90
91 if (!_wcsicmp (Name, L"HKLM"))
92 {
93 wcscpy (Name, L"\\Registry\\Machine\\");
94 return TRUE;
95 }
96
97 if (!_wcsicmp (Name, L"HKU"))
98 {
99 wcscpy (Name, L"\\Registry\\User\\");
100 return TRUE;
101 }
102
103 #if 0
104 if (!_wcsicmp (Name, L"HKR"))
105 return FALSE;
106 #endif
107
108 return FALSE;
109 }
110
111
112 /***********************************************************************
113 * append_multi_sz_value
114 *
115 * Append a multisz string to a multisz registry value.
116 */
117 #if 0
118 static void
119 append_multi_sz_value (HANDLE hkey,
120 const WCHAR *value,
121 const WCHAR *strings,
122 DWORD str_size )
123 {
124 DWORD size, type, total;
125 WCHAR *buffer, *p;
126
127 if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
128 if (type != REG_MULTI_SZ) return;
129
130 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return;
131 if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
132
133 /* compare each string against all the existing ones */
134 total = size;
135 while (*strings)
136 {
137 int len = strlenW(strings) + 1;
138
139 for (p = buffer; *p; p += strlenW(p) + 1)
140 if (!strcmpiW( p, strings )) break;
141
142 if (!*p) /* not found, need to append it */
143 {
144 memcpy( p, strings, len * sizeof(WCHAR) );
145 p[len] = 0;
146 total += len;
147 }
148 strings += len;
149 }
150 if (total != size)
151 {
152 TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) );
153 RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total );
154 }
155 done:
156 HeapFree( GetProcessHeap(), 0, buffer );
157 }
158 #endif
159
160 /***********************************************************************
161 * delete_multi_sz_value
162 *
163 * Remove a string from a multisz registry value.
164 */
165 #if 0
166 static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string )
167 {
168 DWORD size, type;
169 WCHAR *buffer, *src, *dst;
170
171 if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
172 if (type != REG_MULTI_SZ) return;
173 /* allocate double the size, one for value before and one for after */
174 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return;
175 if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
176 src = buffer;
177 dst = buffer + size;
178 while (*src)
179 {
180 int len = strlenW(src) + 1;
181 if (strcmpiW( src, string ))
182 {
183 memcpy( dst, src, len * sizeof(WCHAR) );
184 dst += len;
185 }
186 src += len;
187 }
188 *dst++ = 0;
189 if (dst != buffer + 2*size) /* did we remove something? */
190 {
191 TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) );
192 RegSetValueExW( hkey, value, 0, REG_MULTI_SZ,
193 (BYTE *)(buffer + size), dst - (buffer + size) );
194 }
195 done:
196 HeapFree( GetProcessHeap(), 0, buffer );
197 }
198 #endif
199
200 /***********************************************************************
201 * do_reg_operation
202 *
203 * Perform an add/delete registry operation depending on the flags.
204 */
205 static BOOLEAN
206 do_reg_operation(HANDLE KeyHandle,
207 PUNICODE_STRING ValueName,
208 PINFCONTEXT Context,
209 ULONG Flags)
210 {
211 WCHAR EmptyStr = (WCHAR)0;
212 ULONG Type;
213 ULONG Size;
214
215 if (Flags & FLG_ADDREG_DELVAL) /* deletion */
216 {
217 #if 0
218 if (ValueName)
219 {
220 RegDeleteValueW( KeyHandle, ValueName );
221 }
222 else
223 {
224 RegDeleteKeyW( KeyHandle, NULL );
225 }
226 #endif
227 return TRUE;
228 }
229
230 if (Flags & FLG_ADDREG_KEYONLY)
231 return TRUE;
232
233 #if 0
234 if (Flags & (FLG_ADDREG_NOCLOBBER | FLG_ADDREG_OVERWRITEONLY))
235 {
236 BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL );
237 if (exists && (flags & FLG_ADDREG_NOCLOBBER))
238 return TRUE;
239 if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY))
240 return TRUE;
241 }
242 #endif
243
244 switch (Flags & FLG_ADDREG_TYPE_MASK)
245 {
246 case FLG_ADDREG_TYPE_SZ:
247 Type = REG_SZ;
248 break;
249
250 case FLG_ADDREG_TYPE_MULTI_SZ:
251 Type = REG_MULTI_SZ;
252 break;
253
254 case FLG_ADDREG_TYPE_EXPAND_SZ:
255 Type = REG_EXPAND_SZ;
256 break;
257
258 case FLG_ADDREG_TYPE_BINARY:
259 Type = REG_BINARY;
260 break;
261
262 case FLG_ADDREG_TYPE_DWORD:
263 Type = REG_DWORD;
264 break;
265
266 case FLG_ADDREG_TYPE_NONE:
267 Type = REG_NONE;
268 break;
269
270 default:
271 Type = Flags >> 16;
272 break;
273 }
274
275 if (!(Flags & FLG_ADDREG_BINVALUETYPE) ||
276 (Type == REG_DWORD && SetupGetFieldCount (Context) == 5))
277 {
278 PWCHAR Str = NULL;
279
280 if (Type == REG_MULTI_SZ)
281 {
282 if (!SetupGetMultiSzFieldW (Context, 5, NULL, 0, &Size))
283 Size = 0;
284
285 if (Size)
286 {
287 Str = (WCHAR*) RtlAllocateHeap (ProcessHeap, 0, Size * sizeof(WCHAR));
288 if (Str == NULL)
289 return FALSE;
290
291 SetupGetMultiSzFieldW (Context, 5, Str, Size, NULL);
292 }
293
294 if (Flags & FLG_ADDREG_APPEND)
295 {
296 if (Str == NULL)
297 return TRUE;
298
299 // append_multi_sz_value( hkey, value, str, size );
300
301 RtlFreeHeap (ProcessHeap, 0, Str);
302 return TRUE;
303 }
304 /* else fall through to normal string handling */
305 }
306 else
307 {
308 if (!SetupGetStringFieldW (Context, 5, NULL, 0, &Size))
309 Size = 0;
310
311 if (Size)
312 {
313 Str = (WCHAR*) RtlAllocateHeap (ProcessHeap, 0, Size * sizeof(WCHAR));
314 if (Str == NULL)
315 return FALSE;
316
317 SetupGetStringFieldW (Context, 5, Str, Size, NULL);
318 }
319 }
320
321 if (Type == REG_DWORD)
322 {
323 ULONG dw = Str ? wcstoul (Str, NULL, 0) : 0;
324
325 DPRINT("setting dword %wZ to %lx\n", ValueName, dw);
326
327 #ifdef __REACTOS__
328 NtSetValueKey (KeyHandle,
329 ValueName,
330 0,
331 Type,
332 (PVOID)&dw,
333 sizeof(ULONG));
334 #else
335 RegSetValueExW(KeyHandle, ValueName, 0, Type, (const UCHAR*)&dw, sizeof(ULONG));
336 #endif
337 }
338 else
339 {
340 DPRINT("setting value %wZ to %S\n", ValueName, Str);
341
342 if (Str)
343 {
344 #ifdef __REACTOS__
345 NtSetValueKey (KeyHandle,
346 ValueName,
347 0,
348 Type,
349 (PVOID)Str,
350 Size * sizeof(WCHAR));
351 #else
352 RegSetValueExW(KeyHandle, ValueName, 0, Type, (const UCHAR*)Str, Size * sizeof(WCHAR));
353 #endif
354 }
355 else
356 {
357 #ifdef __REACTOS__
358 NtSetValueKey (KeyHandle,
359 ValueName,
360 0,
361 Type,
362 (PVOID)&EmptyStr,
363 sizeof(WCHAR));
364 #else
365 RegSetValueExW(KeyHandle, ValueName, 0, Type, (const UCHAR*)&EmptyStr, sizeof(WCHAR));
366 #endif
367 }
368 }
369 RtlFreeHeap (ProcessHeap, 0, Str);
370 }
371 else /* get the binary data */
372 {
373 PUCHAR Data = NULL;
374
375 if (!SetupGetBinaryField (Context, 5, NULL, 0, &Size))
376 Size = 0;
377
378 if (Size)
379 {
380 Data = (unsigned char*) RtlAllocateHeap (ProcessHeap, 0, Size);
381 if (Data == NULL)
382 return FALSE;
383
384 DPRINT("setting binary data %wZ len %lu\n", ValueName, Size);
385 SetupGetBinaryField (Context, 5, Data, Size, NULL);
386 }
387
388 #ifdef __REACTOS__
389 NtSetValueKey (KeyHandle,
390 ValueName,
391 0,
392 Type,
393 (PVOID)Data,
394 Size);
395 #else
396 RegSetValueExW(KeyHandle, ValueName, 0, Type, (const UCHAR*)Data, Size);
397 #endif
398
399 RtlFreeHeap (ProcessHeap, 0, Data);
400 }
401
402 return TRUE;
403 }
404
405 #ifdef __REACTOS__
406 NTSTATUS
407 CreateNestedKey (PHANDLE KeyHandle,
408 ACCESS_MASK DesiredAccess,
409 POBJECT_ATTRIBUTES ObjectAttributes)
410 {
411 OBJECT_ATTRIBUTES LocalObjectAttributes;
412 UNICODE_STRING LocalKeyName;
413 ULONG Disposition;
414 NTSTATUS Status;
415 USHORT FullNameLength;
416 PWCHAR Ptr;
417 HANDLE LocalKeyHandle;
418
419 Status = NtCreateKey (KeyHandle,
420 KEY_ALL_ACCESS,
421 ObjectAttributes,
422 0,
423 NULL,
424 0,
425 &Disposition);
426 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
427 if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
428 return Status;
429
430 /* Copy object attributes */
431 RtlCopyMemory (&LocalObjectAttributes,
432 ObjectAttributes,
433 sizeof(OBJECT_ATTRIBUTES));
434 RtlCreateUnicodeString (&LocalKeyName,
435 ObjectAttributes->ObjectName->Buffer);
436 LocalObjectAttributes.ObjectName = &LocalKeyName;
437 FullNameLength = LocalKeyName.Length;
438
439 /* Remove the last part of the key name and try to create the key again. */
440 while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
441 {
442 Ptr = wcsrchr (LocalKeyName.Buffer, '\\');
443 if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
444 {
445 Status = STATUS_UNSUCCESSFUL;
446 break;
447 }
448 *Ptr = (WCHAR)0;
449 LocalKeyName.Length = wcslen (LocalKeyName.Buffer) * sizeof(WCHAR);
450
451 Status = NtCreateKey (&LocalKeyHandle,
452 KEY_ALL_ACCESS,
453 &LocalObjectAttributes,
454 0,
455 NULL,
456 0,
457 &Disposition);
458 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
459 }
460
461 if (!NT_SUCCESS(Status))
462 {
463 RtlFreeUnicodeString (&LocalKeyName);
464 return Status;
465 }
466
467 /* Add removed parts of the key name and create them too. */
468 while (TRUE)
469 {
470 if (LocalKeyName.Length == FullNameLength)
471 {
472 Status = STATUS_SUCCESS;
473 *KeyHandle = LocalKeyHandle;
474 break;
475 }
476 NtClose (LocalKeyHandle);
477
478 LocalKeyName.Buffer[LocalKeyName.Length / sizeof(WCHAR)] = L'\\';
479 LocalKeyName.Length = wcslen (LocalKeyName.Buffer) * sizeof(WCHAR);
480
481 Status = NtCreateKey (&LocalKeyHandle,
482 KEY_ALL_ACCESS,
483 &LocalObjectAttributes,
484 0,
485 NULL,
486 0,
487 &Disposition);
488 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
489 if (!NT_SUCCESS(Status))
490 break;
491 }
492
493 RtlFreeUnicodeString (&LocalKeyName);
494
495 return Status;
496 }
497 #endif
498
499 /***********************************************************************
500 * registry_callback
501 *
502 * Called once for each AddReg and DelReg entry in a given section.
503 */
504 static BOOLEAN
505 registry_callback(HINF hInf, PCWSTR Section, BOOLEAN Delete)
506 {
507 OBJECT_ATTRIBUTES ObjectAttributes;
508 WCHAR Buffer[MAX_INF_STRING_LENGTH];
509 UNICODE_STRING Name;
510 UNICODE_STRING Value;
511 PUNICODE_STRING ValuePtr;
512 NTSTATUS Status;
513 UINT Flags;
514 ULONG Length;
515
516 INFCONTEXT Context;
517 HANDLE KeyHandle;
518 BOOLEAN Ok;
519
520
521 Ok = SetupFindFirstLineW (hInf, Section, NULL, &Context);
522
523 if (Ok)
524 {
525 for (;Ok; Ok = SetupFindNextLine (&Context, &Context))
526 {
527 /* get root */
528 if (!SetupGetStringFieldW (&Context, 1, Buffer, MAX_INF_STRING_LENGTH, NULL))
529 continue;
530 if (!GetRootKey (Buffer))
531 continue;
532
533 /* get key */
534 Length = wcslen (Buffer);
535 if (!SetupGetStringFieldW (&Context, 2, Buffer + Length, MAX_INF_STRING_LENGTH - Length, NULL))
536 *Buffer = 0;
537
538 DPRINT("KeyName: <%S>\n", Buffer);
539
540 /* get flags */
541 if (!SetupGetIntField (&Context, 4, (PINT)&Flags))
542 Flags = 0;
543
544 DPRINT("Flags: %lx\n", Flags);
545
546 #ifdef __REACTOS__
547 RtlInitUnicodeString (&Name,
548 Buffer);
549
550 InitializeObjectAttributes (&ObjectAttributes,
551 &Name,
552 OBJ_CASE_INSENSITIVE,
553 NULL,
554 NULL);
555
556 if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
557 {
558 Status = NtOpenKey (&KeyHandle,
559 KEY_ALL_ACCESS,
560 &ObjectAttributes);
561 if (!NT_SUCCESS(Status))
562 {
563 DPRINT("NtOpenKey(%wZ) failed (Status %lx)\n", &Name, Status);
564 continue; /* ignore if it doesn't exist */
565 }
566 }
567 else
568 {
569 Status = CreateNestedKey (&KeyHandle,
570 KEY_ALL_ACCESS,
571 &ObjectAttributes);
572 if (!NT_SUCCESS(Status))
573 {
574 DPRINT("CreateNestedKey(%wZ) failed (Status %lx)\n", &Name, Status);
575 continue;
576 }
577 }
578 #else
579 if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
580 {
581 LONG rc = RegOpenKeyW(NULL, Buffer, &KeyHandle);
582 if (rc != ERROR_SUCCESS)
583 {
584 DPRINT("RegOpenKeyW(%S) failed (error %lu)\n", Buffer, rc);
585 continue; /* ignore if it doesn't exist */
586 }
587 }
588 else
589 {
590 LONG rc = RegCreateKeyW(NULL, Buffer, &KeyHandle);
591 if (rc != ERROR_SUCCESS)
592 {
593 DPRINT("RegCreateKeyW(%S) failed (error %lu)\n", Buffer, rc);
594 continue;
595 }
596 }
597 #endif
598
599 /* get value name */
600 if (SetupGetStringFieldW (&Context, 3, Buffer, MAX_INF_STRING_LENGTH, NULL))
601 {
602 RtlInitUnicodeString (&Value,
603 Buffer);
604 ValuePtr = &Value;
605 }
606 else
607 {
608 ValuePtr = NULL;
609 }
610
611 /* and now do it */
612 if (!do_reg_operation (KeyHandle, ValuePtr, &Context, Flags))
613 {
614 NtClose (KeyHandle);
615 return FALSE;
616 }
617
618 #ifdef __REACTOS__
619 NtClose (KeyHandle);
620 #endif
621 }
622 }
623
624 return TRUE;
625 }
626
627
628 BOOLEAN
629 ImportRegistryFile(
630 PWSTR Filename,
631 PWSTR Section,
632 LCID LocaleId,
633 BOOLEAN Delete)
634 {
635 WCHAR FileNameBuffer[MAX_PATH];
636 HINF hInf;
637 UINT ErrorLine;
638
639 /* Load inf file from install media. */
640 wcscpy(FileNameBuffer, SourcePath.Buffer);
641 wcscat(FileNameBuffer, L"\\");
642 wcscat(FileNameBuffer, Filename);
643
644 hInf = SetupOpenInfFileW(FileNameBuffer,
645 NULL,
646 INF_STYLE_WIN4,
647 LocaleId,
648 &ErrorLine);
649 if (hInf == INVALID_HANDLE_VALUE)
650 {
651 DPRINT1("SetupOpenInfFile() failed\n");
652 return FALSE;
653 }
654
655 if (!registry_callback(hInf, L"AddReg", FALSE))
656 {
657 DPRINT1("registry_callback() failed\n");
658 }
659
660 if (!registry_callback(hInf, L"AddReg.NT" Architecture, FALSE))
661 {
662 DPRINT1("registry_callback() failed\n");
663 }
664
665 InfCloseFile(hInf);
666
667 return TRUE;
668 }
669
670
671 BOOLEAN
672 SetInstallPathValue(
673 PUNICODE_STRING InstallPath)
674 {
675 OBJECT_ATTRIBUTES ObjectAttributes;
676 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE");
677 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath");
678 HANDLE KeyHandle;
679 NTSTATUS Status;
680
681 /* Create the 'secret' InstallPath key */
682 InitializeObjectAttributes(&ObjectAttributes,
683 &KeyName,
684 OBJ_CASE_INSENSITIVE,
685 NULL,
686 NULL);
687 Status = NtOpenKey(&KeyHandle,
688 KEY_ALL_ACCESS,
689 &ObjectAttributes);
690 if (!NT_SUCCESS(Status))
691 {
692 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
693 return FALSE;
694 }
695
696 Status = NtSetValueKey(KeyHandle,
697 &ValueName,
698 0,
699 REG_SZ,
700 (PVOID)InstallPath->Buffer,
701 InstallPath->Length + sizeof(WCHAR));
702 NtClose(KeyHandle);
703 if (!NT_SUCCESS(Status))
704 {
705 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
706 return FALSE;
707 }
708
709 return TRUE;
710 }
711
712
713 BOOLEAN
714 SetMountedDeviceValue(
715 CHAR Letter,
716 ULONG Signature,
717 LARGE_INTEGER StartingOffset)
718 {
719 OBJECT_ATTRIBUTES ObjectAttributes;
720 WCHAR ValueNameBuffer[16];
721 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
722 UNICODE_STRING ValueName;
723 REG_DISK_MOUNT_INFO MountInfo;
724 NTSTATUS Status;
725 HANDLE KeyHandle;
726
727 swprintf(ValueNameBuffer, L"\\DosDevices\\%C:", Letter);
728 RtlInitUnicodeString(&ValueName, ValueNameBuffer);
729
730 InitializeObjectAttributes(&ObjectAttributes,
731 &KeyName,
732 OBJ_CASE_INSENSITIVE,
733 NULL,
734 NULL);
735 Status = NtOpenKey(&KeyHandle,
736 KEY_ALL_ACCESS,
737 &ObjectAttributes);
738 if (!NT_SUCCESS(Status))
739 {
740 Status = NtCreateKey(&KeyHandle,
741 KEY_ALL_ACCESS,
742 &ObjectAttributes,
743 0,
744 NULL,
745 REG_OPTION_NON_VOLATILE,
746 NULL);
747 }
748
749 if (!NT_SUCCESS(Status))
750 {
751 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
752 return FALSE;
753 }
754
755 MountInfo.Signature = Signature;
756 MountInfo.StartingOffset = StartingOffset;
757 Status = NtSetValueKey(KeyHandle,
758 &ValueName,
759 0,
760 REG_BINARY,
761 (PVOID)&MountInfo,
762 sizeof(MountInfo));
763 NtClose(KeyHandle);
764 if (!NT_SUCCESS(Status))
765 {
766 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
767 return FALSE;
768 }
769
770 return TRUE;
771 }
772
773
774 VOID
775 SetDefaultPagefile(
776 WCHAR Drive)
777 {
778 OBJECT_ATTRIBUTES ObjectAttributes;
779 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
780 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"PagingFiles");
781 WCHAR ValueBuffer[] = L"?:\\pagefile.sys 0 0\0";
782 HANDLE KeyHandle;
783 NTSTATUS Status;
784
785 InitializeObjectAttributes(&ObjectAttributes,
786 &KeyName,
787 OBJ_CASE_INSENSITIVE,
788 NULL,
789 NULL);
790 Status = NtOpenKey(&KeyHandle,
791 KEY_ALL_ACCESS,
792 &ObjectAttributes);
793 if (!NT_SUCCESS(Status))
794 return;
795
796 ValueBuffer[0] = Drive;
797
798 NtSetValueKey(KeyHandle,
799 &ValueName,
800 0,
801 REG_MULTI_SZ,
802 (PVOID)&ValueBuffer,
803 sizeof(ValueBuffer));
804
805 NtClose(KeyHandle);
806 }
807
808 /* EOF */