- Implement beginnings of Ramdisk Port Driver. Planning compatibility with ISO, SDI...
[reactos.git] / reactos / drivers / storage / class / ramdisk / ramdisk.c
1 /*
2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: 2-clause BSD - See COPYING.ARM
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntddk.h>
12 #include <ntdddisk.h>
13 #include <scsi.h>
14 #include <ntddscsi.h>
15 #include <mountdev.h>
16 #include <mountmgr.h>
17 #include <helper.h>
18 #include <ketypes.h>
19 #include <arc/arc.h>
20 #define NDEBUG
21 #include <debug.h>
22
23 /* GLOBALS ********************************************************************/
24
25 ULONG MaximumViewLength;
26 ULONG MaximumPerDiskViewLength;
27 ULONG ReportDetectedDevice;
28 ULONG MarkRamdisksAsRemovable;
29 ULONG MinimumViewCount;
30 ULONG DefaultViewCount;
31 ULONG MaximumViewCount;
32 ULONG MinimumViewLength;
33 ULONG DefaultViewLength;
34 UNICODE_STRING DriverRegistryPath;
35 BOOLEAN ExportBootDiskAsCd;
36 BOOLEAN IsWinPEBoot;
37
38 /* FUNCTIONS ******************************************************************/
39
40 VOID
41 NTAPI
42 QueryParameters(IN PUNICODE_STRING RegistryPath)
43 {
44 ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
45 RTL_QUERY_REGISTRY_TABLE QueryTable[10];
46
47 //
48 // Set defaults
49 //
50 MaximumViewLength = 0x10000000u;
51 MaximumPerDiskViewLength = 0x10000000u;
52 ReportDetectedDevice = 0;
53 MarkRamdisksAsRemovable = 0;
54 MinimumViewCount = 2;
55 DefaultViewCount = 16;
56 MaximumViewCount = 64;
57 MinimumViewLength = 0x10000u;
58 DefaultViewLength = 0x100000u;
59
60 //
61 // Setup the query table and query the registry
62 //
63 RtlZeroMemory(QueryTable, sizeof(QueryTable));
64 QueryTable[0].Flags = 1;
65 QueryTable[0].Name = L"Parameters";
66 QueryTable[1].Flags = 32;
67 QueryTable[1].Name = L"ReportDetectedDevice";
68 QueryTable[1].EntryContext = &ReportDetectedDevice;
69 QueryTable[2].Flags = 32;
70 QueryTable[2].Name = L"MarkRamdisksAsRemovable";
71 QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
72 QueryTable[3].Flags = 32;
73 QueryTable[3].Name = L"MinimumViewCount";
74 QueryTable[3].EntryContext = &MinimumViewCount;
75 QueryTable[4].Flags = 32;
76 QueryTable[4].Name = L"DefaultViewCount";
77 QueryTable[4].EntryContext = &DefaultViewCount;
78 QueryTable[5].Flags = 32;
79 QueryTable[5].Name = L"MaximumViewCount";
80 QueryTable[5].EntryContext = &MaximumViewCount;
81 QueryTable[6].Flags = 32;
82 QueryTable[6].Name = L"MinimumViewLength";
83 QueryTable[6].EntryContext = &MinimumViewLength;
84 QueryTable[7].Flags = 32;
85 QueryTable[7].Name = L"DefaultViewLength";
86 QueryTable[7].EntryContext = &DefaultViewLength;
87 QueryTable[8].Flags = 32;
88 QueryTable[8].Name = L"MaximumViewLength";
89 QueryTable[8].EntryContext = &MaximumViewLength;
90 QueryTable[9].Flags = 32;
91 QueryTable[9].Name = L"MaximumPerDiskViewLength";
92 QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
93 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
94 RegistryPath->Buffer,
95 QueryTable,
96 NULL,
97 NULL);
98
99 //
100 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
101 //
102 MinView = MinimumViewCount;
103 if (MinimumViewCount >= 2)
104 {
105 if (MinimumViewCount > 256) MinView = 256;
106 }
107 else
108 {
109 MinView = 2;
110 }
111 MinimumViewCount = MinView;
112
113 //
114 // Parse default view count, cannot be bigger than 256 or smaller than minimum
115 //
116 DefView = DefaultViewCount;
117 if (DefaultViewCount >= MinView)
118 {
119 if (DefaultViewCount > 256) DefView = 256;
120 }
121 else
122 {
123 DefView = MinView;
124 }
125 DefaultViewCount = DefView;
126
127 //
128 // Parse maximum view count, cannot be bigger than 256 or smaller than default
129 //
130 if (MaximumViewCount >= DefView)
131 {
132 if (MaximumViewCount > 256) MaximumViewCount = 256;
133 }
134 else
135 {
136 MaximumViewCount = DefView;
137 }
138
139 //
140 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
141 //
142 MinViewLength = MinimumViewLength;
143 if (MinimumViewLength >= 0x10000)
144 {
145 if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
146 }
147 else
148 {
149 MinViewLength = 0x10000u;
150 }
151 MinimumViewLength = MinViewLength;
152
153 //
154 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
155 //
156 DefViewLength = DefaultViewLength;
157 if (DefaultViewLength >= MinViewLength)
158 {
159 if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
160 }
161 else
162 {
163 DefViewLength = MinViewLength;
164 }
165 DefaultViewLength = DefViewLength;
166
167 //
168 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
169 //
170 MaxViewLength = MaximumViewLength;
171 if (MaximumViewLength >= DefViewLength)
172 {
173 if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
174 }
175 else
176 {
177 MaxViewLength = DefViewLength;
178 }
179 MaximumViewLength = MaxViewLength;
180
181 //
182 // Parse maximum view length per disk, cannot be smaller than 16MB
183 //
184 if (MaximumPerDiskViewLength >= 0x1000000)
185 {
186 if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
187 }
188 else
189 {
190 MaximumPerDiskViewLength = 0x1000000u;
191 }
192 }
193
194 NTSTATUS
195 NTAPI
196 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
197 IN PIRP Irp)
198 {
199 UNIMPLEMENTED;
200 while (TRUE);
201 return STATUS_SUCCESS;
202 }
203
204 NTSTATUS
205 NTAPI
206 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
207 IN PIRP Irp)
208 {
209 UNIMPLEMENTED;
210 while (TRUE);
211 return STATUS_SUCCESS;
212 }
213
214 NTSTATUS
215 NTAPI
216 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
217 IN PIRP Irp)
218 {
219 UNIMPLEMENTED;
220 while (TRUE);
221 return STATUS_SUCCESS;
222 }
223
224 NTSTATUS
225 NTAPI
226 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
227 IN PIRP Irp)
228 {
229 UNIMPLEMENTED;
230 while (TRUE);
231 return STATUS_SUCCESS;
232 }
233
234 NTSTATUS
235 NTAPI
236 RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
237 IN PIRP Irp)
238 {
239 UNIMPLEMENTED;
240 while (TRUE);
241 return STATUS_SUCCESS;
242 }
243
244 NTSTATUS
245 NTAPI
246 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
247 IN PIRP Irp)
248 {
249 UNIMPLEMENTED;
250 while (TRUE);
251 return STATUS_SUCCESS;
252 }
253
254 NTSTATUS
255 NTAPI
256 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
257 IN PIRP Irp)
258 {
259 UNIMPLEMENTED;
260 while (TRUE);
261 return STATUS_SUCCESS;
262 }
263
264 NTSTATUS
265 NTAPI
266 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
267 IN PIRP Irp)
268 {
269 UNIMPLEMENTED;
270 while (TRUE);
271 return STATUS_SUCCESS;
272 }
273
274 VOID
275 NTAPI
276 RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
277 {
278 UNIMPLEMENTED;
279 while (TRUE);
280 }
281
282 NTSTATUS
283 NTAPI
284 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
285 IN PDEVICE_OBJECT PhysicalDeviceObject)
286 {
287 UNIMPLEMENTED;
288 while (TRUE);
289 return STATUS_SUCCESS;
290 }
291
292 NTSTATUS
293 NTAPI
294 DriverEntry(IN PDRIVER_OBJECT DriverObject,
295 IN PUNICODE_STRING RegistryPath)
296 {
297 PCHAR BootDeviceName, CommandLine;
298 PDEVICE_OBJECT PhysicalDeviceObject;
299 NTSTATUS Status;
300 DPRINT1("RAMDISK Class Driver\n");
301
302 //
303 // Query ramdisk parameters
304 //
305 QueryParameters(RegistryPath);
306
307 //
308 // Save the registry path
309 //
310 DriverRegistryPath = *RegistryPath;
311 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
312 RegistryPath->Length +
313 sizeof(WCHAR),
314 TAG('R', 'a', 'm', 'd'));
315 if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
316 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
317
318 //
319 // Set device routines
320 //
321 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
322 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
323 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
324 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
325 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
326 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
327 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
328 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
329 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
330 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
331 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
332 DriverObject->DriverUnload = RamdiskUnload;
333
334 //
335 // Check for a loader block
336 //
337 if (KeLoaderBlock)
338 {
339 //
340 // Get the boot device name
341 //
342 BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
343 if (BootDeviceName)
344 {
345 //
346 // Check if we're booting from ramdisk
347 //
348 if ((strlen(BootDeviceName) >= 10) &&
349 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
350 {
351 //
352 // We'll have to tell the PnP Manager
353 //
354 ReportDetectedDevice = TRUE;
355
356 //
357 // Check for a command line
358 //
359 CommandLine = KeLoaderBlock->LoadOptions;
360 if (CommandLine)
361 {
362 //
363 // Check if this is an ISO boot
364 //
365 if (strstr(CommandLine, "RDEXPORTASCD"))
366 {
367 //
368 // Remember for later
369 //
370 ExportBootDiskAsCd = TRUE;
371 }
372
373 //
374 // Check if this is PE boot
375 //
376 if (strstr(CommandLine, "MININT"))
377 {
378 //
379 // Remember for later
380 //
381 IsWinPEBoot = TRUE;
382 }
383 }
384 }
385
386 }
387 }
388
389 //
390 // Installing from Ramdisk isn't supported yet
391 //
392 ASSERT(KeLoaderBlock->SetupLdrBlock);
393
394 //
395 // Are we reporting the device
396 //
397 if (ReportDetectedDevice)
398 {
399 //
400 // Do it
401 //
402 Status = IoReportDetectedDevice(DriverObject,
403 InterfaceTypeUndefined,
404 0xFFFFFFFF,
405 0xFFFFFFFF,
406 NULL,
407 NULL,
408 0,
409 &PhysicalDeviceObject);
410 if (NT_SUCCESS(Status))
411 {
412 //
413 // Create the device object
414 //
415 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
416 if (NT_SUCCESS(Status))
417 {
418 //
419 // We're done
420 //
421 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
422 Status = STATUS_SUCCESS;
423 }
424 }
425 }
426 else
427 {
428 //
429 // Done
430 //
431 Status = STATUS_SUCCESS;
432 }
433
434 //
435 // Done
436 //
437 return Status;
438 }