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.

639 lines
17 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. autodial.c
  5. Abstract:
  6. This file provides routines for interacting
  7. with the automatic connection driver (acd.sys).
  8. Author:
  9. Anthony Discolo (adiscolo) 9-6-95
  10. Revision History:
  11. --*/
  12. #include "precomp.h" // procedure headings
  13. #ifdef RASAUTODIAL
  14. #ifndef VXD
  15. #include <acd.h>
  16. #include <acdapi.h>
  17. #endif
  18. //******************* Pageable Routine Declarations ****************
  19. #ifdef ALLOC_PRAGMA
  20. #pragma CTEMakePageable(INIT, NbtAcdBind)
  21. #pragma CTEMakePageable(PAGE, NbtAcdUnbind)
  22. #endif
  23. //******************* Pageable Routine Declarations ****************
  24. //
  25. // Automatic connection global variables.
  26. //
  27. BOOLEAN fAcdLoadedG;
  28. ACD_DRIVER AcdDriverG;
  29. ULONG ulDriverIdG = 'Nbt ';
  30. //
  31. // Imported routines.
  32. //
  33. VOID
  34. CleanUpPartialConnection(
  35. IN NTSTATUS status,
  36. IN tCONNECTELE *pConnEle,
  37. IN tDGRAM_SEND_TRACKING *pTracker,
  38. IN PIRP pClientIrp,
  39. IN CTELockHandle irqlJointLock,
  40. IN CTELockHandle irqlConnEle
  41. );
  42. NTSTATUS
  43. NbtConnectCommon(
  44. IN TDI_REQUEST *pRequest,
  45. IN PVOID pTimeout,
  46. IN PTDI_CONNECTION_INFORMATION pCallInfo,
  47. IN PIRP pIrp
  48. );
  49. NTSTATUS
  50. NbtpConnectCompletionRoutine(
  51. PDEVICE_OBJECT pDeviceObject,
  52. PIRP pIrp,
  53. PVOID pCompletionContext
  54. );
  55. VOID
  56. NbtRetryPreConnect(
  57. IN BOOLEAN fSuccess,
  58. IN PVOID *pArgs
  59. )
  60. /*++
  61. Routine Description:
  62. This routine is called indirectly by the automatic
  63. connection driver to continue the connection process
  64. after an automatic connection has been made.
  65. Arguments:
  66. fSuccess - TRUE if the connection attempt was successful.
  67. pArgs - a pointer to the argument vector
  68. Return Value:
  69. None.
  70. --*/
  71. {
  72. NTSTATUS status;
  73. tCONNECTELE *pConnEle = pArgs[0];
  74. PVOID pTimeout = pArgs[1];
  75. PTDI_CONNECTION_INFORMATION pCallInfo = pArgs[2];
  76. PIRP pIrp = pArgs[3];
  77. TDI_REQUEST request;
  78. KIRQL irql;
  79. CTELockHandle OldIrq;
  80. tDEVICECONTEXT *pDeviceContext = pConnEle->pDeviceContext;
  81. IF_DBG(NBT_DEBUG_NAME)
  82. KdPrint(("Nbt.NbtRetryPreConnect: fSuccess=%d, pIrp=0x%x, pIrp->Cancel=%d, pConnEle=0x%x\n",
  83. fSuccess, pIrp, pIrp->Cancel, pConnEle));
  84. request.Handle.ConnectionContext = pConnEle;
  85. status = NbtCancelCancelRoutine (pIrp);
  86. if (status != STATUS_CANCELLED)
  87. {
  88. //
  89. // We're done with the connection progress,
  90. // so clear the fAutoConnecting flag. We
  91. // set the fAutoConnected flag to prevent us
  92. // from re-attempting another automatic
  93. // connection on this connection.
  94. //
  95. CTESpinLock(pConnEle,OldIrq);
  96. pConnEle->fAutoConnecting = FALSE;
  97. pConnEle->fAutoConnected = TRUE;
  98. CTESpinFree(pConnEle,OldIrq);
  99. status = fSuccess ? NbtConnectCommon (&request, pTimeout, pCallInfo, pIrp) :
  100. STATUS_BAD_NETWORK_PATH;
  101. //
  102. // We are responsible for completing
  103. // the irp.
  104. //
  105. if (status != STATUS_PENDING)
  106. {
  107. //
  108. // Clear out the Irp pointer in the Connection object so that we dont try to
  109. // complete it again when we clean up the connection. Do this under the connection
  110. // lock.
  111. //
  112. CTESpinLock(pConnEle,OldIrq);
  113. pConnEle->pIrp = NULL;
  114. CTESpinFree(pConnEle,OldIrq);
  115. pIrp->IoStatus.Status = status;
  116. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  117. }
  118. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_AUTODIAL, FALSE);
  119. }
  120. } // NbtRetryPreConnect
  121. BOOLEAN
  122. NbtCancelAutoDialRequest(
  123. IN PVOID pArg,
  124. IN ULONG ulFlags,
  125. IN ACD_CONNECT_CALLBACK pProc,
  126. IN USHORT nArgs,
  127. IN PVOID *pArgs
  128. )
  129. {
  130. if (nArgs != 5)
  131. return FALSE;
  132. return (pArgs[4] == pArg);
  133. } // NbtCancelAutoDialRequest
  134. BOOLEAN
  135. NbtCancelPreConnect(
  136. IN PDEVICE_OBJECT pDeviceObject,
  137. IN PIRP pIrp
  138. )
  139. {
  140. NTSTATUS status;
  141. PIO_STACK_LOCATION pIrpSp;
  142. tCONNECTELE *pConnEle;
  143. KIRQL irql;
  144. ACD_ADDR *pAddr;
  145. BOOLEAN fCancelled;
  146. CTELockHandle OldIrq;
  147. UNREFERENCED_PARAMETER(pDeviceObject);
  148. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  149. pConnEle = (tCONNECTELE *) pIrpSp->FileObject->FsContext;
  150. if ((!pConnEle) ||
  151. (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) ||
  152. (!(pAddr = (ACD_ADDR *) NbtAllocMem(sizeof(ACD_ADDR),NBT_TAG('A')))))
  153. {
  154. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  155. ASSERTMSG ("Nbt.NbtCancelPreConnect: ERROR - Invalid Connection Handle\n", 0);
  156. return FALSE;
  157. }
  158. IF_DBG(NBT_DEBUG_NAME)
  159. KdPrint(("NbtCancelPreConnect: pIrp=0x%x, pConnEle=0x%x\n", pIrp, pConnEle));
  160. //
  161. // Get the address of the connection.
  162. //
  163. pAddr->fType = ACD_ADDR_NB;
  164. RtlCopyMemory(&pAddr->cNetbios, pConnEle->RemoteName, 16);
  165. //
  166. // Cancel the autodial request.
  167. //
  168. fCancelled = (*AcdDriverG.lpfnCancelConnection) (ulDriverIdG, pAddr, NbtCancelAutoDialRequest, pIrp);
  169. if (fCancelled)
  170. {
  171. IoSetCancelRoutine(pIrp, NULL);
  172. }
  173. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  174. CTEMemFree(pAddr);
  175. //
  176. // If the request could not be found
  177. // in the driver, then it has already
  178. // been completed, so we simply return.
  179. //
  180. if (!fCancelled)
  181. {
  182. return FALSE;
  183. }
  184. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  185. pIrp->IoStatus.Status = STATUS_CANCELLED;
  186. pIrp->IoStatus.Information = 0;
  187. NBT_DEREFERENCE_DEVICE (pConnEle->pDeviceContext, REF_DEV_AUTODIAL, FALSE);
  188. //
  189. // Clear out the Irp pointer in the Connection object so that we dont try to
  190. // complete it again when we clean up the connection. Do this under the connection
  191. // lock.
  192. //
  193. // This should not be needed since before we call NbtConnectCommon, the Cancel routine
  194. // is NULLed out, so it cannot happen that the pIrp ptr in the connection is set to the
  195. // Irp, and this cancel routine is called.
  196. //
  197. CTESpinLock(pConnEle,OldIrq);
  198. pConnEle->pIrp = NULL;
  199. CTESpinFree(pConnEle,OldIrq);
  200. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  201. KeLowerIrql(irql);
  202. return TRUE;
  203. } // NbtCancelPreConnect
  204. BOOLEAN
  205. NbtCancelPostConnect(
  206. IN PIRP pIrp
  207. )
  208. {
  209. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  210. tCONNECTELE *pConnEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  211. ACD_ADDR *pAddr;
  212. BOOLEAN fCancelled;
  213. if ((!pConnEle) ||
  214. (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) ||
  215. (!(pAddr = (ACD_ADDR *) NbtAllocMem(sizeof(ACD_ADDR),NBT_TAG('A')))))
  216. {
  217. ASSERTMSG ("Nbt.NbtCancelPostConnect: ERROR - Invalid Connection Handle\n", 0);
  218. return FALSE;
  219. }
  220. IF_DBG(NBT_DEBUG_NAME)
  221. KdPrint(("Nbt.NbtCancelPostConnect: pIrp=0x%x, pConnEle=0x%x\n", pIrp, pConnEle));
  222. //
  223. // Get the address of the connection.
  224. //
  225. pAddr->fType = ACD_ADDR_NB;
  226. RtlCopyMemory(&pAddr->cNetbios, pConnEle->RemoteName, 15);
  227. //
  228. // Cancel the autodial request.
  229. //
  230. fCancelled = (*AcdDriverG.lpfnCancelConnection) (ulDriverIdG, pAddr, NbtCancelAutoDialRequest, pIrp);
  231. if (fCancelled)
  232. {
  233. NBT_DEREFERENCE_DEVICE (pConnEle->pDeviceContext, REF_DEV_AUTODIAL, FALSE);
  234. }
  235. CTEMemFree(pAddr);
  236. return (fCancelled);
  237. } // NbtCancelPostConnect
  238. BOOLEAN
  239. NbtAttemptAutoDial(
  240. IN tCONNECTELE *pConnEle,
  241. IN PVOID pTimeout,
  242. IN PTDI_CONNECTION_INFORMATION pCallInfo,
  243. IN PIRP pIrp,
  244. IN ULONG ulFlags,
  245. IN ACD_CONNECT_CALLBACK pProc
  246. )
  247. /*++
  248. Routine Description:
  249. Call the automatic connection driver to attempt an
  250. automatic connection. The first five parameters are
  251. used in the call to NbtConnect after the connection
  252. completes successfully.
  253. Arguments:
  254. ...
  255. ulFlags - automatic connection flags
  256. pProc - callback procedure when the automatic connection completes
  257. Return Value:
  258. TRUE if the automatic connection was started successfully,
  259. FALSE otherwise.
  260. --*/
  261. {
  262. NTSTATUS status;
  263. BOOLEAN fSuccess;
  264. ACD_ADDR *pAddr = NULL;
  265. KIRQL irql;
  266. PVOID pArgs[4];
  267. PCHAR pName;
  268. ULONG ulcbName;
  269. LONG lNameType;
  270. TDI_ADDRESS_NETBT_INTERNAL TdiAddr;
  271. PIO_STACK_LOCATION pIrpSp;
  272. ASSERT(pCallInfo);
  273. //
  274. // If this connection has already been through the
  275. // automatic connection process, don't do it again.
  276. //
  277. if ((pConnEle->fAutoConnected)) {
  278. return FALSE;
  279. }
  280. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  281. if (pIrpSp->CompletionRoutine != NbtpConnectCompletionRoutine) {
  282. status = GetNetBiosNameFromTransportAddress((PTRANSPORT_ADDRESS) pCallInfo->RemoteAddress,
  283. pCallInfo->RemoteAddressLength, &TdiAddr);
  284. } else {
  285. ASSERT(((PTRANSPORT_ADDRESS)pCallInfo->RemoteAddress)->Address[0].AddressType == TDI_ADDRESS_TYPE_UNSPEC);
  286. CTEMemCopy(&TdiAddr,
  287. (PTDI_ADDRESS_NETBT_INTERNAL)((PTRANSPORT_ADDRESS)pCallInfo->RemoteAddress)->Address[0].Address,
  288. sizeof(TdiAddr));
  289. status = STATUS_SUCCESS;
  290. }
  291. if (status != STATUS_SUCCESS || (!NBT_REFERENCE_DEVICE (pConnEle->pDeviceContext, REF_DEV_AUTODIAL, FALSE)) ||
  292. (!(pAddr = (ACD_ADDR *) NbtAllocMem(sizeof(ACD_ADDR),NBT_TAG('A'))))) {
  293. if (pAddr) {
  294. CTEMemFree(pAddr);
  295. }
  296. return FALSE;
  297. }
  298. pName = TdiAddr.OEMRemoteName.Buffer;
  299. ulcbName = TdiAddr.OEMRemoteName.Length;
  300. lNameType = TdiAddr.NameType;
  301. //
  302. // Save the address for pre-connect attempts,
  303. // because if we have to cancel this irp,
  304. // it is not saved anywhere else.
  305. //
  306. CTESpinLock(pConnEle, irql);
  307. pConnEle->fAutoConnecting = TRUE;
  308. CTEMemCopy(pConnEle->RemoteName, pName, NETBIOS_NAME_SIZE);
  309. CTESpinFree(pConnEle, irql);
  310. pAddr->fType = ACD_ADDR_NB;
  311. RtlCopyMemory(&pAddr->cNetbios, pName, NETBIOS_NAME_SIZE);
  312. IF_DBG(NBT_DEBUG_NAME)
  313. KdPrint(("Nbt.NbtAttemptAutodial: szAddr=%-15.15s\n", pName));
  314. //
  315. // Enqueue this request on the network
  316. // connection pending queue.
  317. //
  318. pArgs[0] = pConnEle;
  319. pArgs[1] = pTimeout;
  320. pArgs[2] = pCallInfo;
  321. pArgs[3] = pIrp;
  322. fSuccess = (*AcdDriverG.lpfnStartConnection) (ulDriverIdG, pAddr, ulFlags, pProc, 4, pArgs);
  323. //
  324. // If fSuccess is TRUE, then it means that the NetBT proc has
  325. // already been called to setup the connection, and hence the
  326. // data in pConnEle may not be valid now
  327. //
  328. // In the case it is FALSE, then pProc has not been called, and
  329. // we should set the fAutoConnecting flag to FALSE also
  330. //
  331. if (!fSuccess)
  332. {
  333. NBT_DEREFERENCE_DEVICE (pConnEle->pDeviceContext, REF_DEV_AUTODIAL, FALSE);
  334. CTESpinLock(pConnEle, irql);
  335. pConnEle->fAutoConnecting = FALSE;
  336. CTESpinFree(pConnEle, irql);
  337. }
  338. CTEMemFree(pAddr);
  339. return fSuccess;
  340. } // NbtAttemptAutoDial
  341. VOID
  342. NbtNoteNewConnection(
  343. IN tNAMEADDR *pNameAddr,
  344. IN ULONG IpAddress
  345. )
  346. /*++
  347. Routine Description:
  348. Inform the automatic connection driver of a
  349. successful new connection.
  350. Arguments:
  351. pNameAddr - a pointer to the remote name
  352. IpAddress - Source IP address of the connection
  353. Return Value:
  354. None.
  355. --*/
  356. {
  357. ACD_ADDR *pAddr = NULL;
  358. ACD_ADAPTER *pAdapter = NULL;
  359. //
  360. // Notify the AcdDriver only if we have a valid Source address
  361. //
  362. // We can end up blowing the stack if we pre-allocate ACD_ADDR
  363. // and ACD_ADAPTER on the stack -- so allocate them dynamically!
  364. //
  365. if ((IpAddress) &&
  366. (pAddr = (ACD_ADDR *) NbtAllocMem(sizeof(ACD_ADDR),NBT_TAG('A'))) &&
  367. (pAdapter = (ACD_ADAPTER *) NbtAllocMem(sizeof(ACD_ADAPTER),NBT_TAG('A'))))
  368. {
  369. pAddr->fType = ACD_ADDR_NB;
  370. RtlCopyMemory(&pAddr->cNetbios, pNameAddr->Name, 15);
  371. pAdapter->fType = ACD_ADAPTER_IP;
  372. pAdapter->ulIpaddr = htonl(IpAddress); // Get the source IP address of the connection.
  373. (*AcdDriverG.lpfnNewConnection) (pAddr, pAdapter);
  374. }
  375. if (pAddr)
  376. {
  377. CTEMemFree(pAddr);
  378. }
  379. if (pAdapter)
  380. {
  381. CTEMemFree(pAdapter);
  382. }
  383. } // NbtNoteNewConnection
  384. VOID
  385. NbtAcdBind()
  386. {
  387. NTSTATUS status;
  388. UNICODE_STRING nameString;
  389. IO_STATUS_BLOCK ioStatusBlock;
  390. PIRP pIrp;
  391. PFILE_OBJECT pAcdFileObject;
  392. PDEVICE_OBJECT pAcdDeviceObject;
  393. PACD_DRIVER pDriver = &AcdDriverG;
  394. //
  395. // Initialize the name of the automatic
  396. // connection device.
  397. //
  398. RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME);
  399. //
  400. // Get the file and device objects for the
  401. // device.
  402. //
  403. status = IoGetDeviceObjectPointer(
  404. &nameString,
  405. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  406. &pAcdFileObject,
  407. &pAcdDeviceObject);
  408. if (status != STATUS_SUCCESS)
  409. return;
  410. //
  411. // Reference the device object.
  412. //
  413. ObReferenceObject(pAcdDeviceObject);
  414. //
  415. // Remove the reference IoGetDeviceObjectPointer()
  416. // put on the file object.
  417. //
  418. ObDereferenceObject(pAcdFileObject);
  419. //
  420. // Initialize our part of the ACD_DRIVER
  421. // structure.
  422. //
  423. KeInitializeSpinLock(&AcdDriverG.SpinLock);
  424. AcdDriverG.ulDriverId = ulDriverIdG;
  425. AcdDriverG.fEnabled = FALSE;
  426. //
  427. // Build a request to get the automatic
  428. // connection driver entry points.
  429. //
  430. pIrp = IoBuildDeviceIoControlRequest (IOCTL_INTERNAL_ACD_BIND,
  431. pAcdDeviceObject,
  432. (PVOID)&pDriver,
  433. sizeof (pDriver),
  434. NULL,
  435. 0,
  436. TRUE,
  437. NULL,
  438. &ioStatusBlock);
  439. if (pIrp == NULL)
  440. {
  441. ObDereferenceObject(pAcdDeviceObject);
  442. return;
  443. }
  444. //
  445. // Submit the request to the
  446. // automatic connection driver.
  447. //
  448. status = IoCallDriver(pAcdDeviceObject, pIrp);
  449. fAcdLoadedG = (status == STATUS_SUCCESS);
  450. //
  451. // Close the device.
  452. //
  453. ObDereferenceObject(pAcdDeviceObject);
  454. } // NbtAcdBind
  455. VOID
  456. NbtAcdUnbind()
  457. {
  458. NTSTATUS status;
  459. UNICODE_STRING nameString;
  460. IO_STATUS_BLOCK ioStatusBlock;
  461. PIRP pIrp;
  462. PFILE_OBJECT pAcdFileObject;
  463. PDEVICE_OBJECT pAcdDeviceObject;
  464. PACD_DRIVER pDriver = &AcdDriverG;
  465. //
  466. // Don't bother to unbind if we
  467. // didn't successfully bind in the
  468. // first place.
  469. //
  470. if (!fAcdLoadedG)
  471. {
  472. return;
  473. }
  474. fAcdLoadedG = FALSE;
  475. //
  476. // Initialize the name of the automatic
  477. // connection device.
  478. //
  479. RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME);
  480. //
  481. // Get the file and device objects for the
  482. // device.
  483. //
  484. status = IoGetDeviceObjectPointer (&nameString,
  485. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  486. &pAcdFileObject,
  487. &pAcdDeviceObject);
  488. if (status != STATUS_SUCCESS)
  489. {
  490. return;
  491. }
  492. //
  493. // Reference the device object.
  494. //
  495. ObReferenceObject(pAcdDeviceObject);
  496. //
  497. // Remove the reference IoGetDeviceObjectPointer()
  498. // put on the file object.
  499. //
  500. ObDereferenceObject(pAcdFileObject);
  501. //
  502. // Build a request to unbind from
  503. // the automatic connection driver.
  504. //
  505. pIrp = IoBuildDeviceIoControlRequest (IOCTL_INTERNAL_ACD_UNBIND,
  506. pAcdDeviceObject,
  507. (PVOID)&pDriver,
  508. sizeof (pDriver),
  509. NULL,
  510. 0,
  511. TRUE,
  512. NULL,
  513. &ioStatusBlock);
  514. if (pIrp == NULL)
  515. {
  516. ObDereferenceObject(pAcdDeviceObject);
  517. return;
  518. }
  519. //
  520. // Submit the request to the
  521. // automatic connection driver.
  522. //
  523. status = IoCallDriver(pAcdDeviceObject, pIrp);
  524. //
  525. // Close the device.
  526. //
  527. ObDereferenceObject(pAcdDeviceObject);
  528. } // NbtAcdUnbind
  529. #endif // RASAUTODIAL