- Import disk.sys from Windows XP DDK
[reactos.git] / drivers / storage / class / disk_new / part.c
1 /*++
2
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4
5 Module Name:
6
7 disk.c
8
9 Abstract:
10
11 SCSI disk class driver
12
13 Environment:
14
15 kernel mode only
16
17 Notes:
18
19 Revision History:
20
21 --*/
22
23 #include "disk.h"
24
25 #define PtCache ClassDebugExternal1
26
27 #ifdef ALLOC_PRAGMA
28
29 #pragma alloc_text(PAGE, DiskReadPartitionTableEx)
30 #pragma alloc_text(PAGE, DiskWritePartitionTableEx)
31 #pragma alloc_text(PAGE, DiskSetPartitionInformationEx)
32 #endif
33
34 ULONG DiskBreakOnPtInval = FALSE;
35
36 //
37 // By default, 64-bit systems can see GPT disks and 32-bit systems
38 // cannot. This will likely change in the future.
39 //
40
41 #if defined(_WIN64)
42 ULONG DiskDisableGpt = FALSE;
43 #else
44 ULONG DiskDisableGpt = TRUE;
45 #endif
46
47 NTSTATUS
48 DiskReadPartitionTableEx(
49 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
50 IN BOOLEAN BypassCache,
51 OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout
52 )
53 /*++
54
55 Routine Description:
56
57 This routine will return the current layout information for the disk.
58 If the cached information is still valid then it will be returned,
59 otherwise the layout will be retreived from the kernel and cached for
60 future use.
61
62 This routine must be called with the partitioning lock held. The
63 partition list which is returned is not guaranteed to remain valid
64 once the lock has been released.
65
66 Arguments:
67
68 Fdo - a pointer to the FDO for the disk.
69
70 DriveLayout - a location to store a pointer to the drive layout information.
71
72 Return Value:
73
74 STATUS_SUCCESS if successful or an error status indicating what failed.
75
76 --*/
77
78 {
79 PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
80 NTSTATUS status;
81 PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
82
83 layoutEx = NULL;
84
85 if(BypassCache) {
86 diskData->CachedPartitionTableValid = FALSE;
87 DebugPrint((PtCache, "DiskRPTEx: cache bypassed and invalidated for "
88 "FDO %#p\n", Fdo));
89 }
90
91 //
92 // If the cached partition table is present then return a copy of it.
93 //
94
95 if(diskData->CachedPartitionTableValid == TRUE) {
96
97 ULONG partitionNumber;
98 PDRIVE_LAYOUT_INFORMATION_EX layout = diskData->CachedPartitionTable;
99
100 //
101 // Clear the partition numbers from the list entries
102 //
103
104 for(partitionNumber = 0;
105 partitionNumber < layout->PartitionCount;
106 partitionNumber++) {
107 layout->PartitionEntry[partitionNumber].PartitionNumber = 0;
108 }
109
110 *DriveLayout = diskData->CachedPartitionTable;
111
112 DebugPrint((PtCache, "DiskRPTEx: cached PT returned (%#p) for "
113 "FDO %#p\n",
114 *DriveLayout, Fdo));
115
116 return STATUS_SUCCESS;
117 }
118
119 ASSERTMSG("DiskReadPartitionTableEx is not using cached partition table",
120 (DiskBreakOnPtInval == FALSE));
121
122 //
123 // If there's a cached partition table still around then free it.
124 //
125
126 if(diskData->CachedPartitionTable) {
127 DebugPrint((PtCache, "DiskRPTEx: cached PT (%#p) freed for FDO %#p\n",
128 diskData->CachedPartitionTable, Fdo));
129
130 ExFreePool(diskData->CachedPartitionTable);
131 diskData->CachedPartitionTable = NULL;
132 }
133
134 //
135 // By default, X86 disables recognition of GPT disks. Instead we
136 // return the protective MBR partition. Use IoReadPartitionTable
137 // to get this.
138 //
139
140 status = IoReadPartitionTableEx(Fdo->DeviceObject, &layoutEx);
141
142 if (DiskDisableGpt) {
143 PDRIVE_LAYOUT_INFORMATION layout;
144
145 if (NT_SUCCESS (status) &&
146 layoutEx->PartitionStyle == PARTITION_STYLE_GPT) {
147
148 //
149 // ISSUE - 2000/29/08 - math: Remove from final product.
150 // Leave this debug print in for a while until everybody
151 // has had a chance to convert their GPT disks to MBR.
152 //
153
154 DbgPrint ("DISK: Disk %p recognized as a GPT disk on a system without GPT support.\n"
155 " Disk will appear as RAW.\n",
156 Fdo->DeviceObject);
157
158 ExFreePool (layoutEx);
159 status = IoReadPartitionTable(Fdo->DeviceObject,
160 Fdo->DiskGeometry.BytesPerSector,
161 FALSE,
162 &layout);
163 if (NT_SUCCESS (status)) {
164 layoutEx = DiskConvertLayoutToExtended(layout);
165 ExFreePool (layout);
166 }
167 }
168 }
169
170 diskData->CachedPartitionTable = layoutEx;
171
172 //
173 // If the routine fails make sure we don't have a stale partition table
174 // pointer. Otherwise indicate that the table is now valid.
175 //
176
177 if(!NT_SUCCESS(status)) {
178 diskData->CachedPartitionTable = NULL;
179 } else {
180 diskData->CachedPartitionTableValid = TRUE;
181 }
182
183 *DriveLayout = diskData->CachedPartitionTable;
184
185 DebugPrint((PtCache, "DiskRPTEx: returning PT %#p for FDO %#p with status "
186 "%#08lx. PT is %scached\n",
187 *DriveLayout,
188 Fdo,
189 status,
190 (diskData->CachedPartitionTableValid ? "" : "not ")));
191
192
193 return status;
194 }
195
196 \f
197 NTSTATUS
198 DiskWritePartitionTableEx(
199 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
200 IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
201 )
202 /*++
203
204 Routine Description:
205
206 This routine will invalidate the cached partition table. It will then
207 write the new drive layout to disk.
208
209 Arguments:
210
211 Fdo - the FDO for the disk getting the new partition table.
212
213 DriveLayout - the new drive layout.
214
215 Return Value:
216
217 status
218
219 --*/
220 {
221 PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
222
223 //
224 // Invalidate the cached partition table. Do not free it as it may be
225 // the very drive layout that was passed in to us.
226 //
227
228 diskData->CachedPartitionTableValid = FALSE;
229
230 DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
231 Fdo));
232
233 if (DiskDisableGpt) {
234 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) {
235 return STATUS_NOT_SUPPORTED;
236 }
237 }
238
239 return IoWritePartitionTableEx(Fdo->DeviceObject, DriveLayout);
240 }
241
242 NTSTATUS
243 DiskSetPartitionInformationEx(
244 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
245 IN ULONG PartitionNumber,
246 IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
247 )
248 {
249 PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
250
251 diskData->CachedPartitionTableValid = FALSE;
252 DebugPrint((PtCache, "DiskSPIEx: Invalidating PT cache for FDO %#p\n",
253 Fdo));
254
255 if (DiskDisableGpt) {
256 if (PartitionInfo->PartitionStyle == PARTITION_STYLE_GPT) {
257 return STATUS_NOT_SUPPORTED;
258 }
259 }
260
261 return IoSetPartitionInformationEx(Fdo->DeviceObject,
262 PartitionNumber,
263 PartitionInfo);
264 }
265
266 NTSTATUS
267 DiskSetPartitionInformation(
268 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
269 IN ULONG SectorSize,
270 IN ULONG PartitionNumber,
271 IN ULONG PartitionType
272 )
273 {
274 PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
275
276 diskData->CachedPartitionTableValid = FALSE;
277 DebugPrint((PtCache, "DiskSPI: Invalidating PT cache for FDO %#p\n",
278 Fdo));
279
280 return IoSetPartitionInformation(Fdo->DeviceObject,
281 SectorSize,
282 PartitionNumber,
283 PartitionType);
284 }
285
286 BOOLEAN
287 DiskInvalidatePartitionTable(
288 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
289 IN BOOLEAN PartitionLockHeld
290 )
291 {
292 PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
293 BOOLEAN wasValid;
294
295 wasValid = (BOOLEAN) (diskData->CachedPartitionTableValid ? TRUE : FALSE);
296 diskData->CachedPartitionTableValid = FALSE;
297
298 DebugPrint((PtCache, "DiskIPT: Invalidating PT cache for FDO %#p\n",
299 Fdo));
300
301 if((PartitionLockHeld) && (diskData->CachedPartitionTable != NULL)) {
302 DebugPrint((PtCache, "DiskIPT: Freeing PT cache (%#p) for FDO %#p\n",
303 diskData->CachedPartitionTable, Fdo));
304 ExFreePool(diskData->CachedPartitionTable);
305 diskData->CachedPartitionTable = NULL;
306 }
307
308 return wasValid;
309 }
310
311 NTSTATUS
312 DiskVerifyPartitionTable(
313 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
314 IN BOOLEAN FixErrors
315 )
316 {
317 PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
318
319 if(FixErrors) {
320 diskData->CachedPartitionTableValid = FALSE;
321 DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
322 Fdo));
323 }
324
325 return IoVerifyPartitionTable(Fdo->DeviceObject, FixErrors);
326 }
327