Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

vdm.c File Reference

#include <ntos.h>
#include <vdmntos.h>
#include <ntvdmp.h>
#include <zwapi.h>
#include <fsrtl.h>

Go to the source code of this file.

Classes

struct  _QueryDirPoolData

Typedefs

typedef _QueryDirPoolData QDIR_POOLDATA
typedef _QueryDirPoolDataPQDIR_POOLDATA

Functions

NTSTATUS NtVdmControl (IN VDMSERVICECLASS Service, IN OUT PVOID ServiceData)
NTSTATUS VdmQueryDirectoryFile (PVDMQUERYDIRINFO pVdmQueryDir)

Variables

POBJECT_TYPE IoFileObjectType


Typedef Documentation

typedef struct _QueryDirPoolData * PQDIR_POOLDATA
 

Referenced by VdmQueryDirectoryFile().

typedef struct _QueryDirPoolData QDIR_POOLDATA
 


Function Documentation

NTSTATUS NtVdmControl IN VDMSERVICECLASS  Service,
IN OUT PVOID  ServiceData
 

Definition at line 49 of file vdm/vdm.c.

References PAGED_CODE, and VdmQueryDirectoryFile().

00055 : 00056 00057 This routine is the entry point for controlling Vdms. 00058 On risc it returns STATUS_NOT_IMPLEMENTED. 00059 On 386 the entry point is in i386\vdmentry.c 00060 00061 Arguments: 00062 00063 Service -- Specifies what service is to be performed 00064 ServiceData -- Supplies a pointer to service specific data 00065 00066 Return Value: 00067 00068 00069 --*/ 00070 { 00071 PAGED_CODE(); 00072 00073 00074 if (Service == VdmQueryDir) { 00075 return VdmQueryDirectoryFile(ServiceData); 00076 } 00077 00078 return STATUS_NOT_IMPLEMENTED; 00079 00080 } #endif

NTSTATUS VdmQueryDirectoryFile PVDMQUERYDIRINFO  pVdmQueryDir  ) 
 

Definition at line 87 of file vdm/vdm.c.

