⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 functions.c

📁 This the fourth edition of the Writing Device Drivers articles. This article will introduce the idea
💻 C
📖 第 1 页 / 共 5 页
字号:

                 IoSetCompletionRoutine(MyIrp, Example_SampleCompletionRoutine, NULL, TRUE, TRUE, TRUE);

                 /*
                  *  After we have set up the IRP and the IO_STACK_LOCATION we then simply need to
                  *  call the device object (Which is simply our own) along with the IRP.  This
                  *  will simply invoke the appropriate function in the driver and nothing more.
                  *
                  *  It is still up to the driver to complete the IRP.  We cannot access the
                  *  IRP after this call since the completion of the IRP should be handled with
                  *  our completion routine which will then delete the IRP.
                  *
                  *  P.S. Notice we never set the FILE_OBJECT of this IO_STACK_LOCATION.  The FILE_OBJECT is essentially
                  *  the handle.  We are basically making a contextless call into the driver.
                  *
                  *  Never pass down values in the IRP on the stack.  The IRP may be processed out of context.
                  *  Technically we should have added a reference to the FILE_OBJECT since we passed it down
                  *  however for simplicity we simply passed it down and didn't care.
                  *
                  *  NOTE: We are using OUR DeviceObject here so the filter driver is by-passed!
                  */

                 NtStatus = IoCallDriver(pFileObject->DeviceObject, MyIrp);
             }
             else
             {
                 NtStatus = STATUS_INSUFFICIENT_RESOURCES;
             }
         }

         KeReleaseMutex(&pExampleDeviceContext->kListMutex, FALSE);
    }
   
    
    return NtStatus;
}



/**********************************************************************
 * 
 *  Example_ReleasePipeContext
 *
 *    This is called to close a pipe context
 *
 **********************************************************************/
