ed1d6420e21c51bd53be44426a84a68a8c6d99d3
[reactos.git] / reactos / drivers / filesystems / ntfs / blockdev.c
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 * PROGRAMMER: Eric Kohl
24 */
25
26 /* INCLUDES *****************************************************************/
27
28 #include "ntfs.h"
29
30 #define NDEBUG
31 #include <debug.h>
32
33 /* FUNCTIONS ****************************************************************/
34
35 NTSTATUS
36 NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
37 IN LONGLONG StartingOffset,
38 IN ULONG Length,
39 IN ULONG SectorSize,
40 IN OUT PUCHAR Buffer,
41 IN BOOLEAN Override)
42 {
43 PIO_STACK_LOCATION Stack;
44 IO_STATUS_BLOCK IoStatus;
45 LARGE_INTEGER Offset;
46 KEVENT Event;
47 PIRP Irp;
48 NTSTATUS Status;
49 ULONGLONG RealReadOffset;
50 ULONG RealLength;
51 BOOLEAN AllocatedBuffer = FALSE;
52 PUCHAR ReadBuffer = Buffer;
53
54 DPRINT("NtfsReadDisk(%p, %I64x, %u, %u, %p, %d)\n", DeviceObject, StartingOffset, Length, SectorSize, Buffer, Override);
55
56 KeInitializeEvent(&Event,
57 NotificationEvent,
58 FALSE);
59
60 RealReadOffset = (ULONGLONG)StartingOffset;
61 RealLength = Length;
62
63 if ((RealReadOffset % SectorSize) != 0 || (RealLength % SectorSize) != 0)
64 {
65 RealReadOffset = ROUND_DOWN(StartingOffset, SectorSize);
66 RealLength = ROUND_UP(Length, SectorSize);
67
68 ReadBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength + SectorSize, TAG_NTFS);
69 if (ReadBuffer == NULL)
70 {
71 DPRINT1("Not enough memory!\n");
72 return STATUS_INSUFFICIENT_RESOURCES;
73 }
74 AllocatedBuffer = TRUE;
75 }
76
77 Offset.QuadPart = RealReadOffset;
78
79 DPRINT("Building synchronous FSD Request...\n");
80 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
81 DeviceObject,
82 ReadBuffer,
83 RealLength,
84 &Offset,
85 &Event,
86 &IoStatus);
87 if (Irp == NULL)
88 {
89 DPRINT("IoBuildSynchronousFsdRequest failed\n");
90 return STATUS_INSUFFICIENT_RESOURCES;
91 }
92
93 if (Override)
94 {
95 Stack = IoGetNextIrpStackLocation(Irp);
96 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
97 }
98
99 DPRINT("Calling IO Driver... with irp %p\n", Irp);
100 Status = IoCallDriver(DeviceObject, Irp);
101
102 DPRINT("Waiting for IO Operation for %p\n", Irp);
103 if (Status == STATUS_PENDING)
104 {
105 DPRINT("Operation pending\n");
106 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
107 DPRINT("Getting IO Status... for %p\n", Irp);
108 Status = IoStatus.Status;
109 }
110
111 if (NT_SUCCESS(Status) && AllocatedBuffer)
112 {
113 RtlCopyMemory(Buffer, ReadBuffer + (StartingOffset - RealReadOffset), Length);
114 ExFreePoolWithTag(ReadBuffer, TAG_NTFS);
115 }
116
117 DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
118
119 return Status;
120 }
121
122 NTSTATUS
123 NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
124 IN ULONG DiskSector,
125 IN ULONG SectorCount,
126 IN ULONG SectorSize,
127 IN OUT PUCHAR Buffer,
128 IN BOOLEAN Override)
129 {
130 LONGLONG Offset;
131 ULONG BlockSize;
132
133 Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
134 BlockSize = SectorCount * SectorSize;
135
136 return NtfsReadDisk(DeviceObject, Offset, BlockSize, SectorSize, Buffer, Override);
137 }
138
139
140 NTSTATUS
141 NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
142 IN ULONG ControlCode,
143 IN PVOID InputBuffer,
144 IN ULONG InputBufferSize,
145 IN OUT PVOID OutputBuffer,
146 IN OUT PULONG OutputBufferSize,
147 IN BOOLEAN Override)
148 {
149 PIO_STACK_LOCATION Stack;
150 IO_STATUS_BLOCK IoStatus;
151 KEVENT Event;
152 PIRP Irp;
153 NTSTATUS Status;
154
155 KeInitializeEvent(&Event, NotificationEvent, FALSE);
156
157 DPRINT("Building device I/O control request ...\n");
158 Irp = IoBuildDeviceIoControlRequest(ControlCode,
159 DeviceObject,
160 InputBuffer,
161 InputBufferSize,
162 OutputBuffer,
163 (OutputBufferSize) ? *OutputBufferSize : 0,
164 FALSE,
165 &Event,
166 &IoStatus);
167 if (Irp == NULL)
168 {
169 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
170 return STATUS_INSUFFICIENT_RESOURCES;
171 }
172
173 if (Override)
174 {
175 Stack = IoGetNextIrpStackLocation(Irp);
176 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
177 }
178
179 DPRINT("Calling IO Driver... with irp %p\n", Irp);
180 Status = IoCallDriver(DeviceObject, Irp);
181 if (Status == STATUS_PENDING)
182 {
183 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
184 Status = IoStatus.Status;
185 }
186
187 if (OutputBufferSize)
188 {
189 *OutputBufferSize = IoStatus.Information;
190 }
191
192 return Status;
193 }
194
195 /* EOF */