ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

csq.h
Go to the documentation of this file.
00001 /*
00002  * Cancel-Safe Queue Library
00003  * Created in 2004 by Vizzini (vizzini@plasmic.com)
00004  *
00005  * THIS SOFTWARE IS NOT COPYRIGHTED
00006  *
00007  * This source code is offered for use in the public domain. You may
00008  * use, modify or distribute it freely.
00009  *
00010  * This code is distributed in the hope that it will be useful but
00011  * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
00012  * DISCLAIMED. This includes but is not limited to warranties of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00014  *
00015  *
00016  * This header defines the interface to the ReactOS Cancel-Safe Queue library.
00017  * This interface is based on and is similar to the Microsoft Cancel-Safe
00018  * Queue interface.
00019  *
00020  * BACKGROUND
00021  *
00022  * IRP queuing is a royal pain in the butt, due to the fact that there are
00023  * tons of built-in race conditions.  IRP handling is difficult in general,
00024  * but the cancel logic has been particularly complicated due to some subtle
00025  * races, coupled with the fact that the system interfaces have changed over
00026  * time.
00027  *
00028  * Walter Oney (2nd. Ed. of Programming the Windows Driver Model) states a
00029  * common opinion among driver developers when he says that it is foolish
00030  * to try to roll your own cancel logic.  There are only a very few people
00031  * who have gotten it right in the past.  He suggests, instead, that you
00032  * either use his own well-tested code, or use the code in the Microsoft
00033  * Cancel-Safe Queue Library.
00034  *
00035  * We cannot do either, of course, due to copyright issues.  I have therefore
00036  * created this clone of the Microsoft library in order to concentrate all
00037  * of the IRP-queuing bugs in one place.  I'm quite sure there are problems
00038  * here, so if you are a driver writer, I'd be glad to hear your feedback.
00039  *
00040  * Apart from that, please try to use these routines, rather than building
00041  * your own.  If you think you have found a bug, please bring it up with me
00042  * or on-list, as this is complicated and non-obvious stuff.  Don't just
00043  * change this and hope for the best!
00044  *
00045  * USAGE
00046  *
00047  * This library follows exactly the same interface as the Microsoft Cancel-Safe
00048  * Queue routines (IoCsqXxx()).  As such, the authoritative reference is the
00049  * current DDK.  There is also a DDK sample called "cancel" that has an
00050  * example of how to use this code.  I have also provided a sample driver
00051  * that makes use of this queue. Finally, please do read the header and the
00052  * source if you're curious about the inner workings of these routines.
00053  */
00054 
00055 #pragma once
00056 
00057 #define _CSQ_H_
00058 
00059 #ifdef __cplusplus
00060 extern "C" {
00061 #endif
00062 
00063 /*
00064  * Prevent including the CSQ definitions twice. They're present in NTDDK
00065  * now too, except the *_EX versions.
00066  */
00067 #ifndef IO_TYPE_CSQ_IRP_CONTEXT
00068 
00069 typedef struct _IO_CSQ IO_CSQ, *PIO_CSQ;
00070 
00071 /*
00072  * STRUCTURES
00073  *
00074  * NOTE:  Please do not use these directly.  You will make incompatible code
00075  * if you do.  Always only use the documented IoCsqXxx() interfaces and you
00076  * will amass much Good Karma.
00077  */
00078 #define IO_TYPE_CSQ_IRP_CONTEXT 1
00079 #define IO_TYPE_CSQ 2
00080 
00081 /*
00082  * IO_CSQ_IRP_CONTEXT - Context used to track an IRP in the CSQ
00083  */
00084 typedef struct _IO_CSQ_IRP_CONTEXT {
00085   ULONG Type;
00086   PIRP Irp;
00087   PIO_CSQ Csq;
00088 } IO_CSQ_IRP_CONTEXT, *PIO_CSQ_IRP_CONTEXT;
00089 
00090 /*
00091  * CSQ Callbacks
00092  *
00093  * The cancel-safe queue is implemented as a set of IoCsqXxx() OS routines
00094  * copuled with a set of driver callbacks to handle the basic operations of
00095  * the queue.  You need to supply one of each of these functions in your own
00096  * driver.  These routines are also documented in the DDK under CsqXxx().
00097  * That is the authoritative documentation.
00098  */
00099 
00100 /*
00101  * Function to insert an IRP in the queue.  No need to worry about locking;
00102  * just tack it onto your list or something.
00103  *
00104  * Sample implementation:
00105  *
00106   VOID NTAPI CsqInsertIrp(PIO_CSQ Csq, PIRP Irp)
00107   {
00108     KdPrint(("Inserting IRP 0x%x into CSQ\n", Irp));
00109     InsertTailList(&IrpQueue, &Irp->Tail.Overlay.ListEntry);
00110   }
00111  *
00112  */
00113 typedef VOID
00114 (NTAPI IO_CSQ_INSERT_IRP)(
00115   _In_ struct _IO_CSQ *Csq,
00116   _In_ PIRP Irp);
00117 typedef IO_CSQ_INSERT_IRP *PIO_CSQ_INSERT_IRP;
00118 
00119 /*
00120  * Function to remove an IRP from the queue.
00121  *
00122  * Sample:
00123  *
00124   VOID NTAPI CsqRemoveIrp(PIO_CSQ Csq, PIRP Irp)
00125   {
00126     KdPrint(("Removing IRP 0x%x from CSQ\n", Irp));
00127     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
00128   }
00129  *
00130  */
00131 typedef VOID
00132 (NTAPI IO_CSQ_REMOVE_IRP)(
00133   _In_ struct _IO_CSQ *Csq,
00134   _In_ PIRP Irp);
00135 typedef IO_CSQ_REMOVE_IRP *PIO_CSQ_REMOVE_IRP;
00136 
00137 /*
00138  * Function to look for an IRP in the queue
00139  *
00140  * Sample:
00141  *
00142   PIRP NTAPI CsqPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
00143   {
00144     KdPrint(("Peeking for next IRP\n"));
00145 
00146     if(Irp)
00147       return CONTAINING_RECORD(&Irp->Tail.Overlay.ListEntry.Flink, IRP, Tail.Overlay.ListEntry);
00148 
00149     if(IsListEmpty(&IrpQueue))
00150       return NULL;
00151 
00152     return CONTAINING_RECORD(IrpQueue.Flink, IRP, Tail.Overlay.ListEntry);
00153   }
00154  *
00155  */
00156 typedef PIRP
00157 (NTAPI IO_CSQ_PEEK_NEXT_IRP)(
00158   _In_ struct _IO_CSQ *Csq,
00159   _In_opt_ PIRP Irp,
00160   _In_opt_ PVOID PeekContext);
00161 typedef IO_CSQ_PEEK_NEXT_IRP *PIO_CSQ_PEEK_NEXT_IRP;
00162 
00163 /*
00164  * Lock the queue.  This can be a spinlock, a mutex, or whatever
00165  * else floats your boat.
00166  *
00167  * Sample:
00168  *
00169   VOID NTAPI CsqAcquireLock(PIO_CSQ Csq, PKIRQL Irql)
00170   {
00171     KdPrint(("Acquiring spin lock\n"));
00172     KeAcquireSpinLock(&IrpQueueLock, Irql);
00173   }
00174  *
00175  */
00176 typedef VOID
00177 (NTAPI IO_CSQ_ACQUIRE_LOCK)(
00178   _In_ struct _IO_CSQ *Csq,
00179   _Out_ PKIRQL Irql);
00180 typedef IO_CSQ_ACQUIRE_LOCK *PIO_CSQ_ACQUIRE_LOCK;
00181 
00182 /*
00183  * Unlock the queue:
00184  *
00185   VOID NTAPI CsqReleaseLock(PIO_CSQ Csq, KIRQL Irql)
00186   {
00187     KdPrint(("Releasing spin lock\n"));
00188     KeReleaseSpinLock(&IrpQueueLock, Irql);
00189   }
00190  *
00191  */
00192 typedef VOID
00193 (NTAPI IO_CSQ_RELEASE_LOCK)(
00194   _In_ struct _IO_CSQ *Csq,
00195   _In_ KIRQL Irql);
00196 typedef IO_CSQ_RELEASE_LOCK *PIO_CSQ_RELEASE_LOCK;
00197 
00198 /*
00199  * Finally, this is called by the queue library when it wants to complete
00200  * a canceled IRP.
00201  *
00202  * Sample:
00203  *
00204   VOID NTAPI CsqCompleteCancelledIrp(PIO_CSQ Csq, PIRP Irp)
00205   {
00206     KdPrint(("cancelling irp 0x%x\n", Irp));
00207     Irp->IoStatus.Status = STATUS_CANCELLED;
00208     Irp->IoStatus.Information = 0;
00209     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00210   }
00211  *
00212  */
00213 typedef VOID
00214 (NTAPI IO_CSQ_COMPLETE_CANCELED_IRP)(
00215   _In_ struct _IO_CSQ *Csq,
00216   _In_ PIRP Irp);
00217 typedef IO_CSQ_COMPLETE_CANCELED_IRP *PIO_CSQ_COMPLETE_CANCELED_IRP;
00218 
00219 /*
00220  * IO_CSQ - Queue control structure
00221  */
00222 typedef struct _IO_CSQ {
00223   ULONG Type;
00224   PIO_CSQ_INSERT_IRP CsqInsertIrp;
00225   PIO_CSQ_REMOVE_IRP CsqRemoveIrp;
00226   PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp;
00227   PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock;
00228   PIO_CSQ_RELEASE_LOCK CsqReleaseLock;
00229   PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp;
00230   PVOID ReservePointer; /* must be NULL */
00231 } IO_CSQ, *PIO_CSQ;
00232 
00233 #endif /* IO_TYPE_CSQ_IRP_CONTEXT */
00234 
00235 #ifndef IO_TYPE_CSQ_EX
00236 
00237 /* See IO_TYPE_CSQ_* above */
00238 #define IO_TYPE_CSQ_EX 3
00239 
00240 /*
00241  * Function to insert an IRP into the queue with extended context information.
00242  * This is useful if you need to be able to de-queue particular IRPs more
00243  * easily in some cases.
00244  *
00245  * Same deal as above; sample implementation:
00246  *
00247   NTSTATUS NTAPI CsqInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)
00248   {
00249     CsqInsertIrp(Csq, Irp);
00250     return STATUS_PENDING;
00251   }
00252  *
00253  */
00254 typedef NTSTATUS
00255 (NTAPI IO_CSQ_INSERT_IRP_EX)(
00256   _In_ struct _IO_CSQ *Csq,
00257   _In_ PIRP Irp,
00258   _In_ PVOID InsertContext);
00259 typedef IO_CSQ_INSERT_IRP_EX *PIO_CSQ_INSERT_IRP_EX;
00260 
00261 #endif /* IO_TYPE_CSQ_EX */
00262 
00263 /*
00264  * CANCEL-SAFE QUEUE DDIs
00265  *
00266  * These device driver interfaces are called to make use of the queue.  Again,
00267  * authoritative documentation for these functions is in the DDK.  The csqtest
00268  * driver also makes use of some of them.
00269  */
00270 
00271 
00272 /*
00273  * Call this in DriverEntry or similar in order to set up the Csq structure.
00274  * As long as the Csq struct and the functions you pass in are resident,
00275  * there are no IRQL restrictions.
00276  */
00277 NTKERNELAPI
00278 NTSTATUS NTAPI IoCsqInitialize(_Out_ PIO_CSQ Csq,
00279                                _In_ PIO_CSQ_INSERT_IRP CsqInsertIrp,
00280                                _In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp,
00281                                _In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp,
00282                                _In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock,
00283                                _In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock,
00284                                _In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp);
00285 
00286 /*
00287  * Same as above, except you provide a CsqInsertIrpEx routine instead of
00288  * CsqInsertIrp.  This eventually allows you to supply extra tracking
00289  * information for use with the queue.
00290  */
00291 NTKERNELAPI
00292 NTSTATUS NTAPI IoCsqInitializeEx(_Out_ PIO_CSQ Csq,
00293                                  _In_ PIO_CSQ_INSERT_IRP_EX CsqInsertIrpEx,
00294                                  _In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp,
00295                                  _In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp,
00296                                  _In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock,
00297                                  _In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock,
00298                                  _In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp);
00299 
00300 /*
00301  * Insert an IRP into the queue
00302  */
00303 NTKERNELAPI
00304 VOID NTAPI IoCsqInsertIrp(_Inout_ PIO_CSQ Csq,
00305                           _Inout_ PIRP Irp,
00306                           _Out_opt_ PIO_CSQ_IRP_CONTEXT Context);
00307 
00308 /*
00309  * Insert an IRP into the queue, with special context maintained that
00310  * makes it easy to find IRPs in the queue
00311  */
00312 NTKERNELAPI
00313 NTSTATUS NTAPI IoCsqInsertIrpEx(_Inout_ PIO_CSQ Csq,
00314                                 _Inout_ PIRP Irp,
00315                                 _Out_opt_ PIO_CSQ_IRP_CONTEXT Context,
00316                                 _In_opt_ PVOID InsertContext);
00317 
00318 /*
00319  * Remove a particular IRP from the queue
00320  */
00321 NTKERNELAPI
00322 PIRP NTAPI IoCsqRemoveIrp(_Inout_ PIO_CSQ Csq,
00323                           _Inout_ PIO_CSQ_IRP_CONTEXT Context);
00324 
00325 /*
00326  * Remove the next IRP from the queue
00327  */
00328 NTKERNELAPI
00329 PIRP NTAPI IoCsqRemoveNextIrp(_Inout_ PIO_CSQ Csq,
00330                               _In_opt_ PVOID PeekContext);
00331 
00332 #ifdef __cplusplus
00333 }
00334 #endif

Generated on Fri May 25 2012 04:28:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.