NTSTATUS Example_ReleasePipeContext(PEXAMPLE_DEVICE_CONTEXT pExampleDeviceContext, PFILE_OBJECT pFileObject)
{
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
    PEXAMPLE_LIST pExampleList = NULL, pExampleListFromIrp = (PEXAMPLE_LIST)pFileObject->FsContext;
    BOOLEAN bNotFound = TRUE;
    PDEVICE_OBJECT pTopOfStackDevice = NULL;
    LARGE_INTEGER StartOffset = {0};
    IO_STATUS_BLOCK StatusBlock = {0};
    
    NtStatus = KeWaitForMutexObject(&pExampleDeviceContext->kListMutex, Executive, KernelMode, FALSE, NULL);

    if(NT_SUCCESS(NtStatus))
    {
         pExampleList = pExampleDeviceContext->pExampleList;

         if(pExampleListFromIrp)
         {
              if(pExampleList == pExampleListFromIrp)
              {
                 bNotFound = FALSE;
                 pExampleListFromIrp->uiRefCount--;
                          
                 if(pExampleListFromIrp->uiRefCount == 0)
                 {
                     PIRP MyIrp = NULL;
                     pExampleDeviceContext->pExampleList = pExampleList->pNext;
                     

                     /*
                      * In this example, we simply moved the previous code into the private IOCTL's.
                      * We will allocate an IRP and sent it to our own driver.  This task could be done
                      * with another device obviously but in this case we are doing it with our own.  As
                      * you can see we could easily have issued any major IRP function it's not limited
                      * to private IOCTLs.  Also, this is a simple implementation and there is a little 
                      * matter of "pending IRP's" that has been left out for simplicity.  It doesn't matter
                      * much however since this is our driver and we control all end points.
                      *
                      * The first parameter is the number of IO_STACK_LOCATION's that are allocated for this
                      * IRP.  We use the "StackSize" of the DeviceObject which tells the minimum number
                      * needed to send a request down this device stack.  The initial value is 1 and then
                      * any device driver which then attaches to the device stack of this driver will then
                      * add to this number.  If some higher level driver wants to allocate an IRP and do
                      * some processing on it as well as apart of this IRP stack then it should keep
                      * that in mind when allocating the IRP and ensuring the correct number of stack
                      * locations is allocated.
                      *
                      * The second parameter is to determine whether this IRP should be charged to the
                      * quota of the current process.
                      *
                      * IoBuildSynchronousFsdRequest & IoBuildAsynchronousFsdRequest actually do what
                      * we are doing here execpt they do it for you in one function call.  There is a slight
                      * difference as well though as SynchronousFsdRequest will do a little more so the I/O
                      * Manager is aware and will cal IoFreeIrp for you where BuildAsyncrhonous will not.
                      * 
                      * Other than that,  IoBuildSynchronousFsdRequest actually calls IoBuildAsynchronousFsdRequest
                      * if you look at these in a debugger.
                      *
                      * IoBuildDeviceIoControlRequest Also does this for you, infact even more since it also sets up
                      * the IO_STACK_LOCATION with the correct Major IRP function and IOCTL code.
                      *
                      * We set the other parameters to NULL since we will set them manually anyway.
                      */
                     pTopOfStackDevice = IoGetRelatedDeviceObject(pFileObject);
                     MyIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_INTERNAL_DEVICE_CONTROL, pTopOfStackDevice, NULL, 0, &StartOffset, &StatusBlock);

                     if(MyIrp)
                     {
                         PIO_STACK_LOCATION pMyIoStackLocation = IoGetNextIrpStackLocation(MyIrp);

                         pMyIoStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
                         pMyIoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_CLOSE_RESOURCE_CONTEXT;


                        /*
                         * METHOD_BUFFERED
                         *
                         *    Input Buffer = Irp->AssociatedIrp.SystemBuffer
                         *    Ouput Buffer = Irp->AssociatedIrp.SystemBuffer
                         *
                         *    Input Size   =  Parameters.DeviceIoControl.InputBufferLength
                         *    Output Size  =  Parameters.DeviceIoControl.OutputBufferLength
                         *
                         *    Since we are now doing the same job as the I/O Manager,
                         *    to follow the rules our IOCTL specified METHOD_BUFFERED
                         */  
                         pMyIoStackLocation->Parameters.DeviceIoControl.InputBufferLength  = sizeof(EXAMPLE_LIST);
                         pMyIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength = 0;

                         /*
                          * This is not really how you use IOCTL's but this is simply an example using
                          * an existing implementation.  We will simply set our File Object as the SystemBuffer.
                          * Then the IOCTL handler will know it's a pFileObject and implement the code that we
                          * had here previously.
                          */

                         MyIrp->AssociatedIrp.SystemBuffer = pExampleListFromIrp;
                         MyIrp->MdlAddress                 = NULL;

                         /*
                          * A Completion Routine notifies that the IRP has been completed.  This is when
                          * we will then clean up all memory associated with the IRP and infact actually
                          * remove the returned data or whatever else we need to do.
                          *
                          * Parameter 1 - the IRP
                          * Parameter 2 - Our Completion Routine
                          * Parameter 3 - a context that you create in Non-Paged memory (IRQL <= DISPATCH_LEVEL)
                          * Parameter 4 - Sucess - Invoke this call on success?
                          * Parameter 5 - Error  - Inovke this call on error?
                          * Parameter 6 - Cancel - Invoke this call on cancel?
                          */

                         IoSetCompletionRoutine(MyIrp, Example_SampleCompletionRoutine, NULL, TRUE, TRUE, TRUE);

                         /*
                          *  After we have set up the IRP and the IO_STACK_LOCATION we then simply need to
                          *  call the device object (Which is simply our own) along with the IRP.  This
                          *  will simply invoke the appropriate function in the driver and nothing more.
                          *
                          *  It is still up to the driver to complete the IRP.  We cannot access the
                          *  IRP after this call since the completion of the IRP should be handled with
                          *  our completion routine which will then delete the IRP.
                          *
                          *  P.S. Notice we never set the FILE_OBJECT of this IO_STACK_LOCATION.  The FILE_OBJECT is essentially
                          *  the handle.  We are basically making a contextless call into the driver.
                          *
                          *  Never pass down values in the IRP on the stack.  The IRP may be processed out of context.
                          *  Technically we should have added a reference to the FILE_OBJECT since we passed it down
                          *  however for simplicity we simply passed it down and didn't care.
                          *
                          *  NOTE: In the original code we didn't use IoGetRelatedDeviceObject() so we
                          *        simply used OUR device object and bypassed the filter.  If we call
                          *        this API we will get the top of the device stack and all devices
                          *        attached in the stack will be called.
                          */
                         
                         NtStatus = IoCallDriver(pTopOfStackDevice, MyIrp);
                     }
                     else
                     {
                         NtStatus = STATUS_INSUFFICIENT_RESOURCES;
                     }
                 }

              }
              else
              {

                  do
                  {
                      if(pExampleListFromIrp == pExampleList->pNext)
                      {
                          bNotFound = FALSE;
                          pExampleListFromIrp->uiRefCount--;
                          
                          if(pExampleListFromIrp->uiRefCount == 0)
                          {
                             PIRP MyIrp = NULL;
                             pExampleList->pNext = pExampleListFromIrp->pNext;
                             

                             /*
                              * In this example, we simply moved the previous code into the private IOCTL's.
                              * We will allocate an IRP and sent it to our own driver.  This task could be done
                              * with another device obviously but in this case we are doing it with our own.  As
                              * you can see we could easily have issued any major IRP function it's not limited
                              * to private IOCTLs.  Also, this is a simple implementation and there is a little 
                              * matter of "pending IRP's" that has been left out for simplicity.  It doesn't matter
                              * much however since this is our driver and we control all end points.
                              *
                              * The first parameter is the number of IO_STACK_LOCATION's that are allocated for this
                              * IRP.  We use the "StackSize" of the DeviceObject which tells the minimum number
                              * needed to send a request down this device stack.  The initial value is 1 and then
                              * any device driver which then attaches to the device stack of this driver will then
                              * add to this number.  If some higher level driver wants to allocate an IRP and do
                              * some processing on it as well as apart of this IRP stack then it should keep
                              * that in mind when allocating the IRP and ensuring the correct number of stack
                              * locations is allocated.
                              *
                              * The second parameter is to determine whether this IRP should be charged to the
                              * quota of the current process.
                              *
                              * IoBuildSynchronousFsdRequest & IoBuildAsynchronousFsdRequest actually do what
                              * we are doing here execpt they do it for you in one function call.  There is a slight
                              * difference as well though as SynchronousFsdRequest will do a little more so the I/O
                              * Manager is aware and will cal IoFreeIrp for you where BuildAsyncrhonous will not.
                              * 
                              * Other than that,  IoBuildSynchronousFsdRequest actually calls IoBuildAsynchronousFsdRequest
                              * if you look at these in a debugger.
                              *
                              * IoBuildDeviceIoControlRequest Also does this for you, infact even more since it also sets up
                              * the IO_STACK_LOCATION with the correct Major IRP function and IOCTL code.
                              *
                              * We set the other parameters to NULL since we will set them manually anyway.
                              */
                             pTopOfStackDevice = IoGetRelatedDeviceObject(pFileObject);

                             MyIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_INTERNAL_DEVICE_CONTROL, pTopOfStackDevice, NULL, 0, &StartOffset, &StatusBlock);

                             if(MyIrp)
                             {
                                 PIO_STACK_LOCATION pMyIoStackLocation = IoGetNextIrpStackLocation(MyIrp);

                                 pMyIoStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
                                 pMyIoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_CLOSE_RESOURCE_CONTEXT;


                                /*
                                 * METHOD_BUFFERED
                                 *
                                 *    Input Buffer = Irp->AssociatedIrp.SystemBuffer
                                 *    Ouput Buffer = Irp->AssociatedIrp.SystemBuffer
                                 *
                                 *    Input Size   =  Parameters.DeviceIoControl.InputBufferLength
                                 *    Output Size  =  Parameters.DeviceIoControl.OutputBufferLength
                                 *
                                 *    Since we are now doing the same job as the I/O Manager,
                                 *    to follow the rules our IOCTL specified METHOD_BUFFERED
                                 */  
                                 pMyIoStackLocation->Parameters.DeviceIoControl.InputBufferLength  = sizeof(EXAMPLE_LIST);
                                 pMyIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -