[NTFS]
[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
91 if (AllocatedBuffer)
92 {
93 ExFreePoolWithTag(ReadBuffer, TAG_NTFS);
94 }
95
96 return STATUS_INSUFFICIENT_RESOURCES;
97 }
98
99 if (Override)
100 {
101 Stack = IoGetNextIrpStackLocation(Irp);
102 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
103 }
104
105 DPRINT("Calling IO Driver... with irp %p\n", Irp);
106 Status = IoCallDriver(DeviceObject, Irp);
107
108 DPRINT("Waiting for IO Operation for %p\n", Irp);
109 if (Status == STATUS_PENDING)
110 {
111 DPRINT("Operation pending\n");
112 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
113 DPRINT("Getting IO Status... for %p\n", Irp);
114 Status = IoStatus.Status;
115 }
116
117 if (AllocatedBuffer)
118 {
119 if (NT_SUCCESS(Status))
120 {
121 RtlCopyMemory(Buffer, ReadBuffer + (StartingOffset - RealReadOffset), Length);
122 }
123
124 ExFreePoolWithTag(ReadBuffer, TAG_NTFS);
125 }
126
127 DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
128
129 return Status;
130 }
131
132 NTSTATUS
133 NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
134 IN ULONG DiskSector,
135 IN ULONG SectorCount,
136 IN ULONG SectorSize,
137 IN OUT PUCHAR Buffer,
138 IN BOOLEAN Override)
139 {
140 LONGLONG Offset;
141 ULONG BlockSize;
142
143 Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
144 BlockSize = SectorCount * SectorSize;
145
146 return NtfsReadDisk(DeviceObject, Offset, BlockSize, SectorSize, Buffer, Override);
147 }
148
149
150 NTSTATUS
151 NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
152 IN ULONG ControlCode,
153 IN PVOID InputBuffer,
154 IN ULONG InputBufferSize,
155 IN OUT PVOID OutputBuffer,
156 IN OUT PULONG OutputBufferSize,
157 IN BOOLEAN Override)
158 {
159 PIO_STACK_LOCATION Stack;
160 IO_STATUS_BLOCK IoStatus;
161 KEVENT Event;
162 PIRP Irp;
163 NTSTATUS Status;
164
165 KeInitializeEvent(&Event, NotificationEvent, FALSE);
166
167 DPRINT("Building device I/O control request ...\n");
168 Irp = IoBuildDeviceIoControlRequest(ControlCode,
169 DeviceObject,
170 InputBuffer,
171 InputBufferSize,
172 OutputBuffer,
173 (OutputBufferSize) ? *OutputBufferSize : 0,
174 FALSE,
175 &Event,
176 &IoStatus);
177 if (Irp == NULL)
178 {
179 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
180 return STATUS_INSUFFICIENT_RESOURCES;
181 }
182
183 if (Override)
184 {
185 Stack = IoGetNextIrpStackLocation(Irp);
186 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
187 }
188
189 DPRINT("Calling IO Driver... with irp %p\n", Irp);
190 Status = IoCallDriver(DeviceObject, Irp);
191 if (Status == STATUS_PENDING)
192 {
193 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
194 Status = IoStatus.Status;
195 }
196
197 if (OutputBufferSize)
198 {
199 *OutputBufferSize = IoStatus.Information;
200 }
201
202 return Status;
203 }
204
205 /* EOF */