ReactOS  0.4.14-dev-583-g2a1ba2c
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 
39  IN ULONG Length,
42  IN BOOLEAN Override)
43 {
44  PIO_STACK_LOCATION Stack;
47  KEVENT Event;
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");
83  ReadBuffer,
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 
162 NTSTATUS
165  IN ULONG Length,
167  IN const PUCHAR Buffer)
168 {
171  KEVENT Event;
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
259  DeviceObject,
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 
307 NTSTATUS
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 
325 NTSTATUS
329  IN ULONG InputBufferSize,
331  IN OUT PULONG OutputBufferSize,
332  IN BOOLEAN Override)
333 {
334  PIO_STACK_LOCATION Stack;
336  KEVENT Event;
337  PIRP Irp;
339 
341 
342  DPRINT("Building device I/O control request ...\n");
344  DeviceObject,
345  InputBuffer,
346  InputBufferSize,
347  OutputBuffer,
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 */
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN OUT PIO_STATUS_BLOCK IoStatus
Definition: fatprocs.h:2650
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
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS NtfsWriteDisk(IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN const PUCHAR Buffer)
Definition: blockdev.c:163
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define ReadBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:339
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
CHAR InputBuffer[80]
Definition: conmgr.c:33
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
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1780
void DPRINT(...)
Definition: polytest.cpp:61
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
Definition: bufpool.h:45
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
int64_t LONGLONG
Definition: typedefs.h:66
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
uint64_t ULONGLONG
Definition: typedefs.h:65
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define TAG_NTFS
Definition: ntfs.h:12
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG SectorCount
Definition: part_xbox.c:32
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
Status
Definition: gdiplustypes.h:24
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:30
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
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
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
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 DPRINT1
Definition: precomp.h:8
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_In_ ULONG SectorSize
Definition: halfuncs.h:291
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2938
FORCEINLINE PVOID RtlSecureZeroMemory(_Out_writes_bytes_all_(Size) PVOID Pointer, _In_ SIZE_T Size)
Definition: rtlfuncs.h:3127
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