ReactOS  0.4.12-dev-685-gf36cbf7
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 
87  sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
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 //
103 NTSTATUS
105  IN PDEVICE_EXTENSION DeviceExtension,
106  IN PVFD_IMAGE_INFO ImageInfo)
107 {
110  const DISK_GEOMETRY *geometry;
111  ULONG sectors;
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(
221  &file_handle,
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(
247  file_handle,
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 
280  file_handle,
281  GENERIC_READ,
282  NULL,
283  KernelMode,
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(
328  file_handle,
329  &io_status,
330  &file_basic,
331  sizeof(FILE_BASIC_INFORMATION),
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(
358  file_handle,
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(
383  NonPagedPool,
385  VFD_POOL_TAG);
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 
425 exit_func:
426  VFDTRACE(0, ("[VFD] VfdOpenImage - %s\n", GetStatusName(status)));
427 
428  return status;
429 }
430 
431 //
432 // Close the current image
433 //
434 VOID
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 //
465 NTSTATUS
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);
512  return STATUS_BUFFER_OVERFLOW;
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 }
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VFD_DISKTYPE DiskType
Definition: vfdio.h:64
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define VFD_SECTOR_TO_BYTE(s)
Definition: vfdio.h:45
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK io_status
Definition: comm.c:54
struct _VFD_IMAGE_INFO VFD_IMAGE_INFO
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
ULONG TracksPerCylinder
Definition: ntdddisk.h:374
VFD_MEDIA MediaType
Definition: vfdio.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode
Definition: lsa.idl:66
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
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:496
ULONG_PTR * PSIZE_T
Definition: typedefs.h:78
_In_ ULONG BufferLength
Definition: usbdlib.h:225
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
#define GENERIC_WRITE
Definition: nt_native.h:90
struct _SECURITY_CLIENT_CONTEXT * PSECURITY_CLIENT_CONTEXT
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NTKERNELAPI NTSTATUS NTAPI SeCreateClientSecurity(IN PETHREAD Thread, IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, IN BOOLEAN RemoteClient, OUT PSECURITY_CLIENT_CONTEXT ClientContext)
Definition: access.c:506
#define PCHAR
Definition: match.c:90
NTSTATUS VfdOpenCheck(PDEVICE_EXTENSION DeviceExtension, PVFD_IMAGE_INFO ImageInfo, ULONG InputLength)
Definition: vfdimg.c:25
NTSTATUS VfdQueryImage(IN PDEVICE_EXTENSION DeviceExtension, OUT PVFD_IMAGE_INFO ImageInfo, IN ULONG BufferLength, OUT PULONG ReturnLength)
Definition: vfdimg.c:466
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:372
ULONG SectorsPerTrack
Definition: ntdddisk.h:375
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
* PFILE_OBJECT
Definition: iotypes.h:1954
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
const DISK_GEOMETRY geom_tbl[VFD_MEDIA_MAX]
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
ULONG LowPart
Definition: typedefs.h:104
#define GENERIC_READ
Definition: compat.h:124
#define FILE_WORD_ALIGNMENT
Definition: nt_native.h:787
VOID VfdCloseImage(IN PDEVICE_EXTENSION DeviceExtension)
Definition: vfdimg.c:435
#define FILE_OPEN
Definition: from_kernel.h:54
#define VFD_POOL_TAG
Definition: vfddrv.h:25
#define FILE_ATTRIBUTE_ENCRYPTED
Definition: ntifs_ex.h:385
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
unsigned short USHORT
Definition: pedump.c:61
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define SECURITY_STATIC_TRACKING
Definition: setypes.h:104
NTSTATUS VfdOpenImage(IN PDEVICE_EXTENSION DeviceExtension, IN PVFD_IMAGE_INFO ImageInfo)
Definition: vfdimg.c:104
struct _SECURITY_QUALITY_OF_SERVICE SECURITY_QUALITY_OF_SERVICE
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define FILE_RANDOM_ACCESS
Definition: from_kernel.h:38
unsigned int * PULONG
Definition: retypes.h:1
#define FILE_DEVICE_NETWORK_FILE_SYSTEM
Definition: winioctl.h:125
__u8 sectors[2]
Definition: mkdosfs.c:366
#define FileStandardInformation
Definition: propsheet.cpp:61
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
USHORT NameLength
Definition: vfdio.h:69
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
return STATUS_SUCCESS
Definition: btrfs.c:2725
static SERVICE_STATUS status
Definition: service.c:31
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static FILE * file_handle
Definition: regtests2xml.c:45
LONGLONG QuadPart
Definition: typedefs.h:112
Definition: ps.c:97