Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. Stolen from afd\misc.c
  7. Author:
  8. mbert 9-97
  9. --*/
  10. #include <ntosp.h>
  11. #include <cxport.h>
  12. #include <tdikrnl.h>
  13. #define UINT ULONG //tmp
  14. #include <refcnt.h>
  15. #include <af_irda.h>
  16. #include <irdatdi.h>
  17. #include <irtdicl.h>
  18. #include <irtdiclp.h>
  19. NTSTATUS
  20. IrdaRestartDeviceControl (
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN PIRP Irp,
  23. IN PVOID Context
  24. )
  25. {
  26. //
  27. // N.B. This routine can never be demand paged because it can be
  28. // called before any endpoints have been placed on the global
  29. // list--see IrdaAllocateEndpoint() and it's call to
  30. // IrdaGetTransportInfo().
  31. //
  32. //
  33. // If there was an MDL in the IRP, free it and reset the pointer to
  34. // NULL. The IO system can't handle a nonpaged pool MDL being freed
  35. // in an IRP, which is why we do it here.
  36. //
  37. if ( Irp->MdlAddress != NULL ) {
  38. IoFreeMdl( Irp->MdlAddress );
  39. Irp->MdlAddress = NULL;
  40. }
  41. return STATUS_SUCCESS;
  42. } // IrdaRestartDeviceControl
  43. NTSTATUS
  44. IrdaSetEventHandler (
  45. IN PFILE_OBJECT FileObject,
  46. IN ULONG EventType,
  47. IN PVOID EventHandler,
  48. IN PVOID EventContext
  49. )
  50. /*++
  51. Routine Description:
  52. Sets up a TDI indication handler on a connection or address object
  53. (depending on the file handle). This is done synchronously, which
  54. shouldn't usually be an issue since TDI providers can usually complete
  55. indication handler setups immediately.
  56. Arguments:
  57. FileObject - a pointer to the file object for an open connection or
  58. address object.
  59. EventType - the event for which the indication handler should be
  60. called.
  61. EventHandler - the routine to call when tghe specified event occurs.
  62. EventContext - context which is passed to the indication routine.
  63. Return Value:
  64. NTSTATUS -- Indicates the status of the request.
  65. --*/
  66. {
  67. TDI_REQUEST_KERNEL_SET_EVENT parameters;
  68. PAGED_CODE( );
  69. parameters.EventType = EventType;
  70. parameters.EventHandler = EventHandler;
  71. parameters.EventContext = EventContext;
  72. return IrdaIssueDeviceControl(
  73. NULL,
  74. FileObject,
  75. &parameters,
  76. sizeof(parameters),
  77. NULL,
  78. 0,
  79. TDI_SET_EVENT_HANDLER
  80. );
  81. } // IrdaSetEventHandler
  82. NTSTATUS
  83. IrdaIssueDeviceControl (
  84. IN HANDLE FileHandle OPTIONAL,
  85. IN PFILE_OBJECT FileObject OPTIONAL,
  86. IN PVOID IrpParameters,
  87. IN ULONG IrpParametersLength,
  88. IN PVOID MdlBuffer,
  89. IN ULONG MdlBufferLength,
  90. IN UCHAR MinorFunction
  91. )
  92. /*++
  93. Routine Description:
  94. Issues a device control returst to a TDI provider and waits for the
  95. request to complete.
  96. Note that while FileHandle and FileObject are both marked as optional,
  97. in reality exactly one of these must be specified.
  98. Arguments:
  99. FileHandle - a TDI handle.
  100. FileObject - a pointer to the file object corresponding to a TDI
  101. handle
  102. IrpParameters - information to write to the parameters section of the
  103. stack location of the IRP.
  104. IrpParametersLength - length of the parameter information. Cannot be
  105. greater than 16.
  106. MdlBuffer - if non-NULL, a buffer of nonpaged pool to be mapped
  107. into an MDL and placed in the MdlAddress field of the IRP.
  108. MdlBufferLength - the size of the buffer pointed to by MdlBuffer.
  109. MinorFunction - the minor function code for the request.
  110. Return Value:
  111. NTSTATUS -- Indicates the status of the request.
  112. --*/
  113. {
  114. NTSTATUS status;
  115. PFILE_OBJECT fileObject;
  116. PIRP irp;
  117. PIO_STACK_LOCATION irpSp;
  118. KEVENT event;
  119. IO_STATUS_BLOCK ioStatusBlock;
  120. PDEVICE_OBJECT deviceObject;
  121. PMDL mdl;
  122. PAGED_CODE( );
  123. //
  124. // Initialize the kernel event that will signal I/O completion.
  125. //
  126. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  127. if( FileHandle != NULL ) {
  128. ASSERT( FileObject == NULL );
  129. //
  130. // Get the file object corresponding to the directory's handle.
  131. // Referencing the file object every time is necessary because the
  132. // IO completion routine dereferences it.
  133. //
  134. status = ObReferenceObjectByHandle(
  135. FileHandle,
  136. 0L, // DesiredAccess
  137. NULL, // ObjectType
  138. KernelMode,
  139. (PVOID *)&fileObject,
  140. NULL
  141. );
  142. if ( !NT_SUCCESS(status) ) {
  143. return status;
  144. }
  145. } else {
  146. ASSERT( FileObject != NULL );
  147. //
  148. // Reference the passed in file object. This is necessary because
  149. // the IO completion routine dereferences it.
  150. //
  151. ObReferenceObject( FileObject );
  152. fileObject = FileObject;
  153. }
  154. //
  155. // Set the file object event to a non-signaled state.
  156. //
  157. (VOID) KeResetEvent( &fileObject->Event );
  158. //
  159. // Attempt to allocate and initialize the I/O Request Packet (IRP)
  160. // for this operation.
  161. //
  162. deviceObject = IoGetRelatedDeviceObject ( fileObject );
  163. irp = IoAllocateIrp( (deviceObject)->StackSize, TRUE );
  164. if ( irp == NULL ) {
  165. ObDereferenceObject( fileObject );
  166. return STATUS_INSUFFICIENT_RESOURCES;
  167. }
  168. //
  169. // Fill in the service independent parameters in the IRP.
  170. //
  171. irp->Flags = (LONG)IRP_SYNCHRONOUS_API;
  172. irp->RequestorMode = KernelMode;
  173. irp->PendingReturned = FALSE;
  174. irp->UserIosb = &ioStatusBlock;
  175. irp->UserEvent = &event;
  176. irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  177. irp->AssociatedIrp.SystemBuffer = NULL;
  178. irp->UserBuffer = NULL;
  179. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  180. irp->Tail.Overlay.OriginalFileObject = fileObject;
  181. irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  182. /*
  183. DEBUG ioStatusBlock.Status = STATUS_UNSUCCESSFUL;
  184. DEBUG ioStatusBlock.Information = (ULONG)-1;
  185. */
  186. //
  187. // If an MDL buffer was specified, get an MDL, map the buffer,
  188. // and place the MDL pointer in the IRP.
  189. //
  190. if ( MdlBuffer != NULL ) {
  191. mdl = IoAllocateMdl(
  192. MdlBuffer,
  193. MdlBufferLength,
  194. FALSE,
  195. FALSE,
  196. irp
  197. );
  198. if ( mdl == NULL ) {
  199. IoFreeIrp( irp );
  200. ObDereferenceObject( fileObject );
  201. return STATUS_INSUFFICIENT_RESOURCES;
  202. }
  203. MmBuildMdlForNonPagedPool( mdl );
  204. } else {
  205. irp->MdlAddress = NULL;
  206. }
  207. //
  208. // Put the file object pointer in the stack location.
  209. //
  210. irpSp = IoGetNextIrpStackLocation( irp );
  211. irpSp->FileObject = fileObject;
  212. irpSp->DeviceObject = deviceObject;
  213. //
  214. // Fill in the service-dependent parameters for the request.
  215. //
  216. ASSERT( IrpParametersLength <= sizeof(irpSp->Parameters) );
  217. RtlCopyMemory( &irpSp->Parameters, IrpParameters, IrpParametersLength );
  218. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  219. irpSp->MinorFunction = MinorFunction;
  220. //
  221. // Set up a completion routine which we'll use to free the MDL
  222. // allocated previously.
  223. //
  224. IoSetCompletionRoutine( irp, IrdaRestartDeviceControl, NULL, TRUE, TRUE, TRUE );
  225. //
  226. // Queue the IRP to the thread and pass it to the driver.
  227. //
  228. IoEnqueueIrp( irp );
  229. status = IoCallDriver( deviceObject, irp );
  230. //
  231. // If necessary, wait for the I/O to complete.
  232. //
  233. if ( status == STATUS_PENDING ) {
  234. KeWaitForSingleObject( (PVOID)&event, UserRequest, KernelMode, FALSE, NULL );
  235. }
  236. //
  237. // If the request was successfully queued, get the final I/O status.
  238. //
  239. if ( NT_SUCCESS(status) ) {
  240. status = ioStatusBlock.Status;
  241. }
  242. return status;
  243. } // IrdaIssueDeviceControl