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.

434 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntdisp.c
  5. Abstract:
  6. NT specific routines for dispatching and handling automatic
  7. connection notification IRPs.
  8. The basic architecture involves a user address space,
  9. a network transport, and this driver.
  10. The user address space is responsible for creating a
  11. new network connection given a notification from this
  12. driver (IOCTL_ACD_NOTIFICATION). When it gets a
  13. notification, it is also responsible for pinging the
  14. this driver (IOCTL_ACD_KEEPALIVE) so it can be guaranteed
  15. the connection is progressing. Once the connection is
  16. created, it informs this driver of the success or
  17. failure of the connection attempt (IOCTL_ACD_CONNECTION).
  18. Network transports are responsible for informing this
  19. driver of network unreachable errors via TdiConnect()
  20. or TdiSendDatagram(). When this happens, the transport
  21. is responsible for dequeueing the send request from any
  22. of its internal queues and enqueueing the request in
  23. this driver (AcdWaitForCompletion()), supplying a callback
  24. to be called when the connection has been completed.
  25. Author:
  26. Anthony Discolo (adiscolo) 18-Apr-1995
  27. Revision History:
  28. --*/
  29. #include <ndis.h>
  30. #include <cxport.h>
  31. #include <tdikrnl.h>
  32. #include <tdistat.h>
  33. #include <tdiinfo.h>
  34. #include <acd.h>
  35. #include "acdapi.h"
  36. #include "debug.h"
  37. //
  38. // Driver reference count
  39. //
  40. ULONG ulAcdOpenCountG;
  41. //
  42. // Imported routines
  43. //
  44. NTSTATUS
  45. AcdEnable(
  46. IN PIRP pIrp,
  47. IN PIO_STACK_LOCATION pIrpSp
  48. );
  49. VOID
  50. AcdCancelNotifications();
  51. NTSTATUS
  52. AcdWaitForNotification(
  53. IN PIRP pIrp,
  54. IN PIO_STACK_LOCATION pIrpSp
  55. );
  56. NTSTATUS
  57. AcdConnectionInProgress(
  58. IN PIRP pIrp,
  59. IN PIO_STACK_LOCATION pIrpSp
  60. );
  61. NTSTATUS
  62. AcdSignalCompletion(
  63. IN PIRP pIrp,
  64. IN PIO_STACK_LOCATION pIrpSp
  65. );
  66. NTSTATUS
  67. AcdConnectAddress(
  68. IN PIRP pIrp,
  69. IN PIO_STACK_LOCATION pIrpSp
  70. );
  71. VOID
  72. AcdReset();
  73. NTSTATUS
  74. AcdGetAddressAttributes(
  75. IN PIRP pIrp,
  76. IN PIO_STACK_LOCATION pIrpSp
  77. );
  78. NTSTATUS
  79. AcdSetAddressAttributes(
  80. IN PIRP pIrp,
  81. IN PIO_STACK_LOCATION pIrpSp
  82. );
  83. NTSTATUS
  84. AcdQueryState(
  85. IN PIRP pIrp,
  86. IN PIO_STACK_LOCATION pIrpSp
  87. );
  88. NTSTATUS
  89. AcdEnableAddress(
  90. IN PIRP pIrp,
  91. IN PIO_STACK_LOCATION pIrpSp
  92. );
  93. //
  94. // Internal function prototypes
  95. //
  96. NTSTATUS
  97. AcdCreate(
  98. IN PIRP pIrp,
  99. IN PIO_STACK_LOCATION pIrpSp
  100. );
  101. NTSTATUS
  102. AcdDispatchDeviceControl(
  103. IN PIRP pIrp,
  104. IN PIO_STACK_LOCATION pIrpSp
  105. );
  106. NTSTATUS
  107. AcdDispatchInternalDeviceControl(
  108. IN PIRP pIrp,
  109. IN PIO_STACK_LOCATION pIrpSp
  110. );
  111. NTSTATUS
  112. AcdCleanup(
  113. IN PIRP pIrp,
  114. IN PIO_STACK_LOCATION pIrpSp
  115. );
  116. NTSTATUS
  117. AcdClose(
  118. IN PIRP pIrp,
  119. IN PIO_STACK_LOCATION pIrpSp
  120. );
  121. NTSTATUS
  122. AcdBind(
  123. IN PIRP pIrp,
  124. IN PIO_STACK_LOCATION pIrpSp
  125. );
  126. NTSTATUS
  127. AcdUnbind(
  128. IN PIRP pIrp,
  129. IN PIO_STACK_LOCATION pIrpSp
  130. );
  131. //
  132. // All of this code is pageable.
  133. //
  134. #ifdef ALLOC_PRAGMA
  135. #pragma alloc_text(PAGE, AcdCreate)
  136. #pragma alloc_text(PAGE, AcdDispatchDeviceControl)
  137. #pragma alloc_text(PAGE, AcdDispatchInternalDeviceControl)
  138. #pragma alloc_text(PAGE, AcdCleanup)
  139. #pragma alloc_text(PAGE, AcdClose)
  140. #endif // ALLOC_PRAGMA
  141. NTSTATUS
  142. AcdCreate(
  143. IN PIRP pIrp,
  144. IN PIO_STACK_LOCATION pIrpSp
  145. )
  146. {
  147. ulAcdOpenCountG++;
  148. IF_ACDDBG(ACD_DEBUG_OPENCOUNT) {
  149. AcdPrint(("AcdCreate: ulAcdOpenCountG=%d\n", ulAcdOpenCountG));
  150. }
  151. return STATUS_SUCCESS;
  152. } // AcdCreate
  153. NTSTATUS
  154. AcdDispatchDeviceControl(
  155. IN PIRP pIrp,
  156. IN PIO_STACK_LOCATION pIrpSp
  157. )
  158. {
  159. NTSTATUS status;
  160. PAGED_CODE();
  161. //
  162. // Set this in advance. Any IOCTL dispatch routine that cares about it
  163. // will modify it itself.
  164. //
  165. pIrp->IoStatus.Information = 0;
  166. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode) {
  167. case IOCTL_ACD_RESET:
  168. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  169. AcdPrint(("AcdDispatchDeviceControl: IOCTL_ACD_RESET\n"));
  170. }
  171. AcdReset();
  172. status = STATUS_SUCCESS;
  173. break;
  174. case IOCTL_ACD_ENABLE:
  175. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  176. AcdPrint(("AcdDispatchDeviceControl: IOCTL_ACD_ENABLE\n"));
  177. }
  178. //
  179. // Enable/disable requests to/from the driver.
  180. //
  181. status = AcdEnable(pIrp, pIrpSp);
  182. break;
  183. case IOCTL_ACD_NOTIFICATION:
  184. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  185. AcdPrint(("AcdDispatchDeviceControl: IOCTL_ACD_NOTIFICATION\n"));
  186. }
  187. //
  188. // This irp will be completed upon the
  189. // next connection attempt to
  190. // allow a user-space process to attempt
  191. // to make a connection.
  192. //
  193. status = AcdWaitForNotification(pIrp, pIrpSp);
  194. break;
  195. case IOCTL_ACD_KEEPALIVE:
  196. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  197. AcdPrint(("AcdDispatchDeviceControl: IOCTL_ACD_KEEPALIVE\n"));
  198. }
  199. //
  200. // Inform the driver that the connection
  201. // is in the process of being created.
  202. //
  203. status = AcdConnectionInProgress(pIrp, pIrpSp);
  204. break;
  205. case IOCTL_ACD_COMPLETION:
  206. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  207. AcdPrint(("AcdDispatchDeviceControl: IOCTL_ACD_COMPLETION\n"));
  208. }
  209. //
  210. // Complete all pending irps that initially
  211. // encountered a network unreachable error,
  212. // and have been waiting for a connection to be
  213. // made.
  214. //
  215. status = AcdSignalCompletion(pIrp, pIrpSp);
  216. break;
  217. case IOCTL_ACD_CONNECT_ADDRESS:
  218. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  219. AcdPrint(("AcdDispatchDeviceControl: IOCTL_ACD_CONNECT_ADDRESS\n"));
  220. }
  221. //
  222. // This allows a user space application to
  223. // generate the same automatic connection
  224. // mechanism as a transport protocol.
  225. //
  226. status = AcdConnectAddress(pIrp, pIrpSp);
  227. break;
  228. case IOCTL_ACD_ENABLE_ADDRESS:
  229. //DbgPrint("AcdDispatchDeviceControl: IOCTL_ACD_ENABLE_ADDRESS\n");
  230. status = AcdEnableAddress(pIrp, pIrpSp);
  231. break;
  232. default:
  233. status = STATUS_NOT_IMPLEMENTED;
  234. break;
  235. }
  236. if (status != STATUS_PENDING) {
  237. pIrp->IoStatus.Status = status;
  238. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  239. }
  240. return status;
  241. } // AcdDispatchDeviceControl
  242. NTSTATUS
  243. AcdDispatchInternalDeviceControl(
  244. IN PIRP pIrp,
  245. IN PIO_STACK_LOCATION pIrpSp
  246. )
  247. {
  248. NTSTATUS status;
  249. PAGED_CODE();
  250. //
  251. // Set this in advance. Any IOCTL dispatch routine that cares about it
  252. // will modify it itself.
  253. //
  254. pIrp->IoStatus.Information = 0;
  255. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode) {
  256. case IOCTL_INTERNAL_ACD_BIND:
  257. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  258. AcdPrint(("AcdDispatchInternalDeviceControl: IOCTL_INTERNAL_ACD_BIND\n"));
  259. }
  260. //
  261. // Transfer entrypoints to client.
  262. //
  263. status = AcdBind(pIrp, pIrpSp);
  264. break;
  265. case IOCTL_INTERNAL_ACD_UNBIND:
  266. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  267. AcdPrint(("AcdDispatchInternalDeviceControl: IOCTL_INTERNAL_ACD_UNBIND\n"));
  268. }
  269. //
  270. // Remove any pending requests from
  271. // this driver.
  272. //
  273. status = AcdUnbind(pIrp, pIrpSp);
  274. break;
  275. case IOCTL_INTERNAL_ACD_QUERY_STATE:
  276. IF_ACDDBG(ACD_DEBUG_IOCTL) {
  277. AcdPrint(("AcdDispatchDeviceControl: IOCTL_INTERNAL_ACD_QUERY_STATE\n"));
  278. }
  279. status = AcdQueryState(pIrp, pIrpSp);
  280. break;
  281. default:
  282. status = STATUS_NOT_IMPLEMENTED;
  283. break;
  284. }
  285. if (status != STATUS_PENDING) {
  286. pIrp->IoStatus.Status = status;
  287. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  288. }
  289. return status;
  290. } // AcdDispatchInternalDeviceControl
  291. NTSTATUS
  292. AcdCleanup(
  293. IN PIRP pIrp,
  294. IN PIO_STACK_LOCATION pIrpSp
  295. )
  296. {
  297. return STATUS_SUCCESS;
  298. } // AcdCleanup
  299. NTSTATUS
  300. AcdClose(
  301. IN PIRP pIrp,
  302. IN PIO_STACK_LOCATION pIrpSp
  303. )
  304. {
  305. ulAcdOpenCountG--;
  306. IF_ACDDBG(ACD_DEBUG_OPENCOUNT) {
  307. AcdPrint(("AcdClose: ulAcdOpenCountG=%d\n", ulAcdOpenCountG));
  308. }
  309. if (!ulAcdOpenCountG)
  310. AcdReset();
  311. return STATUS_SUCCESS;
  312. } // AcdClose
  313. NTSTATUS
  314. AcdDispatch(
  315. IN PDEVICE_OBJECT pDeviceObject,
  316. IN PIRP pIrp
  317. )
  318. /*++
  319. DESCRIPTION
  320. This is the dispatch routine for the network connection
  321. notification driver.
  322. ARGUMENTS
  323. pDeviceObject: a pointer to device object for target device
  324. pIrp: a pointer to I/O request packet
  325. Return Value:
  326. NTSTATUS
  327. --*/
  328. {
  329. NTSTATUS status;
  330. PIO_STACK_LOCATION pIrpSp;
  331. UNREFERENCED_PARAMETER(pDeviceObject);
  332. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  333. switch (pIrpSp->MajorFunction) {
  334. case IRP_MJ_CREATE:
  335. status = AcdCreate(pIrp, pIrpSp);
  336. break;
  337. case IRP_MJ_DEVICE_CONTROL:
  338. return AcdDispatchDeviceControl(pIrp, pIrpSp);
  339. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  340. return AcdDispatchInternalDeviceControl(pIrp, pIrpSp);
  341. case IRP_MJ_CLEANUP:
  342. status = AcdCleanup(pIrp, pIrpSp);
  343. break;
  344. case IRP_MJ_CLOSE:
  345. status = AcdClose(pIrp, pIrpSp);
  346. break;
  347. default:
  348. status = STATUS_NOT_IMPLEMENTED;
  349. break;
  350. }
  351. if (status != STATUS_PENDING) {
  352. pIrp->IoStatus.Status = status;
  353. pIrp->IoStatus.Information = 0;
  354. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  355. }
  356. return status;
  357. } // AcdDispatch
  358.