ReactOS 0.4.15-dev-8191-gbc6c731
blockdev.c
Go to the documentation of this file.
1/*
2 * ReactOS kernel
3 * Copyright (C) 2002 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/blockdev.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMERS: Eric Kohl
24 * Trevor Thompson
25 */
26
27/* INCLUDES *****************************************************************/
28
29#include "ntfs.h"
30
31#define NDEBUG
32#include <debug.h>
33
34/* FUNCTIONS ****************************************************************/
35
42 IN BOOLEAN Override)
43{
48 PIRP Irp;
50 ULONGLONG RealReadOffset;
51 ULONG RealLength;
52 BOOLEAN AllocatedBuffer = FALSE;
54
55 DPRINT("NtfsReadDisk(%p, %I64x, %lu, %lu, %p, %d)\n", DeviceObject, StartingOffset, Length, SectorSize, Buffer, Override);
56
59 FALSE);
60
61 RealReadOffset = (ULONGLONG)StartingOffset;
62 RealLength = Length;
63
64 if ((RealReadOffset % SectorSize) != 0 || (RealLength % SectorSize) != 0)
65 {
66 RealReadOffset = ROUND_DOWN(StartingOffset, SectorSize);
67 RealLength = ROUND_UP(Length, SectorSize);
68
70 if (ReadBuffer == NULL)
71 {
72 DPRINT1("Not enough memory!\n");
74 }
75 AllocatedBuffer = TRUE;
76 }
77
78 Offset.QuadPart = RealReadOffset;
79
80 DPRINT("Building synchronous FSD Request...\n");
84 RealLength,
85 &Offset,
86 &Event,
87 &IoStatus);
88 if (Irp == NULL)
89 {
90 DPRINT("IoBuildSynchronousFsdRequest failed\n");
91
92 if (AllocatedBuffer)
93 {
95 }
96
98 }
99
100 if (Override)
101 {
104 }
105
106 DPRINT("Calling IO Driver... with irp %p\n", Irp);
108
109 DPRINT("Waiting for IO Operation for %p\n", Irp);
110 if (Status == STATUS_PENDING)
111 {
112 DPRINT("Operation pending\n");
114 DPRINT("Getting IO Status... for %p\n", Irp);
115 Status = IoStatus.Status;
116 }
117
118 if (AllocatedBuffer)
119 {
120 if (NT_SUCCESS(Status))
121 {
122 RtlCopyMemory(Buffer, ReadBuffer + (StartingOffset - RealReadOffset), Length);
123 }
124
126 }
127
128 DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
129
130 return Status;
131}
132
167 IN const PUCHAR Buffer)
168{
172 PIRP Irp;
174 ULONGLONG RealWriteOffset;
175 ULONG RealLength;
176 BOOLEAN AllocatedBuffer = FALSE;
177 PUCHAR TempBuffer = NULL;
178
179 DPRINT("NtfsWriteDisk(%p, %I64x, %lu, %lu, %p)\n", DeviceObject, StartingOffset, Length, SectorSize, Buffer);
180
181 if (Length == 0)
182 return STATUS_SUCCESS;
183
184 RealWriteOffset = (ULONGLONG)StartingOffset;
185 RealLength = Length;
186
187 // Does the write need to be adjusted to be sector-aligned?
188 if ((RealWriteOffset % SectorSize) != 0 || (RealLength % SectorSize) != 0)
189 {
190 ULONGLONG relativeOffset;
191
192 // We need to do a read-modify-write. We'll start be copying the entire
193 // contents of every sector that will be overwritten.
194 // TODO: Optimize (read no more than necessary)
195
196 RealWriteOffset = ROUND_DOWN(StartingOffset, SectorSize);
197 RealLength = ROUND_UP(Length, SectorSize);
198
199 // Would the end of our sector-aligned write fall short of the requested write?
200 if (RealWriteOffset + RealLength < StartingOffset + Length)
201 {
202 RealLength += SectorSize;
203 }
204
205 // Did we underestimate the memory required somehow?
206 if (RealLength + RealWriteOffset < StartingOffset + Length)
207 {
208 DPRINT1("\a\t\t\t\t\tFIXME: calculated less memory than needed!\n");
209 DPRINT1("StartingOffset: %lu\tLength: %lu\tRealWriteOffset: %lu\tRealLength: %lu\n",
210 StartingOffset, Length, RealWriteOffset, RealLength);
211
212 RealLength += SectorSize;
213 }
214
215 // Allocate a buffer to copy the existing data to
216 TempBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength, TAG_NTFS);
217
218 // Did we fail to allocate it?
219 if (TempBuffer == NULL)
220 {
221 DPRINT1("Not enough memory!\n");
222
224 }
225
226 // Read the sectors we'll be overwriting into TempBuffer
227 Status = NtfsReadDisk(DeviceObject, RealWriteOffset, RealLength, SectorSize, TempBuffer, FALSE);
228
229 // Did we fail the read?
230 if (!NT_SUCCESS(Status))
231 {
232 RtlSecureZeroMemory(TempBuffer, RealLength);
233 ExFreePoolWithTag(TempBuffer, TAG_NTFS);
234 return Status;
235 }
236
237 // Calculate where the new data should be written to, relative to the start of TempBuffer
238 relativeOffset = StartingOffset - RealWriteOffset;
239
240 // Modify the tempbuffer with the data being read
241 RtlCopyMemory(TempBuffer + relativeOffset, Buffer, Length);
242
243 AllocatedBuffer = TRUE;
244 }
245
246 // set the destination offset
247 Offset.QuadPart = RealWriteOffset;
248
249 // setup the notification event for the write
252 FALSE);
253
254 DPRINT("Building synchronous FSD Request...\n");
255
256 // Build an IRP requesting the lower-level [disk] driver to perform the write
257 // TODO: Forward the existing IRP instead
260 // if we allocated a temp buffer, use that instead of the Buffer parameter
261 ((AllocatedBuffer) ? TempBuffer : Buffer),
262 RealLength,
263 &Offset,
264 &Event,
265 &IoStatus);
266 // Did we fail to build the IRP?
267 if (Irp == NULL)
268 {
269 DPRINT1("IoBuildSynchronousFsdRequest failed\n");
270
271 if (AllocatedBuffer)
272 {
273 RtlSecureZeroMemory(TempBuffer, RealLength);
274 ExFreePoolWithTag(TempBuffer, TAG_NTFS);
275 }
276
278 }
279
280 // Call the next-lower driver to perform the write
281 DPRINT("Calling IO Driver with irp %p\n", Irp);
283
284 // Wait until the next-lower driver has completed the IRP
285 DPRINT("Waiting for IO Operation for %p\n", Irp);
286 if (Status == STATUS_PENDING)
287 {
288 DPRINT("Operation pending\n");
290 DPRINT("Getting IO Status... for %p\n", Irp);
291 Status = IoStatus.Status;
292 }
293
294 if (AllocatedBuffer)
295 {
296 // zero the buffer before freeing it, so private user data can't be snooped
297 RtlSecureZeroMemory(TempBuffer, RealLength);
298
299 ExFreePoolWithTag(TempBuffer, TAG_NTFS);
300 }
301
302 DPRINT("NtfsWriteDisk() done (Status %x)\n", Status);
303
304 return Status;
305}
306
309 IN ULONG DiskSector,
313 IN BOOLEAN Override)
314{
316 ULONG BlockSize;
317
318 Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
319 BlockSize = SectorCount * SectorSize;
320
321 return NtfsReadDisk(DeviceObject, Offset, BlockSize, SectorSize, Buffer, Override);
322}
323
324
329 IN ULONG InputBufferSize,
331 IN OUT PULONG OutputBufferSize,
332 IN BOOLEAN Override)
333{
337 PIRP Irp;
339
341
342 DPRINT("Building device I/O control request ...\n");
346 InputBufferSize,
348 (OutputBufferSize) ? *OutputBufferSize : 0,
349 FALSE,
350 &Event,
351 &IoStatus);
352 if (Irp == NULL)
353 {
354 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
356 }
357
358 if (Override)
359 {
362 }
363
364 DPRINT("Calling IO Driver... with irp %p\n", Irp);
366 if (Status == STATUS_PENDING)
367 {
369 Status = IoStatus.Status;
370 }
371
372 if (OutputBufferSize)
373 {
374 *OutputBufferSize = IoStatus.Information;
375 }
376
377 return Status;
378}
379
380/* EOF */
unsigned char BOOLEAN
#define ReadBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:339
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TAG_NTFS
Definition: ntfs.h:12
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define NonPagedPool
Definition: env_spec_w32.h:307
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33
Status
Definition: gdiplustypes.h:25
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:34
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
NTSTATUS NtfsWriteDisk(IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN const PUCHAR Buffer)
Definition: blockdev.c:163
NTSTATUS NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject, IN ULONG DiskSector, IN ULONG SectorCount, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:308
NTSTATUS NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, IN ULONG ControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer, IN OUT PULONG OutputBufferSize, IN BOOLEAN Override)
Definition: blockdev.c:326
NTSTATUS NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:37
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_PENDING
Definition: ntstatus.h:82
ULONG SectorCount
Definition: part_xbox.c:31
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
_In_ ULONG SectorSize
Definition: halfuncs.h:291
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
@ Suspended
Definition: ketypes.h:420
FORCEINLINE PVOID RtlSecureZeroMemory(_Out_writes_bytes_all_(Size) PVOID Pointer, _In_ SIZE_T Size)
Definition: rtlfuncs.h:3125