References APC_LEVEL, _IRP::AssociatedIrp, DO_BUFFERED_IO, DO_DIRECT_IO, Event(), ExAllocatePoolWithQuotaTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExRaiseStatus(), FALSE, _QueryDirPoolData::FileName, FileName, _QueryDirPoolData::FileNameBuf, _IO_STACK_LOCATION::FileObject, _DEVICE_OBJECT::Flags, _IO_STACK_LOCATION::Flags, _IRP::Flags, IoAllocateIrp(), IoAllocateMdl(), IoCallDriver, IoFileObjectType, IoFreeIrp(), IoFreeMdl(), IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IoWriteAccess, IRP_MJ_DIRECTORY_CONTROL, IRP_MN_QUERY_DIRECTORY, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KeLowerIrql(), KeRaiseIrql(), _QueryDirPoolData::kevent, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, _IO_STACK_LOCATION::MinorFunction, MmProbeAndLockPages(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PQDIR_POOLDATA, ProbeAndReadUnicodeString, ProbeForRead, ProbeForWrite(), PsGetCurrentThread, _IRP::RequestorMode, SL_INDEX_SPECIFIED, _DEVICE_OBJECT::StackSize, _IRP::Tail, _IRP::ThreadListEntry, TRUE, _IRP::UserBuffer, _IRP::UserEvent, _IRP::UserIosb, UserMode, and UserRequest.

Referenced by NtVdmControl().

00098 : PVDMQUERYDIRINFO pVdmQueryDir 00099 00100 FileHandle - Supplies a handle to the directory file for which information 00101 should be returned. 00102 00103 FileInformation - Supplies a buffer to receive the requested information 00104 returned about the contents of the directory. 00105 00106 Length - Supplies the length, in bytes, of the FileInformation buffer. 00107 00108 FileName - Supplies a file name within the specified directory. 00109 00110 FileIndex - Supplies a file index within the specified directory. 00111 00112 The FileInformationClass is assumed to be FILE_BOTH_DIR_INFORMATION 00113 The Caller's mode is assumed to be UserMode 00114 Synchronous IO is used 00115 00116 --*/ 00117 00118 { 00119 KIRQL irql; 00120 NTSTATUS status; 00121 PKEVENT Event; 00122 00123 HANDLE FileHandle; 00124 IO_STATUS_BLOCK IoStatusBlock; 00125 PVOID FileInformation; 00126 ULONG Length; 00127 UNICODE_STRING FileName; 00128 PUNICODE_STRING pFileNameSrc; 00129 ULONG FileIndex; 00130 00131 PQDIR_POOLDATA QDirPoolData = NULL; 00132 FILE_FS_DEVICE_INFORMATION DeviceInfo; 00133 00134 PMDL mdl; 00135 PIRP irp; 00136 PIO_STACK_LOCATION irpSp; 00137 PCHAR SystemBuffer; 00138 PFILE_OBJECT fileObject; 00139 PDEVICE_OBJECT DeviceObject; 00140 00141 00142 PAGED_CODE(); 00143 00144 // 00145 // We assume that the caller is usermode, so verify all parameters 00146 // accordingly 00147 // 00148 00149 try { 00150 00151 // 00152 // Copy out the callers service data into local variables 00153 // 00154 ProbeForRead( pVdmQueryDir, sizeof(VDMQUERYDIRINFO), sizeof(ULONG)); 00155 00156 FileHandle = pVdmQueryDir->FileHandle; 00157 FileInformation = pVdmQueryDir->FileInformation; 00158 Length = pVdmQueryDir->Length; 00159 FileIndex = pVdmQueryDir->FileIndex; 00160 pFileNameSrc = pVdmQueryDir->FileName; 00161 00162 // 00163 // Ensure that we have a valid file name string 00164 // 00165 00166 // 00167 // check for pVdmQueryDir->Filename validity first 00168 // 00169 if (NULL == pFileNameSrc) { 00170 return(STATUS_INVALID_PARAMETER); 00171 } 00172 00173 FileName = ProbeAndReadUnicodeString(pFileNameSrc); 00174 if (!FileName.Length || 00175 FileName.Length > MAXIMUM_FILENAME_LENGTH<<1) { 00176 return(STATUS_INVALID_PARAMETER); 00177 } 00178 00179 ProbeForRead(FileName.Buffer, FileName.Length, sizeof( UCHAR )); 00180 00181 // 00182 // The FileInformation buffer must be writeable by the caller. 00183 // 00184 00185 ProbeForWrite( FileInformation, Length, sizeof( ULONG ) ); 00186 00187 // 00188 // Ensure that the caller's supplied buffer is at least large enough 00189 // to contain the fixed part of the structure required for this 00190 // query. 00191 // 00192 00193 if (Length < sizeof(FILE_BOTH_DIR_INFORMATION)) { 00194 return STATUS_INFO_LENGTH_MISMATCH; 00195 } 00196 00197 00198 00199 // 00200 // Allocate from nonpaged pool a buffer large enough to contain 00201 // the file name, and the kevent used to wait for io. 00202 // 00203 00204 QDirPoolData = (PQDIR_POOLDATA) ExAllocatePoolWithQuotaTag( 00205 NonPagedPool, 00206 sizeof(QDIR_POOLDATA) + FileName.Length, 00207 ' MDV'); 00208 00209 // 00210 // Capture the file name string into the nonpaged pool block. 00211 // 00212 00213 QDirPoolData->FileName.Length = FileName.Length; 00214 QDirPoolData->FileName.MaximumLength = FileName.Length; 00215 QDirPoolData->FileName.Buffer = QDirPoolData->FileNameBuf; 00216 RtlCopyMemory( QDirPoolData->FileNameBuf, 00217 FileName.Buffer, 00218 FileName.Length ); 00219 00220 00221 } except(EXCEPTION_EXECUTE_HANDLER) { 00222 00223 if (QDirPoolData) { 00224 ExFreePool(QDirPoolData); 00225 } 00226 00227 return GetExceptionCode(); 00228 } 00229 00230 // 00231 // There were no blatant errors so far, so reference the file object so 00232 // the target device object can be found. Note that if the handle does 00233 // not refer to a file object, or if the caller does not have the required 00234 // access to the file, then it will fail. 00235 // 00236 00237 status = ObReferenceObjectByHandle( FileHandle, 00238 FILE_LIST_DIRECTORY, 00239 IoFileObjectType, 00240 UserMode, 00241 (PVOID *) &fileObject, 00242 (POBJECT_HANDLE_INFORMATION) NULL ); 00243 if (!NT_SUCCESS( status )) { 00244 if (QDirPoolData) { 00245 ExFreePool(QDirPoolData); 00246 } 00247 return status; 00248 } 00249 00250 // 00251 // We don't handle FO_SYNCHRONOUS_IO, because it requires 00252 // io internal finctionality. Ntvdm can get away with this 00253 // because it serializes access to the dir handle. 00254 // 00255 00256 // 00257 // Initialize the kernel event that will signal I/O completion 00258 // 00259 Event = &QDirPoolData->kevent; 00260 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 00261 00262 00263 // 00264 // Set the file object to the Not-Signaled state. 00265 // 00266 00267 KeClearEvent( &fileObject->Event ); 00268 00269 // 00270 // Get the address of the target device object. 00271 // 00272 00273 DeviceObject = IoGetRelatedDeviceObject( fileObject ); 00274 00275 // 00276 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00277 // The allocation is performed with an exception handler in case the 00278 // caller does not have enough quota to allocate the packet. 00279 00280 irp = IoAllocateIrp( DeviceObject->StackSize, TRUE ); 00281 if (!irp) { 00282 00283 // 00284 // An IRP could not be allocated. Cleanup and return an appropriate 00285 // error status code. 00286 // 00287 00288 ObDereferenceObject( fileObject ); 00289 if (QDirPoolData) { 00290 ExFreePool(QDirPoolData); 00291 } 00292 00293 return STATUS_INSUFFICIENT_RESOURCES; 00294 } 00295 00296 // 00297 // Fill in the service independent parameters in the IRP. 00298 // 00299 00300 irp->Flags = (ULONG)IRP_SYNCHRONOUS_API; 00301 irp->RequestorMode = UserMode; 00302 00303 irp->UserIosb = &IoStatusBlock; 00304 irp->UserEvent = Event; 00305 00306 irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 00307 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 00308 SystemBuffer = NULL; 00309 00310 00311 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00312 irp->Tail.Overlay.OriginalFileObject = fileObject; 00313 irp->Tail.Overlay.AuxiliaryBuffer = NULL; 00314 irp->MdlAddress = NULL; 00315 00316 // 00317 // Get a pointer to the stack location for the first driver. This will be 00318 // used to pass the function codes and parameters. 00319 // 00320 00321 irpSp = IoGetNextIrpStackLocation( irp ); 00322 irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; 00323 irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY; 00324 irpSp->FileObject = fileObject; 00325 00326 00327 // 00328 // Copy the caller's parameters to the service-specific portion of the 00329 // IRP. 00330 // 00331 00332 irpSp->Parameters.QueryDirectory.Length = Length; 00333 irpSp->Parameters.QueryDirectory.FileInformationClass = FileBothDirectoryInformation; 00334 irpSp->Parameters.QueryDirectory.FileIndex = FileIndex; 00335 00336 if (QDirPoolData->FileName.Length) { 00337 irpSp->Parameters.QueryDirectory.FileName = (PSTRING)&QDirPoolData->FileName; 00338 } else { 00339 irpSp->Parameters.QueryDirectory.FileName = NULL; 00340 } 00341 00342 irpSp->Flags = SL_INDEX_SPECIFIED; 00343 00344 00345 // 00346 // Now determine whether this driver expects to have data buffered to it 00347 // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO 00348 // flag in the device object. If the flag is set, then a system buffer is 00349 // allocated and the driver's data will be copied into it. Otherwise, a 00350 // Memory Descriptor List (MDL) is allocated and the caller's buffer is 00351 // locked down using it. 00352 // 00353 00354 if (DeviceObject->Flags & DO_BUFFERED_IO) { 00355 00356 // 00357 // The file system wants buffered I/O. Pass the address of the 00358 // "system buffer" in the IRP. Note that we don't want the buffer 00359 // deallocated, nor do we want the I/O system to copy to a user 00360 // buffer, so we don't set the corresponding flags in irp->Flags. 00361 // 00362 00363 00364 try { 00365 00366 // 00367 // Allocate the intermediary system buffer from nonpaged pool and 00368 // charge quota for it. 00369 // 00370 00371 SystemBuffer = ExAllocatePoolWithQuotaTag( NonPagedPool, 00372 Length, 00373 ' MDV' ); 00374 00375 irp->AssociatedIrp.SystemBuffer = SystemBuffer; 00376 00377 00378 } except(EXCEPTION_EXECUTE_HANDLER) { 00379 00380 IoFreeIrp(irp); 00381 00382 ObDereferenceObject( fileObject ); 00383 00384 if (QDirPoolData) { 00385 ExFreePool(QDirPoolData); 00386 } 00387 00388 return GetExceptionCode(); 00389 } 00390 00391 00392 } else if (DeviceObject->Flags & DO_DIRECT_IO) { 00393 00394 // 00395 // This is a direct I/O operation. Allocate an MDL and invoke the 00396 // memory management routine to lock the buffer into memory. This is 00397 // done using an exception handler that will perform cleanup if the 00398 // operation fails. 00399 // 00400 00401 mdl = (PMDL) NULL; 00402 00403 try { 00404 00405 // 00406 // Allocate an MDL, charging quota for it, and hang it off of the 00407 // IRP. Probe and lock the pages associated with the caller's 00408 // buffer for write access and fill in the MDL with the PFNs of 00409 // those pages. 00410 // 00411 00412 mdl = IoAllocateMdl( FileInformation, Length, FALSE, TRUE, irp ); 00413 if (mdl == NULL) { 00414 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00415 } 00416 MmProbeAndLockPages( mdl, UserMode, IoWriteAccess ); 00417 00418 } except(EXCEPTION_EXECUTE_HANDLER) { 00419 00420 if (irp->MdlAddress != NULL) { 00421 IoFreeMdl( irp->MdlAddress ); 00422 } 00423 00424 IoFreeIrp(irp); 00425 00426 ObDereferenceObject( fileObject ); 00427 00428 if (QDirPoolData) { 00429 ExFreePool(QDirPoolData); 00430 } 00431 00432 return GetExceptionCode(); 00433 } 00434 00435 } else { 00436 00437 // 00438 // Pass the address of the user's buffer so the driver has access to 00439 // it. It is now the driver's responsibility to do everything. 00440 // 00441 00442 irp->UserBuffer = FileInformation; 00443 00444 } 00445 00446 00447 // 00448 // Insert the packet at the head of the IRP list for the thread. 00449 // 00450 00451 KeRaiseIrql( APC_LEVEL, &irql ); 00452 InsertHeadList( &irp->Tail.Overlay.Thread->IrpList, 00453 &irp->ThreadListEntry ); 00454 KeLowerIrql( irql ); 00455 00456 00457 // 00458 // invoke the driver and wait for it to complete 00459 // 00460 00461 status = IoCallDriver(DeviceObject, irp); 00462 00463 if (status == STATUS_PENDING) { 00464 status = KeWaitForSingleObject( 00465 Event, 00466 UserRequest, 00467 UserMode, 00468 FALSE, 00469 NULL ); 00470 } 00471 00472 if (NT_SUCCESS(status)) { 00473 status = IoStatusBlock.Status; 00474 if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { 00475 if (SystemBuffer) { 00476 try { 00477 RtlCopyMemory( FileInformation, 00478 SystemBuffer, 00479 IoStatusBlock.Information 00480 ); 00481 00482 } except(EXCEPTION_EXECUTE_HANDLER) { 00483 status = GetExceptionCode(); 00484 } 00485 } 00486 } 00487 } 00488 00489 00490 // 00491 // Cleanup any memory allocated 00492 // 00493 if (QDirPoolData) { 00494 ExFreePool(QDirPoolData); 00495 } 00496 00497 if (SystemBuffer) { 00498 ExFreePool(SystemBuffer); 00499 } 00500 00501 00502 return status; 00503 }


Variable Documentation

POBJECT_TYPE IoFileObjectType
 

Definition at line 84 of file vdm/vdm.c.


Generated on Sat May 15 19:46:07 2004 for test by doxygen 1.3.7