[Compuware Corporation] [Compuware NuMega home page]                [NuMega Lab]
[teal]

 [DriverStudio]    [Image][Image]
   Home
 [Driver Products]        Driver Technical Tips
   DriverStudio          Using File Objects in NT Drivers
   DriverBundle
   Previews              Device driver writers know that applications access devices using
   Compatibility         Win32 file I/O calls: CreateFile, ReadFile, WriteFile,
 [Downloads]             DeviceIoControl, and CloseHandle. What is sometimes overlooked is
                          that device drivers have access to the data structure that the
 Wizards                  system uses to manage the file handle of an open device. This
   Utilities             data structure, called a File Object, plays a central role in
   NT source             File System Drivers, but can very useful in ordinary device
 examples                 drivers as well. This week's tip looks at a couple of ways device
   VxD source            drivers can take advantage of File Objects.
 examples
   WDM source            The system creates the File Object when an application calls
 examples                 CreateFile on a device object. Duping an existing handle does not
 [Resources]             create a new File Object. The definition of the File Object
 Technical papers         structure is found in ntddk.h:
   Useful links
   Technical tips        typedef struct _FILE_OBJECT {
 [Support]                   CSHORT Type;
                              CSHORT Size;
 Support                      PDEVICE_OBJECT DeviceObject;
   Knowledge base            PVPB Vpb;
   Problem                   PVOID FsContext;
 submission                   PVOID FsContext2;
   Product                   PSECTION_OBJECT_POINTERS SectionObjectPointer;
 registration                 PVOID PrivateCacheMap;
   Release notes             NTSTATUS FinalStatus;
 [Shop NuMega]               struct _FILE_OBJECT *RelatedFileObject;
 Buy it!                      BOOLEAN LockOperation;
   Price list                BOOLEAN DeletePending;
   How to buy                BOOLEAN ReadAccess;
   Sales offices             BOOLEAN WriteAccess;
                              BOOLEAN DeleteAccess;
                              BOOLEAN SharedRead;
 [Y2K Compliance]             BOOLEAN SharedWrite;
                              BOOLEAN SharedDelete;
                              ULONG Flags;
 [More information]           UNICODE_STRING FileName;
                              LARGE_INTEGER CurrentByteOffset;
                              ULONG Waiters;
                              ULONG Busy;
                              PVOID LastLock;
                              KEVENT Lock;
                              KEVENT Event;
                              PIO_COMPLETION_CONTEXT CompletionContext;
                          } FILE_OBJECT;

                          When an application opens or calls a device driver, the system
                          stores a pointer to the File Object corresponding to the caller's
                          file handle in the IRP that is passed to the driver. More
                          precisely, the pointer appears in the IO_STACK_LOCATION. Here is
                          the code you would use to obtain the File Object pointer, given
                          an IRP pointed to by variable pIrp.

                                  PIRP pIrp;
                                  PIO_STACK_LOCATION pIoStack;
                                  PFILE_OBJECT pFile;

                                  pIoStack = IoGetCurrentStackLocation(pIrp);
                                  pFile= pIoStack->FileObject;

                          Using DriverWorks, it looks like this:

                                  KIrp I;
                                  PFILE_OBJECT pFile = I.FileObject(CURRENT);

                          So why would you want to get the File Object pointer? Suppose you
                          had a device with multiple "subdevices". An example would be a
                          USB device with several pipes, or certain kinds of streaming
                          devices that maintain several channels of data. Instead of
                          creating separate device objects or symbolic links for each of
                          the device components, the application can distinguish the
                          components by supplying a file name.

                          For example, an application typically opens a device with no file
                          name:

                                  hDevice = CreateFile(L"\\\\.\\MyDevice", . . .

                          But it can specify a particular component of the device by
                          supplying a file name:

                                  hDevice = CreateFile(L"\\\\.\\MyDevice\\Stream1", . . .

                          The driver then receives IRP_MJ_CREATE, and can examine the path
                          name that the application supplied in field FileName of the File
                          Object. What the name actually means is entirely up to the
                          driver.

                          Once the driver has determined the supplied file name, it needs a
                          way to remember how the application opened the device, in order
                          to respond correctly to future calls on the same handle. To solve
                          this problem, the File Object structure provides two 32-bit
                          fields for use by the driver: FsContext and FsContext2. The
                          driver can store values or pointers in these locations, and can
                          recall them in later calls (e.g. IRP_MJ_READ or
                          IRP_MJ_DEVICE_CONTROL), by accessing the File Object in an
                          identical manner.

                          In fact, the context fields are extremely useful in other
                          situations, regardless of if a file name was used to open the
                          driver. These fields enable the driver to store information
                          specific to a particular file handle. Since the system always
                          closes open handles when a process terminates, the context fields
                          give the driver a means to correctly manage the resources that
                          allocated for a particular process. For example, if a driver maps
                          physical memory into a process's address space, it can use the
                          context field to connect the mapping to the file handle. When the
                          process terminates, the driver receives IRP_MJ_CLOSE, retrieves
                          the File Object, locates the mapping information, and destroys
                          the mapping.

                          Note that drivers in a layered stack of drivers cannot safely use
                          the context fields of the File Object, unless it is absolutely
                          certain that only a single driver is using each of the two
                          context fields.

                          Back to technical tip start page.

  DriverCentral  DriverStudio  Free downloads  Resources  Support and
                          Services  Shop NuMega
     Compuware NuMega  Tel: +1 603 578-8400  Updated: 9 August 1999 
                      Problems? Contact our webmaster.
