ReactOS 0.4.15-dev-5664-g3bf4ef6
vfdimg.c
Go to the documentation of this file.
1/*
2 vfdimg.c
3
4 Virtual Floppy Drive for Windows NT platform
5 Kernel mode driver: Image handling functions
6
7 Copyright (C) 2003-2005 Ken Kato
8*/
9
10#include "imports.h"
11#include "vfddrv.h"
12#include "vfddbg.h"
13
14#ifdef ALLOC_PRAGMA
15#pragma alloc_text(PAGE, VfdOpenCheck)
16#pragma alloc_text(PAGE, VfdOpenImage)
17#pragma alloc_text(PAGE, VfdCloseImage)
18#pragma alloc_text(PAGE, VfdQueryImage)
19#endif // ALLOC_PRAGMA
20
21//
22// Check IOCTL_VFD_OPEN_IMAGE input parameters
23//
26 PDEVICE_EXTENSION DeviceExtension,
27 PVFD_IMAGE_INFO ImageInfo,
28 ULONG InputLength)
29{
30 // Check media status
31
32 if (DeviceExtension->FileHandle ||
33 DeviceExtension->FileBuffer) {
34
35 VFDTRACE(VFDWARN, ("[VFD] image already opened.\n"));
36
37 return STATUS_DEVICE_BUSY;
38 }
39
40 // Check input parameter length
41
42 if (InputLength < sizeof(VFD_IMAGE_INFO) ||
43 InputLength < sizeof(VFD_IMAGE_INFO) + ImageInfo->NameLength)
44 {
46 }
47
48 // Check input parameters
49
50 if (ImageInfo->MediaType == VFD_MEDIA_NONE ||
51 ImageInfo->MediaType >= VFD_MEDIA_MAX) {
52
53 VFDTRACE(VFDWARN, ("[VFD] invalid MediaType - %u.\n",
54 ImageInfo->MediaType));
55
57 }
58
59 if (ImageInfo->DiskType == VFD_DISKTYPE_FILE &&
60 ImageInfo->NameLength == 0) {
61
62 VFDTRACE(VFDWARN,
63 ("[VFD] File name required for VFD_DISKTYPE_FILE.\n"));
64
66 }
67
68 // create a security context to match the calling process' context
69 // the driver thread uses this context to impersonate the client
70 // to open the specified image file
71
72// if (ImageInfo->DiskType == VFD_DISKTYPE_FILE)
73 {
75
76 if (DeviceExtension->SecurityContext != NULL) {
77 SeDeleteClientSecurity(DeviceExtension->SecurityContext);
78 }
79 else {
80 DeviceExtension->SecurityContext =
83 }
84
86
90 sqos.EffectiveOnly = FALSE;
91
93 PsGetCurrentThread(), &sqos, FALSE,
94 DeviceExtension->SecurityContext);
95 }
96
97 return STATUS_SUCCESS;
98}
99
100//
101// Open a virtual floppy image file or create an empty ram disk
102//
105 IN PDEVICE_EXTENSION DeviceExtension,
106 IN PVFD_IMAGE_INFO ImageInfo)
107{
110 const DISK_GEOMETRY *geometry;
112 ULONG alignment;
113
114 VFDTRACE(0, ("[VFD] VfdOpenImage - IN\n"));
115
116 //
117 // Store file name in the device extension
118 //
119 if (ImageInfo->NameLength) {
120
121 if (ImageInfo->NameLength + 1 >
122 DeviceExtension->FileName.MaximumLength) {
123
124 // expand the filename buffer
125
126 if (DeviceExtension->FileName.Buffer) {
127 ExFreePool(DeviceExtension->FileName.Buffer);
129 &DeviceExtension->FileName,
130 sizeof(ANSI_STRING));
131 }
132
133 DeviceExtension->FileName.Buffer = (PCHAR)ExAllocatePoolWithTag(
134 NonPagedPool, ImageInfo->NameLength + 1, VFD_POOL_TAG);
135
136 if (!DeviceExtension->FileName.Buffer) {
137 VFDTRACE(0, ("[VFD] Can't allocate memory for image path\n"));
139 }
140
141 DeviceExtension->FileName.MaximumLength
142 = (USHORT)(ImageInfo->NameLength + 1);
143
145 DeviceExtension->FileName.Buffer,
146 DeviceExtension->FileName.MaximumLength);
147 }
148
149 if (DeviceExtension->FileName.Buffer) {
151 DeviceExtension->FileName.Buffer,
152 ImageInfo->FileName,
153 ImageInfo->NameLength);
154
155 DeviceExtension->FileName.Buffer[ImageInfo->NameLength] = '\0';
156 }
157 }
158
159 DeviceExtension->FileName.Length = ImageInfo->NameLength;
160
161 //
162 // Get DISK_GEOMETRY and calculate the media capacity
163 // -- validity of the ImageInfo->MediaType value is assured in
164 // the VfdOpenCheck function
165 //
166 geometry = &geom_tbl[ImageInfo->MediaType];
167
168 sectors =
169 geometry->Cylinders.LowPart *
170 geometry->TracksPerCylinder *
171 geometry->SectorsPerTrack;
172
173 if (ImageInfo->ImageSize != 0 &&
174 ImageInfo->ImageSize < VFD_SECTOR_TO_BYTE(sectors)) {
175
176 VFDTRACE(0, ("[VFD] Image is smaller than the media\n"));
178 }
179
180 //
181 // Prepare a virtual media according to the ImageInfo
182 //
183 if (ImageInfo->DiskType == VFD_DISKTYPE_FILE) {
184 //
185 // open an existing image file
186 //
188 OBJECT_ATTRIBUTES attributes;
189 UNICODE_STRING unicode_name;
190 FILE_STANDARD_INFORMATION file_standard;
191 FILE_BASIC_INFORMATION file_basic;
192 FILE_ALIGNMENT_INFORMATION file_alignment;
193 PFILE_OBJECT file_object;
194 BOOLEAN network_drive;
195
196 // convert the filename into a unicode string
197
199 &unicode_name, &DeviceExtension->FileName, TRUE);
200
201 if (!NT_SUCCESS(status)) {
202 VFDTRACE(0, ("[VFD] Failed to convert filename to UNICODE\n"));
203 return status;
204 }
205
206 VFDTRACE(VFDINFO,
207 ("[VFD] Opening %s\n", DeviceExtension->FileName.Buffer));
208
209 // prepare an object attribute to open
210
212 &attributes,
213 &unicode_name,
215 NULL,
216 NULL);
217
218 // open the target file
219
220 status = ZwCreateFile(
223 &attributes,
224 &io_status,
225 NULL,
227 0,
228 FILE_OPEN,
233 NULL,
234 0);
235
236 RtlFreeUnicodeString(&unicode_name);
237
238 if (!NT_SUCCESS(status)) {
239 VFDTRACE(0, ("[VFD] ZwCreateFile - %s\n",
240 GetStatusName(status)));
241 return status;
242 }
243
244 // Check the file size
245
246 status = ZwQueryInformationFile(
248 &io_status,
249 &file_standard,
252
253 if (!NT_SUCCESS(status)) {
254 VFDTRACE(0,
255 ("[VFD] ZwQueryInformationFile - FILE_STANDARD_INFORMATION\n"));
256
258 goto exit_func;
259 }
260
261 // Actual file size can be larger than the media capacity
262
263 if (file_standard.EndOfFile.QuadPart < VFD_SECTOR_TO_BYTE(sectors)) {
264
265 VFDTRACE(0, ("[VFD] file is smaller than the media.\n"));
266
268
270 goto exit_func;
271 }
272
273 DeviceExtension->ImageSize = file_standard.EndOfFile.LowPart;
274
275 // Find out whether the file is on a local disk or a network drive
276
277 network_drive = FALSE;
278
282 NULL,
284#ifndef __REACTOS__
285 &file_object,
286#else
287 (PVOID *)&file_object,
288#endif
289 NULL);
290
291 if (NT_SUCCESS(status)) {
292 if (file_object && file_object->DeviceObject) {
293 VFDTRACE(VFDINFO, ("[VFD] Device type is 0x%08x\n",
294 file_object->DeviceObject->DeviceType));
295
296 if (file_object->DeviceObject->DeviceType
298 network_drive = TRUE;
299 }
300
301 // how about these types ?
302 // FILE_DEVICE_NETWORK
303 // FILE_DEVICE_NETWORK_BROWSER
304 // FILE_DEVICE_NETWORK_REDIRECTOR
305 }
306 else {
307 VFDTRACE(VFDWARN, ("[VFD Cannot decide the device type\n"));
308 }
309 ObDereferenceObject(file_object);
310 }
311 else {
312 VFDTRACE(0, ("[VFD] ObReferenceObjectByHandle - %s\n",
313 GetStatusName(status)));
314 }
315
316 if (!network_drive) {
317 // The NT cache manager can deadlock if a filesystem that is using
318 // the cache manager is used in a virtual disk that stores its file
319 // on a file systemthat is also using the cache manager, this is
320 // why we open the file with FILE_NO_INTERMEDIATE_BUFFERING above,
321 // however if the file is compressed or encrypted NT will not honor
322 // this request and cache it anyway since it need to store the
323 // decompressed/unencrypted data somewhere, therefor we put an
324 // extra check here and don't alow disk images to be compressed/
325 // encrypted.
326
327 status = ZwQueryInformationFile(
329 &io_status,
330 &file_basic,
333
334 if (!NT_SUCCESS(status)) {
335 VFDTRACE(0,
336 ("[VFD] ZwQueryInformationFile - FILE_BASIC_INFORMATION\n"));
337
339 goto exit_func;
340 }
341
342 if (file_basic.FileAttributes
344 {
345 VFDTRACE(0,
346 ("[VFD] Image file is compressed and/or encrypted\n"));
347
349
351 goto exit_func;
352 }
353 }
354
355 // Retrieve the file alignment requirement
356
357 status = ZwQueryInformationFile(
359 &io_status,
360 &file_alignment,
363
364 if (!NT_SUCCESS(status)) {
365 VFDTRACE(0,
366 ("[VFD] ZwQueryInformationFile - FILE_ALIGNMENT_INFORMATION\n"));
367
369 goto exit_func;
370 }
371
372 DeviceExtension->FileHandle = file_handle;
373
374 alignment = file_alignment.AlignmentRequirement;
375
376 VFDTRACE(0, ("[VFD] Opened an image file\n"));
377 }
378 else {
379 //
380 // Create an empty RAM disk
381 //
382 DeviceExtension->FileBuffer = (PUCHAR)ExAllocatePoolWithTag(
386
387 if (!DeviceExtension->FileBuffer) {
388 VFDTRACE(0, ("[VFD] Can't allocate memory for RAM disk\n"));
390 }
391
393 DeviceExtension->FileBuffer,
395
396 if (ImageInfo->ImageSize) {
397 DeviceExtension->ImageSize = ImageInfo->ImageSize;
398 }
399 else {
400 DeviceExtension->ImageSize = VFD_SECTOR_TO_BYTE(sectors);
401 }
402
403 alignment = FILE_WORD_ALIGNMENT;
404
405 VFDTRACE(0, ("[VFD] Created an empty RAM disk\n"));
406 }
407
408 DeviceExtension->MediaChangeCount++;
409
410 DeviceExtension->MediaType = ImageInfo->MediaType;
411 DeviceExtension->MediaFlags = ImageInfo->MediaFlags;
412 DeviceExtension->FileType = ImageInfo->FileType;
413 DeviceExtension->Geometry = geometry;
414 DeviceExtension->Sectors = sectors;
415
416 VFDTRACE(0, ("[VFD] Media:%d Flag:0x%02x Size:%lu Capacity:%lu\n",
417 DeviceExtension->MediaType,
418 DeviceExtension->MediaFlags,
419 DeviceExtension->ImageSize,
420 DeviceExtension->Sectors));
421
422 DeviceExtension->DeviceObject->AlignmentRequirement
423 = alignment;
424
425exit_func:
426 VFDTRACE(0, ("[VFD] VfdOpenImage - %s\n", GetStatusName(status)));
427
428 return status;
429}
430
431//
432// Close the current image
433//
434VOID
436 IN PDEVICE_EXTENSION DeviceExtension)
437{
438 VFDTRACE(0, ("[VFD] VfdCloseImage - IN\n"));
439
440 ASSERT(DeviceExtension);
441
442 DeviceExtension->MediaType = VFD_MEDIA_NONE;
443 DeviceExtension->MediaFlags = 0;
444 DeviceExtension->FileType = 0;
445 DeviceExtension->ImageSize = 0;
446 DeviceExtension->FileName.Length = 0;
447 DeviceExtension->Sectors = 0;
448
449 if (DeviceExtension->FileHandle) {
450 ZwClose(DeviceExtension->FileHandle);
451 DeviceExtension->FileHandle = NULL;
452 }
453
454 if (DeviceExtension->FileBuffer) {
455 ExFreePool(DeviceExtension->FileBuffer);
456 DeviceExtension->FileBuffer = NULL;
457 }
458
459 VFDTRACE(0, ("[VFD] VfdCloseImage - OUT\n"));
460}
461
462//
463// Return information about the current image
464//
467 IN PDEVICE_EXTENSION DeviceExtension,
468 OUT PVFD_IMAGE_INFO ImageInfo,
470#ifndef __REACTOS__
472#else
474#endif
475{
476 // Check output buffer length
477
478 if (BufferLength < sizeof(VFD_IMAGE_INFO)) {
480 }
481
482 RtlZeroMemory(ImageInfo, BufferLength);
483
484 // Store fixed length image information
485
486 ImageInfo->MediaType = DeviceExtension->MediaType;
487
488 if (DeviceExtension->MediaType == VFD_MEDIA_NONE) {
489 *ReturnLength = sizeof(VFD_IMAGE_INFO);
490 return STATUS_SUCCESS;
491 }
492
493 if (DeviceExtension->FileBuffer) {
494 ImageInfo->DiskType = VFD_DISKTYPE_RAM;
495 }
496 else {
497 ImageInfo->DiskType = VFD_DISKTYPE_FILE;
498 }
499
500 ImageInfo->MediaFlags = DeviceExtension->MediaFlags;
501 ImageInfo->FileType = DeviceExtension->FileType;
502 ImageInfo->ImageSize = DeviceExtension->ImageSize;
503
504 ImageInfo->NameLength = DeviceExtension->FileName.Length;
505
506 // output buffer is large enough to hold the file name?
507
508 if (BufferLength < sizeof(VFD_IMAGE_INFO) +
509 DeviceExtension->FileName.Length)
510 {
511 *ReturnLength = sizeof(VFD_IMAGE_INFO);
513 }
514
515 // copy file name
516
517 if (DeviceExtension->FileName.Length &&
518 DeviceExtension->FileName.Buffer) {
519
520 RtlCopyMemory(ImageInfo->FileName,
521 DeviceExtension->FileName.Buffer,
522 DeviceExtension->FileName.Length);
523 }
524
525 // store the actually returned data length
526
527 *ReturnLength = sizeof(VFD_IMAGE_INFO) +
528 DeviceExtension->FileName.Length;
529
530 return STATUS_SUCCESS;
531}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GENERIC_READ
Definition: compat.h:135
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
@ FileAlignmentInformation
Definition: from_kernel.h:78
@ FileBasicInformation
Definition: from_kernel.h:65
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define FILE_RANDOM_ACCESS
Definition: from_kernel.h:38
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
unsigned int * PULONG
Definition: retypes.h:1
unsigned char * PUCHAR
Definition: retypes.h:3
unsigned int ULONG
Definition: retypes.h:1
@ SecurityImpersonation
Definition: lsa.idl:57
struct _SECURITY_QUALITY_OF_SERVICE SECURITY_QUALITY_OF_SERVICE
__u8 sectors[2]
Definition: mkdosfs.c:8
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
struct _SECURITY_CLIENT_CONTEXT * PSECURITY_CLIENT_CONTEXT
NTKERNELAPI NTSTATUS NTAPI SeCreateClientSecurity(IN PETHREAD Thread, IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, IN BOOLEAN RemoteClient, OUT PSECURITY_CLIENT_CONTEXT ClientContext)
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK io_status
Definition: comm.c:56
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
#define FILE_WORD_ALIGNMENT
Definition: nt_native.h:787
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FILE_ATTRIBUTE_ENCRYPTED
Definition: ntifs_ex.h:385
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
unsigned short USHORT
Definition: pedump.c:61
#define FileStandardInformation
Definition: propsheet.cpp:61
#define FILE_DEVICE_NETWORK_FILE_SYSTEM
Definition: winioctl.h:126
static FILE * file_handle
Definition: regtests2xml.c:45
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:405
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode
Definition: lsa.idl:66
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
VFD_DISKTYPE DiskType
Definition: vfdio.h:64
USHORT NameLength
Definition: vfdio.h:69
VFD_MEDIA MediaType
Definition: vfdio.h:65
Definition: ps.c:97
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
const DISK_GEOMETRY geom_tbl[VFD_MEDIA_MAX]
#define VFD_POOL_TAG
Definition: vfddrv.h:25
NTSTATUS VfdQueryImage(IN PDEVICE_EXTENSION DeviceExtension, OUT PVFD_IMAGE_INFO ImageInfo, IN ULONG BufferLength, OUT PULONG ReturnLength)
Definition: vfdimg.c:466
VOID VfdCloseImage(IN PDEVICE_EXTENSION DeviceExtension)
Definition: vfdimg.c:435
NTSTATUS VfdOpenImage(IN PDEVICE_EXTENSION DeviceExtension, IN PVFD_IMAGE_INFO ImageInfo)
Definition: vfdimg.c:104
NTSTATUS VfdOpenCheck(PDEVICE_EXTENSION DeviceExtension, PVFD_IMAGE_INFO ImageInfo, ULONG InputLength)
Definition: vfdimg.c:25
struct _VFD_IMAGE_INFO VFD_IMAGE_INFO
#define VFD_SECTOR_TO_BYTE(s)
Definition: vfdio.h:45
@ VFD_MEDIA_NONE
Definition: vfdtypes.h:27
@ VFD_MEDIA_MAX
Definition: vfdtypes.h:43
@ VFD_DISKTYPE_FILE
Definition: vfdtypes.h:18
@ VFD_DISKTYPE_RAM
Definition: vfdtypes.h:19
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
#define SECURITY_STATIC_TRACKING
Definition: setypes.h:104