xref: /reactos/ntoskrnl/config/cmwraprs.c (revision 7f26a396)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/config/cmwraprs.c
5  * PURPOSE:         Configuration Manager - Wrappers for Hive Operations
6  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14 
15 /* FUNCTIONS *****************************************************************/
16 
17 NTSTATUS
18 NTAPI
19 CmpCreateEvent(IN EVENT_TYPE EventType,
20                OUT PHANDLE EventHandle,
21                OUT PKEVENT *Event)
22 {
23     NTSTATUS Status;
24     OBJECT_ATTRIBUTES ObjectAttributes;
25 
26     /* Create the event */
27     InitializeObjectAttributes(&ObjectAttributes,
28                                NULL,
29                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
30                                NULL,
31                                NULL);
32     Status = ZwCreateEvent(EventHandle,
33                            EVENT_ALL_ACCESS,
34                            &ObjectAttributes,
35                            EventType,
36                            FALSE);
37     if (!NT_SUCCESS(Status)) return Status;
38 
39     /* Get a pointer to the object itself */
40     Status = ObReferenceObjectByHandle(*EventHandle,
41                                        EVENT_ALL_ACCESS,
42                                        NULL,
43                                        KernelMode,
44                                        (PVOID*)Event,
45                                        NULL);
46     if (!NT_SUCCESS(Status)) ZwClose(*EventHandle);
47 
48     /* Return status */
49     return Status;
50 }
51 
52 PVOID
53 NTAPI
54 CmpAllocate(IN SIZE_T Size,
55             IN BOOLEAN Paged,
56             IN ULONG Tag)
57 {
58     return ExAllocatePoolWithTag(Paged ? PagedPool : NonPagedPool,
59                                  Size,
60                                  Tag);
61 }
62 
63 VOID
64 NTAPI
65 CmpFree(IN PVOID Ptr,
66         IN ULONG Quota)
67 {
68     ExFreePool(Ptr);
69 }
70 
71 BOOLEAN
72 NTAPI
73 CmpFileRead(IN PHHIVE RegistryHive,
74             IN ULONG FileType,
75             IN PULONG FileOffset,
76             OUT PVOID Buffer,
77             IN SIZE_T BufferLength)
78 {
79     PCMHIVE CmHive = (PCMHIVE)RegistryHive;
80     HANDLE HiveHandle = CmHive->FileHandles[FileType];
81     LARGE_INTEGER _FileOffset;
82     IO_STATUS_BLOCK IoStatusBlock;
83     NTSTATUS Status;
84 
85     /* Just return success if no file is associated with this hive */
86     if (HiveHandle == NULL)
87         return TRUE;
88 
89     _FileOffset.QuadPart = *FileOffset;
90     Status = ZwReadFile(HiveHandle, NULL, NULL, NULL, &IoStatusBlock,
91                         Buffer, (ULONG)BufferLength, &_FileOffset, NULL);
92     /* We do synchronous I/O for simplicity - see CmpOpenHiveFiles. */
93     ASSERT(Status != STATUS_PENDING);
94     return NT_SUCCESS(Status) ? TRUE : FALSE;
95 }
96 
97 BOOLEAN
98 NTAPI
99 CmpFileWrite(IN PHHIVE RegistryHive,
100              IN ULONG FileType,
101              IN PULONG FileOffset,
102              IN PVOID Buffer,
103              IN SIZE_T BufferLength)
104 {
105     PCMHIVE CmHive = (PCMHIVE)RegistryHive;
106     HANDLE HiveHandle = CmHive->FileHandles[FileType];
107     LARGE_INTEGER _FileOffset;
108     IO_STATUS_BLOCK IoStatusBlock;
109     NTSTATUS Status;
110 
111     /* Just return success if no file is associated with this hive */
112     if (HiveHandle == NULL)
113         return TRUE;
114 
115     /* Don't do anything if we're not supposed to */
116     if (CmpNoWrite)
117         return TRUE;
118 
119     _FileOffset.QuadPart = *FileOffset;
120     Status = ZwWriteFile(HiveHandle, NULL, NULL, NULL, &IoStatusBlock,
121                          Buffer, (ULONG)BufferLength, &_FileOffset, NULL);
122     /* We do synchronous I/O for simplicity - see CmpOpenHiveFiles.
123      * Windows optimizes here by starting an async write for each 64k chunk,
124      * then waiting for all writes to complete at once.
125      */
126     ASSERT(Status != STATUS_PENDING);
127     return NT_SUCCESS(Status) ? TRUE : FALSE;
128 }
129 
130 BOOLEAN
131 NTAPI
132 CmpFileSetSize(
133     _In_ PHHIVE RegistryHive,
134     _In_ ULONG FileType,
135     _In_ ULONG FileSize,
136     _In_ ULONG OldFileSize)
137 {
138     PCMHIVE CmHive = (PCMHIVE)RegistryHive;
139     HANDLE HiveHandle = CmHive->FileHandles[FileType];
140     FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
141     FILE_ALLOCATION_INFORMATION FileAllocationInfo;
142     IO_STATUS_BLOCK IoStatusBlock;
143     BOOLEAN HardErrors;
144     NTSTATUS Status;
145 
146     /* Just return success if no file is associated with this hive */
147     if (HiveHandle == NULL)
148     {
149         DPRINT1("No hive handle associated with the given hive\n");
150         return TRUE;
151     }
152 
153     /*
154      * Disable hard errors so that we don't deadlock
155      * when touching with the hive files.
156      */
157     HardErrors = IoSetThreadHardErrorMode(FALSE);
158 
159     EndOfFileInfo.EndOfFile.QuadPart = FileSize;
160     Status = ZwSetInformationFile(HiveHandle,
161                                   &IoStatusBlock,
162                                   &EndOfFileInfo,
163                                   sizeof(FILE_END_OF_FILE_INFORMATION),
164                                   FileEndOfFileInformation);
165     if (!NT_SUCCESS(Status))
166     {
167         DPRINT1("ZwSetInformationFile failed to set new size of end of file (Status 0x%lx)\n", Status);
168         IoSetThreadHardErrorMode(HardErrors);
169         return FALSE;
170     }
171 
172     FileAllocationInfo.AllocationSize.QuadPart = FileSize;
173     Status = ZwSetInformationFile(HiveHandle,
174                                   &IoStatusBlock,
175                                   &FileAllocationInfo,
176                                   sizeof(FILE_ALLOCATION_INFORMATION),
177                                   FileAllocationInformation);
178     if (!NT_SUCCESS(Status))
179     {
180         DPRINT1("ZwSetInformationFile failed to set new of allocation file (Status 0x%lx)\n", Status);
181         IoSetThreadHardErrorMode(HardErrors);
182         return FALSE;
183     }
184 
185     /* Reset the hard errors back */
186     IoSetThreadHardErrorMode(HardErrors);
187     return TRUE;
188 }
189 
190 BOOLEAN
191 NTAPI
192 CmpFileFlush(IN PHHIVE RegistryHive,
193              IN ULONG FileType,
194              IN OUT PLARGE_INTEGER FileOffset,
195              IN ULONG Length)
196 {
197     PCMHIVE CmHive = (PCMHIVE)RegistryHive;
198     HANDLE HiveHandle = CmHive->FileHandles[FileType];
199     IO_STATUS_BLOCK IoStatusBlock;
200     NTSTATUS Status;
201 
202     /* Just return success if no file is associated with this hive */
203     if (HiveHandle == NULL)
204         return TRUE;
205 
206     /* Don't do anything if we're not supposed to */
207     if (CmpNoWrite)
208         return TRUE;
209 
210     Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock);
211 
212     /* This operation is always synchronous */
213     ASSERT(Status != STATUS_PENDING);
214     ASSERT(Status == IoStatusBlock.Status);
215 
216     return NT_SUCCESS(Status) ? TRUE : FALSE;
217 }
218