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.

3406 lines
80 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. atktdi.c
  5. Abstract:
  6. This module contains the code providing the tdi interface.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com)
  9. Nikhil Kamkolkar (nikhilk@microsoft.com)
  10. Revision History:
  11. 19 Jun 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #include <atalk.h>
  15. #pragma hdrstop
  16. #define FILENUM ATKTDI
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(INIT, AtalkLockInit)
  19. #pragma alloc_text(PAGE, AtalkTdiOpenAddress)
  20. #pragma alloc_text(PAGE, AtalkTdiOpenConnection)
  21. //#pragma alloc_text(PAGE, AtalkTdiOpenControlChannel)
  22. #pragma alloc_text(PAGE, AtalkTdiAction)
  23. #pragma alloc_text(PAGE, atalkQueuedLockUnlock)
  24. #pragma alloc_text(PAGE_TDI, AtalkTdiCleanupAddress)
  25. #pragma alloc_text(PAGE_TDI, AtalkTdiCleanupConnection)
  26. #pragma alloc_text(PAGE_TDI, AtalkTdiCloseAddress)
  27. #pragma alloc_text(PAGE_TDI, AtalkTdiCloseConnection)
  28. #pragma alloc_text(PAGE_TDI, AtalkTdiCloseControlChannel)
  29. #pragma alloc_text(PAGE_TDI, AtalkTdiAssociateAddress)
  30. #pragma alloc_text(PAGE_TDI, AtalkTdiDisassociateAddress)
  31. #pragma alloc_text(PAGE_TDI, AtalkTdiConnect)
  32. #pragma alloc_text(PAGE_TDI, AtalkTdiDisconnect)
  33. #pragma alloc_text(PAGE_TDI, AtalkTdiAccept)
  34. #pragma alloc_text(PAGE_TDI, AtalkTdiListen)
  35. #pragma alloc_text(PAGE_TDI, AtalkTdiSend)
  36. #pragma alloc_text(PAGE_TDI, AtalkTdiSendDgram)
  37. #pragma alloc_text(PAGE_TDI, AtalkTdiReceive)
  38. #pragma alloc_text(PAGE_TDI, AtalkTdiReceiveDgram)
  39. #pragma alloc_text(PAGE_TDI, AtalkTdiQueryInformation)
  40. #pragma alloc_text(PAGE_TDI, AtalkTdiSetInformation)
  41. #pragma alloc_text(PAGE_TDI, AtalkTdiSetEventHandler)
  42. #pragma alloc_text(PAGE_TDI, AtalkTdiCancel)
  43. #pragma alloc_text(PAGE_TDI, AtalkQueryInitProviderInfo)
  44. #pragma alloc_text(PAGE_TDI, atalkTdiActionComplete)
  45. #pragma alloc_text(PAGE_TDI, atalkTdiGenericComplete)
  46. #pragma alloc_text(PAGE_TDI, atalkTdiGenericReadComplete)
  47. #pragma alloc_text(PAGE_TDI, atalkTdiGenericWriteComplete)
  48. #endif
  49. // Primary TDI Functions for appletalk stack
  50. NTSTATUS
  51. AtalkTdiOpenAddress(
  52. IN PIRP pIrp,
  53. IN PIO_STACK_LOCATION pIrpSp,
  54. IN PTA_APPLETALK_ADDRESS pTdiAddr,
  55. IN BYTE ProtoType,
  56. IN BYTE SocketType,
  57. IN OUT PATALK_DEV_CTX pCtx
  58. )
  59. /*++
  60. Routine Description:
  61. This routine is used to create an address object. It will also the
  62. create the appropriate socket with the portable stack.
  63. Arguments:
  64. Return Value:
  65. STATUS_SUCCESS if address was successfully opened
  66. Error otherwise.
  67. --*/
  68. {
  69. PVOID FsContext;
  70. ATALK_ADDR atalkAddr;
  71. ATALK_ERROR error;
  72. do
  73. {
  74. atalkWaitDefaultPort();
  75. // We honor only if count/type and length are as we expect. And only if the
  76. // default port is valid.
  77. if ((AtalkDefaultPort == NULL) ||
  78. (AtalkDefaultPort->pd_Flags & PD_PNP_RECONFIGURE) ||
  79. (pTdiAddr->TAAddressCount != 1) ||
  80. (pTdiAddr->Address[0].AddressLength < sizeof(TDI_ADDRESS_APPLETALK)) ||
  81. (pTdiAddr->Address[0].AddressType != TDI_ADDRESS_TYPE_APPLETALK))
  82. {
  83. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  84. ("AtalkTdiOpenAddress: returning STATUS_INVALID_ADDRESS (%lx)\n",AtalkDefaultPort));
  85. error = ATALK_NEW_SOCKET; // maps to STATUS_INVALID_ADDRESS
  86. break;
  87. }
  88. TDI_TO_ATALKADDR(&atalkAddr, pTdiAddr);
  89. // Now depending on the requested device...
  90. switch (pCtx->adc_DevType)
  91. {
  92. case ATALK_DEV_DDP:
  93. error = AtalkDdpOpenAddress(AtalkDefaultPort,
  94. atalkAddr.ata_Socket,
  95. NULL, // Desired node (any node)
  96. NULL, // NULL Socket Handler
  97. NULL, // Context for handler
  98. ProtoType,
  99. pCtx,
  100. (PDDP_ADDROBJ *)(&FsContext));
  101. break;
  102. case ATALK_DEV_ASPC:
  103. AtalkLockAspCIfNecessary();
  104. error = AtalkAspCCreateAddress(pCtx, (PASPC_ADDROBJ *)(&FsContext));
  105. break;
  106. case ATALK_DEV_ASP:
  107. AtalkLockAspIfNecessary();
  108. error = AtalkAspCreateAddress((PASP_ADDROBJ *)(&FsContext));
  109. break;
  110. case ATALK_DEV_PAP:
  111. AtalkLockPapIfNecessary();
  112. error = AtalkPapCreateAddress(pCtx, (PPAP_ADDROBJ *)(&FsContext));
  113. break;
  114. case ATALK_DEV_ADSP:
  115. AtalkLockAdspIfNecessary();
  116. error = AtalkAdspCreateAddress(pCtx,
  117. SocketType,
  118. (PADSP_ADDROBJ *)(&FsContext));
  119. break;
  120. default:
  121. // The device type in the Ctx field can never be anything
  122. // other than the above! Internal protocol error. KeBugCheck.
  123. error = ATALK_INVALID_REQUEST;
  124. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  125. ("AtalkTdiOpenAddress: Invalid device type\n"));
  126. break;
  127. }
  128. if (ATALK_SUCCESS(error))
  129. {
  130. pIrpSp->FileObject->FsContext2 =
  131. (PVOID)((ULONG_PTR)(TDI_TRANSPORT_ADDRESS_FILE + (pCtx->adc_DevType << 16)));
  132. pIrpSp->FileObject->FsContext = FsContext;
  133. AtalkLockTdiIfNecessary();
  134. }
  135. } while (FALSE);
  136. return AtalkErrorToNtStatus(error);
  137. }
  138. NTSTATUS
  139. AtalkTdiOpenConnection(
  140. IN PIRP pIrp,
  141. IN PIO_STACK_LOCATION pIrpSp,
  142. IN CONNECTION_CONTEXT ConnCtx,
  143. IN OUT PATALK_DEV_CTX pCtx
  144. )
  145. /*++
  146. Routine Description:
  147. This routine is used to create a connection object and associate the
  148. passed ConnectionContext with it.
  149. Arguments:
  150. ConnectionContext - The TDI ConnectionContext to be associated with object
  151. Context - The DeviceContext of the device on which open is happening
  152. Return Value:
  153. STATUS_SUCCESS if connection was successfully opened
  154. Error otherwise.
  155. --*/
  156. {
  157. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  158. PVOID FsContext;
  159. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  160. (pCtx->adc_DevType == ATALK_DEV_ADSP)||
  161. (pCtx->adc_DevType == ATALK_DEV_ASPC))
  162. do
  163. {
  164. atalkWaitDefaultPort();
  165. // Only if the default port is valid.
  166. if (AtalkDefaultPort == NULL)
  167. {
  168. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  169. ("AtalkTdiOpenConnection: returning STATUS_INVALID_ADDRESS\n"));
  170. error = ATALK_NEW_SOCKET; // maps to STATUS_INVALID_ADDRESS
  171. break;
  172. }
  173. // Now depending on the requested device...
  174. switch (pCtx->adc_DevType)
  175. {
  176. case ATALK_DEV_PAP:
  177. AtalkLockPapIfNecessary();
  178. error = AtalkPapCreateConnection(ConnCtx,
  179. pCtx,
  180. (PPAP_CONNOBJ *)(&FsContext));
  181. break;
  182. case ATALK_DEV_ADSP:
  183. AtalkLockAdspIfNecessary();
  184. error = AtalkAdspCreateConnection(ConnCtx,
  185. pCtx,
  186. (PADSP_CONNOBJ *)(&FsContext));
  187. break;
  188. case ATALK_DEV_ASPC:
  189. AtalkLockAspCIfNecessary();
  190. error = AtalkAspCCreateConnection(ConnCtx,
  191. pCtx,
  192. (PASPC_CONNOBJ *)(&FsContext));
  193. break;
  194. }
  195. if (ATALK_SUCCESS(error))
  196. {
  197. pIrpSp->FileObject->FsContext2 = (PVOID)((ULONG_PTR)(TDI_CONNECTION_FILE +
  198. (pCtx->adc_DevType << 16)));
  199. pIrpSp->FileObject->FsContext = FsContext;
  200. AtalkLockTdiIfNecessary();
  201. }
  202. ASSERT(error == ATALK_NO_ERROR);
  203. } while (FALSE);
  204. return AtalkErrorToNtStatus(error);
  205. }
  206. NTSTATUS
  207. AtalkTdiOpenControlChannel(
  208. IN PIRP pIrp,
  209. IN PIO_STACK_LOCATION pIrpSp,
  210. IN OUT PATALK_DEV_CTX pCtx
  211. )
  212. /*++
  213. Routine Description:
  214. This routine is used to create a control channel
  215. Arguments:
  216. Context - The DeviceContext of the device on which open is happening
  217. Return Value:
  218. STATUS_SUCCESS if controlchannel was successfully opened
  219. Error otherwise.
  220. --*/
  221. {
  222. PDDP_ADDROBJ pDdpAddr;
  223. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  224. KIRQL OldIrql;
  225. do
  226. {
  227. if (pCtx->adc_DevType != ATALK_DEV_ARAP)
  228. {
  229. atalkWaitDefaultPort();
  230. // Only if the default port is valid.
  231. if (AtalkDefaultPort == NULL)
  232. {
  233. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  234. ("AtalkTdiOpenControlChannel: NOT ATALK_DEV_ARAP: returning STATUS_INVALID_ADDRESS\n"));
  235. if (!AtalkNoDefPortPrinted)
  236. {
  237. LOG_ERROR(EVENT_ATALK_NO_DEFAULTPORT, 0, NULL, 0);
  238. AtalkNoDefPortPrinted = TRUE;
  239. }
  240. error = ATALK_NEW_SOCKET; // maps to STATUS_INVALID_ADDRESS
  241. break;
  242. }
  243. }
  244. // Now depending on the requested device...
  245. switch (pCtx->adc_DevType)
  246. {
  247. case ATALK_DEV_DDP:
  248. case ATALK_DEV_ASP:
  249. case ATALK_DEV_PAP:
  250. case ATALK_DEV_ADSP:
  251. case ATALK_DEV_ASPC:
  252. error = AtalkDdpOpenAddress(AtalkDefaultPort,
  253. UNKNOWN_SOCKET,
  254. NULL,
  255. NULL,
  256. NULL,
  257. 0,
  258. pCtx,
  259. &pDdpAddr);
  260. break;
  261. case ATALK_DEV_ARAP:
  262. if (AtalkDefaultPort == NULL)
  263. {
  264. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  265. ("AtalkTdiOpenControlChannel: device is ATALK_DEV_ARAP: returning STATUS_INVALID_ADDRESS\n"));
  266. if (!AtalkNoDefPortPrinted)
  267. {
  268. LOG_ERROR(EVENT_ATALK_NO_DEFAULTPORT, 0, NULL, 0);
  269. AtalkNoDefPortPrinted = TRUE;
  270. }
  271. error = ATALK_NEW_SOCKET; // maps to STATUS_INVALID_ADDRESS
  272. break;
  273. }
  274. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,("RAS device opened\n"));
  275. #if DBG
  276. KeQuerySystemTime(&ArapDbgLastTraceTime);
  277. #endif
  278. error = ATALK_NO_ERROR;
  279. break;
  280. default:
  281. // The device type in the Ctx field can never be anything
  282. // other than the above! Internal protocol error. KeBugCheck.
  283. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  284. ("AtalkTdiOpenControlChannel: Invalid device type\n"));
  285. break;
  286. }
  287. if (ATALK_SUCCESS(error))
  288. {
  289. pIrpSp->FileObject->FsContext2 =
  290. (PVOID)((ULONG_PTR)(TDI_CONTROL_CHANNEL_FILE + (pCtx->adc_DevType << 16)));
  291. pIrpSp->FileObject->FsContext = pDdpAddr;
  292. AtalkLockTdiIfNecessary();
  293. }
  294. else
  295. {
  296. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  297. ("AtalkTdiOpenControlChannel: Failed %ld\n", error));
  298. }
  299. } while (FALSE);
  300. return AtalkErrorToNtStatus(error);
  301. }
  302. NTSTATUS
  303. AtalkTdiCleanupAddress(
  304. IN PIRP pIrp,
  305. IN PIO_STACK_LOCATION pIrpSp,
  306. IN OUT PATALK_DEV_CTX pCtx
  307. )
  308. /*++
  309. Routine Description:
  310. This routine removes the creation reference on the object. It also
  311. sets up the closepIrp for completion.
  312. Arguments:
  313. pIrp - The close irp
  314. Context - The DeviceContext of the device on which close is happening
  315. Return Value:
  316. STATUS_SUCCESS if successfully setup
  317. Error otherwise.
  318. --*/
  319. {
  320. ATALK_ERROR error;
  321. PVOID pAddrObj = pIrpSp->FileObject->FsContext;
  322. do
  323. {
  324. // Now depending on the requested device...
  325. switch (pCtx->adc_DevType)
  326. {
  327. case ATALK_DEV_DDP:
  328. if (!(VALID_DDP_ADDROBJ(((PDDP_ADDROBJ)pAddrObj))))
  329. {
  330. ASSERT(0);
  331. error = ATALK_INVALID_ADDRESS;
  332. break;
  333. }
  334. AtalkDdpReferenceByPtr(((PDDP_ADDROBJ)pAddrObj), &error);
  335. if (ATALK_SUCCESS(error))
  336. {
  337. AtalkDdpCleanupAddress((PDDP_ADDROBJ)pAddrObj);
  338. AtalkDdpDereference(((PDDP_ADDROBJ)pAddrObj));
  339. }
  340. break;
  341. case ATALK_DEV_ASPC:
  342. if (!(VALID_ASPCAO((PASPC_ADDROBJ)pAddrObj)))
  343. {
  344. ASSERT(0);
  345. error = ATALK_INVALID_ADDRESS;
  346. break;
  347. }
  348. AtalkLockAspCIfNecessary();
  349. AtalkAspCAddrReference((PASPC_ADDROBJ)pAddrObj, &error);
  350. if (ATALK_SUCCESS(error))
  351. {
  352. AtalkAspCCleanupAddress((PASPC_ADDROBJ)pAddrObj);
  353. AtalkAspCAddrDereference((PASPC_ADDROBJ)pAddrObj);
  354. }
  355. AtalkUnlockAspCIfNecessary();
  356. break;
  357. case ATALK_DEV_ASP:
  358. error = ATALK_NO_ERROR;
  359. break;
  360. case ATALK_DEV_PAP:
  361. if (!(VALID_PAPAO((PPAP_ADDROBJ)pAddrObj)))
  362. {
  363. ASSERT(0);
  364. error = ATALK_INVALID_ADDRESS;
  365. break;
  366. }
  367. AtalkLockPapIfNecessary();
  368. AtalkPapAddrReference((PPAP_ADDROBJ)pAddrObj, &error);
  369. if (ATALK_SUCCESS(error))
  370. {
  371. AtalkPapCleanupAddress((PPAP_ADDROBJ)pAddrObj);
  372. AtalkPapAddrDereference((PPAP_ADDROBJ)pAddrObj);
  373. }
  374. AtalkUnlockPapIfNecessary();
  375. break;
  376. case ATALK_DEV_ADSP:
  377. if (!(VALID_ADSPAO((PADSP_ADDROBJ)pAddrObj)))
  378. {
  379. ASSERT(0);
  380. error = ATALK_INVALID_ADDRESS;
  381. break;
  382. }
  383. AtalkLockAdspIfNecessary();
  384. AtalkAdspAddrReference((PADSP_ADDROBJ)pAddrObj, &error);
  385. if (ATALK_SUCCESS(error))
  386. {
  387. AtalkAdspCleanupAddress((PADSP_ADDROBJ)pAddrObj);
  388. AtalkAdspAddrDereference((PADSP_ADDROBJ)pAddrObj);
  389. }
  390. AtalkUnlockAdspIfNecessary();
  391. break;
  392. default:
  393. // The device type in the Ctx field can never be anything
  394. // other than the above! Internal protocol error. KeBugCheck.
  395. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  396. ("AtalkTdiCleanupAddress: Invalid device type\n"));
  397. error = ATALK_INVALID_REQUEST;
  398. break;
  399. }
  400. } while (FALSE);
  401. return AtalkErrorToNtStatus(error);
  402. }
  403. NTSTATUS
  404. AtalkTdiCleanupConnection(
  405. IN PIRP pIrp,
  406. IN PIO_STACK_LOCATION pIrpSp,
  407. IN OUT PATALK_DEV_CTX pCtx
  408. )
  409. /*++
  410. Routine Description:
  411. This routine removes the creation reference on the object. It also
  412. sets up the closepIrp for completion.
  413. Arguments:
  414. pIrp - The close irp
  415. Context - The DeviceContext of the device on which close is happening
  416. Return Value:
  417. STATUS_SUCCESS if successfully setup
  418. Error otherwise.
  419. --*/
  420. {
  421. ATALK_ERROR error;
  422. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  423. do
  424. {
  425. // Now depending on the requested device...
  426. switch (pCtx->adc_DevType)
  427. {
  428. case ATALK_DEV_PAP:
  429. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  430. {
  431. ASSERT(0);
  432. error = ATALK_INVALID_CONNECTION;
  433. break;
  434. }
  435. AtalkLockPapIfNecessary();
  436. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  437. if (ATALK_SUCCESS(error))
  438. {
  439. // No need to have lock as we have a reference.
  440. ((PPAP_CONNOBJ)pConnObj)->papco_CleanupComp = atalkTdiGenericComplete;
  441. ((PPAP_CONNOBJ)pConnObj)->papco_CleanupCtx = pIrp;
  442. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  443. ("AtalkTdiCleanupConnection: Cleanup %lx.%lx\n",
  444. pConnObj, pIrp));
  445. AtalkPapCleanupConnection((PPAP_CONNOBJ)pConnObj);
  446. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  447. error = ATALK_PENDING;
  448. }
  449. AtalkUnlockPapIfNecessary();
  450. break;
  451. case ATALK_DEV_ADSP:
  452. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  453. {
  454. ASSERT(0);
  455. error = ATALK_INVALID_CONNECTION;
  456. break;
  457. }
  458. AtalkLockAdspIfNecessary();
  459. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  460. if (ATALK_SUCCESS(error))
  461. {
  462. // No need to have lock as we have a reference.
  463. ((PADSP_CONNOBJ)pConnObj)->adspco_CleanupComp = atalkTdiGenericComplete;
  464. ((PADSP_CONNOBJ)pConnObj)->adspco_CleanupCtx = pIrp;
  465. AtalkAdspCleanupConnection((PADSP_CONNOBJ)pConnObj);
  466. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  467. error = ATALK_PENDING;
  468. }
  469. AtalkUnlockAdspIfNecessary();
  470. break;
  471. case ATALK_DEV_ASPC:
  472. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  473. {
  474. ASSERT(0);
  475. error = ATALK_INVALID_CONNECTION;
  476. break;
  477. }
  478. AtalkLockAspCIfNecessary();
  479. AtalkAspCConnReference((PASPC_CONNOBJ)pConnObj, &error);
  480. if (ATALK_SUCCESS(error))
  481. {
  482. // No need to have lock as we have a reference.
  483. ((PASPC_CONNOBJ)pConnObj)->aspcco_CleanupComp = atalkTdiGenericComplete;
  484. ((PASPC_CONNOBJ)pConnObj)->aspcco_CleanupCtx = pIrp;
  485. AtalkAspCCleanupConnection((PASPC_CONNOBJ)pConnObj);
  486. AtalkAspCConnDereference((PASPC_CONNOBJ)pConnObj);
  487. error = ATALK_PENDING;
  488. }
  489. AtalkUnlockAspCIfNecessary();
  490. break;
  491. case ATALK_DEV_DDP:
  492. default:
  493. // The device type in the Ctx field can never be anything
  494. // other than the above! Internal protocol error. KeBugCheck.
  495. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  496. ("AtalkTdiCleanupConnection: Invalid device type\n"));
  497. error = ATALK_INVALID_REQUEST;
  498. break;
  499. }
  500. } while (FALSE);
  501. return AtalkErrorToNtStatus(error);
  502. }
  503. NTSTATUS
  504. AtalkTdiCloseAddress(
  505. IN PIRP pIrp,
  506. IN PIO_STACK_LOCATION pIrpSp,
  507. IN OUT PATALK_DEV_CTX pCtx
  508. )
  509. /*++
  510. Routine Description:
  511. This routine removes the creation reference on the object. It also
  512. sets up the closepIrp for completion.
  513. Arguments:
  514. pIrp - The close irp
  515. Context - The DeviceContext of the device on which close is happening
  516. Return Value:
  517. STATUS_SUCCESS if successfully setup
  518. Error otherwise.
  519. --*/
  520. {
  521. ATALK_ERROR error;
  522. PVOID pAddrObj = pIrpSp->FileObject->FsContext;
  523. do
  524. {
  525. // Now depending on the requested device...
  526. switch (pCtx->adc_DevType)
  527. {
  528. case ATALK_DEV_DDP:
  529. if (!(VALID_DDP_ADDROBJ(((PDDP_ADDROBJ)pAddrObj))))
  530. {
  531. ASSERT(0);
  532. error = ATALK_INVALID_ADDRESS;
  533. break;
  534. }
  535. AtalkDdpReferenceByPtr(((PDDP_ADDROBJ)pAddrObj), &error);
  536. if (ATALK_SUCCESS(error))
  537. {
  538. error = AtalkDdpCloseAddress((PDDP_ADDROBJ)pAddrObj,
  539. atalkTdiCloseAddressComplete,
  540. pIrp);
  541. AtalkDdpDereference(((PDDP_ADDROBJ)pAddrObj));
  542. }
  543. break;
  544. case ATALK_DEV_ASPC:
  545. if (!(VALID_ASPCAO((PASPC_ADDROBJ)pAddrObj)))
  546. {
  547. ASSERT(0);
  548. error = ATALK_INVALID_ADDRESS;
  549. break;
  550. }
  551. AtalkAspCAddrReference((PASPC_ADDROBJ)pAddrObj, &error);
  552. if (ATALK_SUCCESS(error))
  553. {
  554. error = AtalkAspCCloseAddress((PASPC_ADDROBJ)pAddrObj,
  555. atalkTdiCloseAddressComplete,
  556. pIrp);
  557. AtalkAspCAddrDereference((PASPC_ADDROBJ)pAddrObj);
  558. }
  559. break;
  560. case ATALK_DEV_ASP:
  561. if (!(VALID_ASPAO((PASP_ADDROBJ)pAddrObj)))
  562. {
  563. ASSERT(0);
  564. error = ATALK_INVALID_ADDRESS;
  565. break;
  566. }
  567. if (AtalkAspReferenceAddr((PASP_ADDROBJ)pAddrObj) != NULL)
  568. {
  569. error = AtalkAspCloseAddress((PASP_ADDROBJ)pAddrObj,
  570. atalkTdiCloseAddressComplete,
  571. pIrp);
  572. AtalkAspDereferenceAddr((PASP_ADDROBJ)pAddrObj);
  573. }
  574. break;
  575. case ATALK_DEV_PAP:
  576. if (!(VALID_PAPAO((PPAP_ADDROBJ)pAddrObj)))
  577. {
  578. ASSERT(0);
  579. error = ATALK_INVALID_ADDRESS;
  580. break;
  581. }
  582. AtalkPapAddrReference((PPAP_ADDROBJ)pAddrObj, &error);
  583. if (ATALK_SUCCESS(error))
  584. {
  585. error = AtalkPapCloseAddress((PPAP_ADDROBJ)pAddrObj,
  586. atalkTdiCloseAddressComplete,
  587. pIrp);
  588. AtalkPapAddrDereference((PPAP_ADDROBJ)pAddrObj);
  589. }
  590. break;
  591. case ATALK_DEV_ADSP:
  592. if (!(VALID_ADSPAO((PADSP_ADDROBJ)pAddrObj)))
  593. {
  594. ASSERT(0);
  595. error = ATALK_INVALID_ADDRESS;
  596. break;
  597. }
  598. AtalkAdspAddrReference((PADSP_ADDROBJ)pAddrObj, &error);
  599. if (ATALK_SUCCESS(error))
  600. {
  601. error = AtalkAdspCloseAddress((PADSP_ADDROBJ)pAddrObj,
  602. atalkTdiCloseAddressComplete,
  603. pIrp);
  604. AtalkAdspAddrDereference((PADSP_ADDROBJ)pAddrObj);
  605. }
  606. break;
  607. default:
  608. // The device type in the Ctx field can never be anything
  609. // other than the above! Internal protocol error. KeBugCheck.
  610. error = ATALK_INVALID_REQUEST;
  611. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  612. ("AtalkTdiCloseAddress: Invalid device type\n"));
  613. break;
  614. }
  615. } while (FALSE);
  616. if (error == ATALK_NO_ERROR)
  617. error = ATALK_PENDING;
  618. return AtalkErrorToNtStatus(error);
  619. }
  620. NTSTATUS
  621. AtalkTdiCloseConnection(
  622. IN PIRP pIrp,
  623. IN PIO_STACK_LOCATION pIrpSp,
  624. IN OUT PATALK_DEV_CTX pCtx
  625. )
  626. /*++
  627. Routine Description:
  628. This routine removes the creation reference on the object. It also
  629. sets up the closepIrp for completion.
  630. Arguments:
  631. pIrp - The close irp
  632. Context - The DeviceContext of the device on which close is happening
  633. Return Value:
  634. STATUS_SUCCESS if successfully setup
  635. Error otherwise.
  636. --*/
  637. {
  638. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  639. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  640. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  641. (pCtx->adc_DevType == ATALK_DEV_ADSP)||
  642. (pCtx->adc_DevType == ATALK_DEV_ASPC))
  643. do
  644. {
  645. // Now depending on the requested device...
  646. switch (pCtx->adc_DevType)
  647. {
  648. case ATALK_DEV_PAP:
  649. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  650. {
  651. ASSERT(0);
  652. error = ATALK_INVALID_CONNECTION;
  653. break;
  654. }
  655. AtalkLockPapIfNecessary();
  656. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  657. if (ATALK_SUCCESS(error))
  658. {
  659. error = AtalkPapCloseConnection((PPAP_CONNOBJ)pConnObj,
  660. atalkTdiCloseAddressComplete,
  661. pIrp);
  662. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  663. }
  664. AtalkUnlockPapIfNecessary();
  665. break;
  666. case ATALK_DEV_ADSP:
  667. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  668. {
  669. ASSERT(0);
  670. error = ATALK_INVALID_CONNECTION;
  671. break;
  672. }
  673. AtalkLockAdspIfNecessary();
  674. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  675. if (ATALK_SUCCESS(error))
  676. {
  677. error = AtalkAdspCloseConnection((PADSP_CONNOBJ)pConnObj,
  678. atalkTdiCloseAddressComplete,
  679. pIrp);
  680. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  681. }
  682. AtalkUnlockAdspIfNecessary();
  683. break;
  684. case ATALK_DEV_ASPC:
  685. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  686. {
  687. ASSERT(0);
  688. error = ATALK_INVALID_CONNECTION;
  689. break;
  690. }
  691. AtalkLockAspCIfNecessary();
  692. if (!AtalkAspCConnectionIsValid((PASPC_CONNOBJ)pConnObj))
  693. {
  694. error = ATALK_INVALID_CONNECTION;
  695. AtalkUnlockAspCIfNecessary();
  696. break;
  697. }
  698. AtalkAspCConnReference((PASPC_CONNOBJ)pConnObj, &error);
  699. if (ATALK_SUCCESS(error))
  700. {
  701. error = AtalkAspCCloseConnection((PASPC_CONNOBJ)pConnObj,
  702. atalkTdiCloseAddressComplete,
  703. pIrp);
  704. AtalkAspCConnDereference((PASPC_CONNOBJ)pConnObj);
  705. }
  706. AtalkUnlockAspCIfNecessary();
  707. break;
  708. }
  709. } while (FALSE);
  710. if (error == ATALK_NO_ERROR)
  711. error = ATALK_PENDING;
  712. return AtalkErrorToNtStatus(error);
  713. }
  714. NTSTATUS
  715. AtalkTdiCloseControlChannel(
  716. IN PIRP pIrp,
  717. IN PIO_STACK_LOCATION pIrpSp,
  718. IN OUT PATALK_DEV_CTX pCtx
  719. )
  720. /*++
  721. Routine Description:
  722. This routine removes the creation reference on the object. It also
  723. sets up the closepIrp for completion.
  724. Arguments:
  725. pIrp - The close irp
  726. Context - The DeviceContext of the device on which close is happening
  727. Return Value:
  728. STATUS_SUCCESS if successfully setup
  729. Error otherwise.
  730. --*/
  731. {
  732. ATALK_ERROR error;
  733. PVOID pCtrlChnl = pIrpSp->FileObject->FsContext;
  734. KIRQL OldIrql;
  735. if (pCtx->adc_DevType == ATALK_DEV_ARAP)
  736. {
  737. ArapReleaseResources();
  738. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  739. ("AtalkTdiCloseAddress: RAS device closed\n"));
  740. // flip the state, so if engine restarts, we tell the engine
  741. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  742. if (ArapStackState == ARAP_STATE_ACTIVE)
  743. {
  744. ArapStackState = ARAP_STATE_ACTIVE_WAITING;
  745. }
  746. else if (ArapStackState == ARAP_STATE_INACTIVE)
  747. {
  748. ArapStackState = ARAP_STATE_INACTIVE_WAITING;
  749. }
  750. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  751. AtalkUnlockTdiIfNecessary();
  752. return(STATUS_SUCCESS);
  753. }
  754. if (!(VALID_DDP_ADDROBJ((PDDP_ADDROBJ)pCtrlChnl)))
  755. {
  756. ASSERT(0);
  757. error = ATALK_INVALID_ADDRESS;
  758. return AtalkErrorToNtStatus(error);
  759. }
  760. AtalkDdpReferenceByPtr(((PDDP_ADDROBJ)pCtrlChnl), &error);
  761. if (ATALK_SUCCESS(error))
  762. {
  763. error = AtalkDdpCloseAddress(((PDDP_ADDROBJ)pCtrlChnl),
  764. atalkTdiCloseAddressComplete,
  765. pIrp);
  766. AtalkDdpDereference(((PDDP_ADDROBJ)pCtrlChnl));
  767. }
  768. return AtalkErrorToNtStatus(error);
  769. }
  770. NTSTATUS
  771. AtalkTdiAssociateAddress(
  772. IN PIRP pIrp,
  773. IN PIO_STACK_LOCATION pIrpSp,
  774. IN OUT PATALK_DEV_CTX pCtx
  775. )
  776. /*++
  777. Routine Description:
  778. This routine will associate the connection object with the specified
  779. address object.
  780. This routine is pretty much provider independent. All we check for is
  781. that the address object and the provider object belong to the same device.
  782. Also, this routine will complete synchronously.
  783. Arguments:
  784. Return Value:
  785. STATUS_SUCCESS if successfully completed
  786. Error otherwise.
  787. --*/
  788. {
  789. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  790. PVOID pAddrObj;
  791. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  792. PFILE_OBJECT pFileObj = NULL;
  793. HANDLE AddrObjHandle =
  794. ((PTDI_REQUEST_KERNEL_ASSOCIATE)(&pIrpSp->Parameters))->AddressHandle;
  795. PDEVICE_OBJECT pDeviceObject;
  796. NTSTATUS status;
  797. DWORD i;
  798. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  799. (pCtx->adc_DevType == ATALK_DEV_ADSP)||
  800. (pCtx->adc_DevType == ATALK_DEV_ASPC))
  801. do
  802. {
  803. // Get the handle to the address object from the irp and map it to
  804. // the corres. file object.
  805. {
  806. status = ObReferenceObjectByHandle(AddrObjHandle,
  807. 0,
  808. *IoFileObjectType,
  809. pIrp->RequestorMode,
  810. (PVOID *)&pFileObj,
  811. NULL);
  812. ASSERT (NT_SUCCESS(status));
  813. if (!NT_SUCCESS(status))
  814. {
  815. return(status);
  816. }
  817. }
  818. pDeviceObject = IoGetRelatedDeviceObject(pFileObj);
  819. status = STATUS_OBJECT_NAME_INVALID;
  820. for (i=0; i < ATALK_NO_DEVICES; i++ )
  821. {
  822. if (pDeviceObject == (PDEVICE_OBJECT)AtalkDeviceObject[i])
  823. {
  824. status = STATUS_SUCCESS;
  825. break;
  826. }
  827. }
  828. if (!NT_SUCCESS(status))
  829. {
  830. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  831. ("AtalkTdiAssociateAddress: wrong devObject %lx\n",pDeviceObject));
  832. ASSERT(0);
  833. return(status);
  834. }
  835. pAddrObj = pFileObj->FsContext;
  836. ASSERT(((LONG_PTR)pFileObj->FsContext2 >> 16) == pCtx->adc_DevType);
  837. switch (pCtx->adc_DevType)
  838. {
  839. case ATALK_DEV_PAP:
  840. if (!(VALID_PAPAO((PPAP_ADDROBJ)pAddrObj)))
  841. {
  842. ASSERT(0);
  843. error = ATALK_INVALID_ADDRESS;
  844. break;
  845. }
  846. AtalkLockPapIfNecessary();
  847. AtalkPapAddrReference((PPAP_ADDROBJ)pAddrObj, &error);
  848. if (ATALK_SUCCESS(error))
  849. {
  850. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  851. {
  852. ASSERT(0);
  853. error = ATALK_INVALID_CONNECTION;
  854. AtalkPapAddrDereference((PPAP_ADDROBJ)pAddrObj);
  855. break;
  856. }
  857. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  858. if (ATALK_SUCCESS(error))
  859. {
  860. error = AtalkPapAssociateAddress((PPAP_ADDROBJ)pAddrObj,
  861. (PPAP_CONNOBJ)pConnObj);
  862. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  863. }
  864. AtalkPapAddrDereference((PPAP_ADDROBJ)pAddrObj);
  865. }
  866. AtalkUnlockPapIfNecessary();
  867. break;
  868. case ATALK_DEV_ADSP:
  869. if (!(VALID_ADSPAO((PADSP_ADDROBJ)pAddrObj)))
  870. {
  871. ASSERT(0);
  872. error = ATALK_INVALID_ADDRESS;
  873. break;
  874. }
  875. AtalkLockAdspIfNecessary();
  876. AtalkAdspAddrReference((PADSP_ADDROBJ)pAddrObj, &error);
  877. if (ATALK_SUCCESS(error))
  878. {
  879. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  880. {
  881. ASSERT(0);
  882. error = ATALK_INVALID_CONNECTION;
  883. AtalkAdspAddrDereference((PADSP_ADDROBJ)pAddrObj);
  884. break;
  885. }
  886. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  887. if (ATALK_SUCCESS(error))
  888. {
  889. error = AtalkAdspAssociateAddress((PADSP_ADDROBJ)pAddrObj,
  890. (PADSP_CONNOBJ)pConnObj);
  891. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  892. }
  893. AtalkAdspAddrDereference((PADSP_ADDROBJ)pAddrObj);
  894. }
  895. AtalkUnlockAdspIfNecessary();
  896. break;
  897. case ATALK_DEV_ASPC:
  898. if (!(VALID_ASPCAO((PASPC_ADDROBJ)pAddrObj)))
  899. {
  900. ASSERT(0);
  901. error = ATALK_INVALID_ADDRESS;
  902. break;
  903. }
  904. AtalkLockAspCIfNecessary();
  905. AtalkAspCAddrReference((PASPC_ADDROBJ)pAddrObj, &error);
  906. if (ATALK_SUCCESS(error))
  907. {
  908. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  909. {
  910. ASSERT(0);
  911. error = ATALK_INVALID_CONNECTION;
  912. AtalkAspCAddrDereference((PASPC_ADDROBJ)pAddrObj);
  913. break;
  914. }
  915. AtalkAspCConnReference((PASPC_CONNOBJ)pConnObj, &error);
  916. if (ATALK_SUCCESS(error))
  917. {
  918. error = AtalkAspCAssociateAddress((PASPC_ADDROBJ)pAddrObj,
  919. (PASPC_CONNOBJ)pConnObj);
  920. AtalkAspCConnDereference((PASPC_CONNOBJ)pConnObj);
  921. }
  922. AtalkAspCAddrDereference((PASPC_ADDROBJ)pAddrObj);
  923. }
  924. AtalkUnlockAspCIfNecessary();
  925. break;
  926. }
  927. // Dereference the file object corres. to the address object
  928. ObDereferenceObject(pFileObj);
  929. } while (FALSE);
  930. return AtalkErrorToNtStatus(error);
  931. }
  932. NTSTATUS
  933. AtalkTdiDisassociateAddress(
  934. IN PIRP pIrp,
  935. IN PIO_STACK_LOCATION pIrpSp,
  936. IN OUT PATALK_DEV_CTX pCtx
  937. )
  938. /*++
  939. Routine Description:
  940. This routine performs a disassociate. This request is only valid when
  941. the connection is in a purely ASSOCIATED state.
  942. Arguments:
  943. Return Value:
  944. STATUS_SUCCESS if successfully completed
  945. Error otherwise.
  946. --*/
  947. {
  948. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  949. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  950. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  951. (pCtx->adc_DevType == ATALK_DEV_ADSP)||
  952. (pCtx->adc_DevType == ATALK_DEV_ASPC))
  953. do
  954. {
  955. ASSERT(((LONG_PTR)pIrpSp->FileObject->FsContext2 >> 16) == pCtx->adc_DevType);
  956. // Now depending on the requested device...
  957. switch (pCtx->adc_DevType)
  958. {
  959. case ATALK_DEV_PAP:
  960. // Reference the connection object
  961. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  962. {
  963. ASSERT(0);
  964. error = ATALK_INVALID_CONNECTION;
  965. break;
  966. }
  967. AtalkLockPapIfNecessary();
  968. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  969. if (ATALK_SUCCESS(error))
  970. {
  971. error = AtalkPapDissociateAddress(pConnObj);
  972. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  973. }
  974. AtalkUnlockPapIfNecessary();
  975. break;
  976. case ATALK_DEV_ADSP:
  977. // Reference the connection object
  978. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  979. {
  980. ASSERT(0);
  981. error = ATALK_INVALID_CONNECTION;
  982. break;
  983. }
  984. AtalkLockAdspIfNecessary();
  985. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  986. if (ATALK_SUCCESS(error))
  987. {
  988. error = AtalkAdspDissociateAddress(pConnObj);
  989. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  990. }
  991. AtalkUnlockAdspIfNecessary();
  992. break;
  993. case ATALK_DEV_ASPC:
  994. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  995. {
  996. ASSERT(0);
  997. error = ATALK_INVALID_CONNECTION;
  998. break;
  999. }
  1000. AtalkLockAspCIfNecessary();
  1001. if (!AtalkAspCConnectionIsValid((PASPC_CONNOBJ)pConnObj))
  1002. {
  1003. error = ATALK_INVALID_CONNECTION;
  1004. AtalkUnlockAspCIfNecessary();
  1005. break;
  1006. }
  1007. // Reference the connection object
  1008. AtalkAspCConnReference((PASPC_CONNOBJ)pConnObj, &error);
  1009. if (ATALK_SUCCESS(error))
  1010. {
  1011. error = AtalkAspCDissociateAddress(pConnObj);
  1012. AtalkAspCConnDereference((PASPC_CONNOBJ)pConnObj);
  1013. }
  1014. AtalkUnlockAspCIfNecessary();
  1015. break;
  1016. }
  1017. } while (FALSE);
  1018. return AtalkErrorToNtStatus(error);
  1019. }
  1020. NTSTATUS
  1021. AtalkTdiConnect(
  1022. IN PIRP pIrp,
  1023. IN PIO_STACK_LOCATION pIrpSp,
  1024. IN OUT PATALK_DEV_CTX pCtx
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This routine will post a connect request with the portable stack.
  1029. Arguments:
  1030. Return Value:
  1031. STATUS_PENDING if successfully started
  1032. Error otherwise.
  1033. --*/
  1034. {
  1035. PTDI_REQUEST_KERNEL_CONNECT parameters;
  1036. PTA_APPLETALK_ADDRESS remoteTdiAddr;
  1037. ATALK_ADDR remoteAddr;
  1038. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  1039. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  1040. parameters = (PTDI_REQUEST_KERNEL_CONNECT)&pIrpSp->Parameters;
  1041. remoteTdiAddr = (PTA_APPLETALK_ADDRESS)
  1042. parameters->RequestConnectionInformation->RemoteAddress;
  1043. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  1044. ("AtalkTdiConnect: Net %x Node %x Socket %x\n",
  1045. remoteTdiAddr->Address[0].Address[0].Network,
  1046. remoteTdiAddr->Address[0].Address[0].Node,
  1047. remoteTdiAddr->Address[0].Address[0].Socket));
  1048. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  1049. ("AtalkConnPostConnect: Cnt %x\n", remoteTdiAddr->TAAddressCount));
  1050. TDI_TO_ATALKADDR(&remoteAddr, remoteTdiAddr);
  1051. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  1052. ("AtalkTdiConnect: Portable Net %x Node %x Socket %x\n",
  1053. remoteAddr.ata_Network, remoteAddr.ata_Node, remoteAddr.ata_Socket));
  1054. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  1055. (pCtx->adc_DevType == ATALK_DEV_ADSP)||
  1056. (pCtx->adc_DevType == ATALK_DEV_ASPC))
  1057. do
  1058. {
  1059. ASSERT(((LONG_PTR)pIrpSp->FileObject->FsContext2 >> 16) == pCtx->adc_DevType);
  1060. // Now depending on the requested device...
  1061. switch (pCtx->adc_DevType)
  1062. {
  1063. case ATALK_DEV_PAP:
  1064. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  1065. {
  1066. ASSERT(0);
  1067. error = ATALK_INVALID_CONNECTION;
  1068. break;
  1069. }
  1070. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  1071. if (ATALK_SUCCESS(error))
  1072. {
  1073. error = AtalkPapPostConnect((PPAP_CONNOBJ)pConnObj,
  1074. &remoteAddr,
  1075. pIrp,
  1076. atalkTdiGenericComplete);
  1077. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  1078. }
  1079. break;
  1080. case ATALK_DEV_ADSP:
  1081. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  1082. {
  1083. ASSERT(0);
  1084. error = ATALK_INVALID_CONNECTION;
  1085. break;
  1086. }
  1087. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  1088. if (ATALK_SUCCESS(error))
  1089. {
  1090. error = AtalkAdspPostConnect((PADSP_CONNOBJ)pConnObj,
  1091. &remoteAddr,
  1092. pIrp,
  1093. atalkTdiGenericComplete);
  1094. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  1095. }
  1096. break;
  1097. case ATALK_DEV_ASPC:
  1098. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  1099. {
  1100. ASSERT(0);
  1101. error = ATALK_INVALID_CONNECTION;
  1102. break;
  1103. }
  1104. if (!AtalkAspCConnectionIsValid((PASPC_CONNOBJ)pConnObj))
  1105. {
  1106. error = ATALK_INVALID_CONNECTION;
  1107. break;
  1108. }
  1109. AtalkAspCConnReference((PASPC_CONNOBJ)pConnObj, &error);
  1110. if (ATALK_SUCCESS(error))
  1111. {
  1112. error = AtalkAspCPostConnect((PASPC_CONNOBJ)pConnObj,
  1113. &remoteAddr,
  1114. pIrp,
  1115. atalkTdiGenericComplete);
  1116. AtalkAspCConnDereference((PASPC_CONNOBJ)pConnObj);
  1117. }
  1118. break;
  1119. }
  1120. } while (FALSE);
  1121. return AtalkErrorToNtStatus(error);
  1122. }
  1123. NTSTATUS
  1124. AtalkTdiDisconnect(
  1125. IN PIRP pIrp,
  1126. IN PIO_STACK_LOCATION pIrpSp,
  1127. IN OUT PATALK_DEV_CTX pCtx
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. This routine will disconnect an active connection or cancel a posted
  1132. listen/connect
  1133. Arguments:
  1134. Return Value:
  1135. STATUS_SUCCESS if successfully completed
  1136. STATUS_PENDING if successfully started
  1137. Error otherwise.
  1138. --*/
  1139. {
  1140. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  1141. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  1142. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  1143. (pCtx->adc_DevType == ATALK_DEV_ADSP)||
  1144. (pCtx->adc_DevType == ATALK_DEV_ASPC))
  1145. do
  1146. {
  1147. ASSERT(((LONG_PTR)pIrpSp->FileObject->FsContext2 >> 16) == pCtx->adc_DevType);
  1148. // Now depending on the requested device...
  1149. switch (pCtx->adc_DevType)
  1150. {
  1151. case ATALK_DEV_PAP:
  1152. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  1153. {
  1154. ASSERT(0);
  1155. error = ATALK_INVALID_CONNECTION;
  1156. break;
  1157. }
  1158. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  1159. if (ATALK_SUCCESS(error))
  1160. {
  1161. error = AtalkPapDisconnect((PPAP_CONNOBJ)pConnObj,
  1162. ATALK_LOCAL_DISCONNECT,
  1163. pIrp,
  1164. atalkTdiGenericComplete);
  1165. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  1166. }
  1167. break;
  1168. case ATALK_DEV_ADSP:
  1169. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  1170. {
  1171. ASSERT(0);
  1172. error = ATALK_INVALID_CONNECTION;
  1173. break;
  1174. }
  1175. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  1176. if (ATALK_SUCCESS(error))
  1177. {
  1178. error = AtalkAdspDisconnect((PADSP_CONNOBJ)pConnObj,
  1179. ATALK_LOCAL_DISCONNECT,
  1180. pIrp,
  1181. atalkTdiGenericComplete);
  1182. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  1183. }
  1184. break;
  1185. case ATALK_DEV_ASPC:
  1186. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  1187. {
  1188. ASSERT(0);
  1189. error = ATALK_INVALID_CONNECTION;
  1190. break;
  1191. }
  1192. if (!AtalkAspCConnectionIsValid((PASPC_CONNOBJ)pConnObj))
  1193. {
  1194. error = ATALK_INVALID_CONNECTION;
  1195. break;
  1196. }
  1197. AtalkAspCConnReference((PASPC_CONNOBJ)pConnObj, &error);
  1198. if (ATALK_SUCCESS(error))
  1199. {
  1200. error = AtalkAspCDisconnect((PASPC_CONNOBJ)pConnObj,
  1201. ATALK_LOCAL_DISCONNECT,
  1202. pIrp,
  1203. atalkTdiGenericComplete);
  1204. AtalkAspCConnDereference((PASPC_CONNOBJ)pConnObj);
  1205. }
  1206. break;
  1207. }
  1208. } while (FALSE);
  1209. return AtalkErrorToNtStatus(error);
  1210. }
  1211. NTSTATUS
  1212. AtalkTdiAccept(
  1213. IN PIRP pIrp,
  1214. IN PIO_STACK_LOCATION pIrpSp,
  1215. IN OUT PATALK_DEV_CTX pCtx
  1216. )
  1217. /*++
  1218. Routine Description:
  1219. This routine
  1220. Arguments:
  1221. Return Value:
  1222. STATUS_SUCCESS if successfully completed
  1223. STATUS_PENDING if successfully started
  1224. Error otherwise.
  1225. --*/
  1226. {
  1227. NTSTATUS status = STATUS_SUCCESS;
  1228. do
  1229. {
  1230. ASSERT(((LONG_PTR)pIrpSp->FileObject->FsContext2 >> 16) == pCtx->adc_DevType);
  1231. // Now depending on the requested device...
  1232. switch (pCtx->adc_DevType)
  1233. {
  1234. case ATALK_DEV_ADSP:
  1235. case ATALK_DEV_PAP:
  1236. break;
  1237. default:
  1238. // The device type in the Ctx field can never be anything
  1239. // other than the above! Internal protocol error. KeBugCheck.
  1240. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  1241. ("AtalkTdiAccept: Invalid device type\n"));
  1242. case ATALK_DEV_DDP:
  1243. case ATALK_DEV_ASPC:
  1244. case ATALK_DEV_ASP:
  1245. status = STATUS_INVALID_DEVICE_REQUEST;
  1246. break;
  1247. }
  1248. } while (FALSE);
  1249. return status;
  1250. }
  1251. NTSTATUS
  1252. AtalkTdiListen(
  1253. IN PIRP pIrp,
  1254. IN PIO_STACK_LOCATION pIrpSp,
  1255. IN OUT PATALK_DEV_CTX pCtx
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. This routine
  1260. Arguments:
  1261. Return Value:
  1262. STATUS_PENDING if successfully started
  1263. Error otherwise.
  1264. --*/
  1265. {
  1266. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  1267. PVOID pConnObj = pIrpSp->FileObject->FsContext;
  1268. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  1269. (pCtx->adc_DevType == ATALK_DEV_ADSP))
  1270. do
  1271. {
  1272. ASSERT(((LONG_PTR)pIrpSp->FileObject->FsContext2 >> 16) == pCtx->adc_DevType);
  1273. // Now depending on the requested device...
  1274. switch (pCtx->adc_DevType)
  1275. {
  1276. case ATALK_DEV_PAP:
  1277. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  1278. {
  1279. ASSERT(0);
  1280. error = ATALK_INVALID_CONNECTION;
  1281. break;
  1282. }
  1283. AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pConnObj, &error);
  1284. if (ATALK_SUCCESS(error))
  1285. {
  1286. error = AtalkPapPostListen((PPAP_CONNOBJ)pConnObj,
  1287. pIrp,
  1288. atalkTdiGenericComplete);
  1289. AtalkPapConnDereference((PPAP_CONNOBJ)pConnObj);
  1290. }
  1291. break;
  1292. case ATALK_DEV_ADSP:
  1293. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  1294. {
  1295. ASSERT(0);
  1296. error = ATALK_INVALID_CONNECTION;
  1297. break;
  1298. }
  1299. AtalkAdspConnReferenceByPtr((PADSP_CONNOBJ)pConnObj, &error);
  1300. if (ATALK_SUCCESS(error))
  1301. {
  1302. error = AtalkAdspPostListen((PADSP_CONNOBJ)pConnObj,
  1303. pIrp,
  1304. atalkTdiGenericComplete);
  1305. AtalkAdspConnDereference((PADSP_CONNOBJ)pConnObj);
  1306. }
  1307. break;
  1308. }
  1309. } while (FALSE);
  1310. if (error == ATALK_NO_ERROR)
  1311. error = ATALK_PENDING;
  1312. return AtalkErrorToNtStatus(error);
  1313. }
  1314. NTSTATUS
  1315. AtalkTdiSendDgram(
  1316. IN PIRP pIrp,
  1317. IN PIO_STACK_LOCATION pIrpSp,
  1318. IN OUT PATALK_DEV_CTX pCtx
  1319. )
  1320. /*++
  1321. Routine Description:
  1322. This routine sends a datagram.
  1323. Arguments:
  1324. Return Value:
  1325. STATUS_PENDING if successfully started
  1326. Error otherwise.
  1327. --*/
  1328. {
  1329. NTSTATUS status = STATUS_SUCCESS;
  1330. SEND_COMPL_INFO SendInfo;
  1331. do
  1332. {
  1333. // Now depending on the requested device...
  1334. switch (pCtx->adc_DevType)
  1335. {
  1336. case ATALK_DEV_DDP:
  1337. {
  1338. PTDI_REQUEST_KERNEL_SENDDG pParam;
  1339. PBUFFER_DESC pBufDesc;
  1340. ATALK_ERROR error;
  1341. PTA_APPLETALK_ADDRESS pTaDest;
  1342. ATALK_ADDR AtalkAddr;
  1343. PDDP_ADDROBJ pDdpAddr;
  1344. pDdpAddr = (PDDP_ADDROBJ)pIrpSp->FileObject->FsContext;
  1345. if (!(VALID_DDP_ADDROBJ(pDdpAddr)))
  1346. {
  1347. ASSERT(0);
  1348. error = ATALK_INVALID_ADDRESS;
  1349. break;
  1350. }
  1351. pParam = (PTDI_REQUEST_KERNEL_SENDDG)&pIrpSp->Parameters;
  1352. pTaDest = (PTA_APPLETALK_ADDRESS)
  1353. pParam->SendDatagramInformation->RemoteAddress;
  1354. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_INFO,
  1355. ("DDP: SendDatagram - Net %x Node %x Socket %x\n",
  1356. pTaDest->Address[0].Address[0].Network,
  1357. pTaDest->Address[0].Address[0].Node,
  1358. pTaDest->Address[0].Address[0].Socket));
  1359. if ((pTaDest->Address[0].AddressType != TDI_ADDRESS_TYPE_APPLETALK) ||
  1360. (pTaDest->Address[0].AddressLength < sizeof(TDI_ADDRESS_APPLETALK)))
  1361. {
  1362. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  1363. ("AtalkTdiSendDgram: returning STATUS_INVALID_ADDRESS (Type %x Len %d)\n",
  1364. pTaDest->Address[0].AddressType,pTaDest->Address[0].AddressLength));
  1365. status = STATUS_INVALID_ADDRESS;
  1366. }
  1367. else
  1368. {
  1369. ULONG sendLength;
  1370. AtalkAddr.ata_Network = pTaDest->Address[0].Address[0].Network;
  1371. AtalkAddr.ata_Node = pTaDest->Address[0].Address[0].Node;
  1372. AtalkAddr.ata_Socket = pTaDest->Address[0].Address[0].Socket;
  1373. // Get the length of the send mdl
  1374. sendLength = AtalkSizeMdlChain(pIrp->MdlAddress);
  1375. // Check destination address
  1376. if (INVALID_ADDRESS(&AtalkAddr))
  1377. {
  1378. error = ATALK_DDP_INVALID_ADDR;
  1379. }
  1380. if (sendLength > MAX_DGRAM_SIZE)
  1381. {
  1382. error = ATALK_BUFFER_TOO_BIG;
  1383. }
  1384. else if ((pBufDesc = AtalkAllocBuffDesc(pIrp->MdlAddress,
  1385. (USHORT)sendLength,
  1386. 0)) != NULL)
  1387. {
  1388. SendInfo.sc_TransmitCompletion = atalkTdiSendDgramComplete;
  1389. SendInfo.sc_Ctx1 = pDdpAddr;
  1390. SendInfo.sc_Ctx2 = pBufDesc;
  1391. SendInfo.sc_Ctx3 = pIrp;
  1392. error = AtalkDdpSend(pDdpAddr,
  1393. &AtalkAddr,
  1394. pDdpAddr->ddpao_Protocol,
  1395. FALSE,
  1396. pBufDesc,
  1397. NULL, // OptHdr
  1398. 0, // OptHdrLen
  1399. NULL, // ZoneMcastAddr
  1400. &SendInfo);
  1401. if (!ATALK_SUCCESS(error))
  1402. {
  1403. atalkTdiSendDgramComplete(NDIS_STATUS_FAILURE,
  1404. &SendInfo);
  1405. error = ATALK_PENDING;
  1406. }
  1407. }
  1408. else error = ATALK_RESR_MEM;
  1409. status = AtalkErrorToNtStatus(error);
  1410. }
  1411. }
  1412. break;
  1413. case ATALK_DEV_ASPC:
  1414. case ATALK_DEV_ADSP:
  1415. case ATALK_DEV_ASP:
  1416. case ATALK_DEV_PAP:
  1417. status = STATUS_INVALID_DEVICE_REQUEST;
  1418. break;
  1419. default:
  1420. // The device type in the Ctx field can never be anything
  1421. // other than the above! Internal protocol error. KeBugCheck.
  1422. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  1423. ("AtalkTdiSendDatagram: Invalid device type\n"));
  1424. break;
  1425. }
  1426. } while (FALSE);
  1427. return status;
  1428. }
  1429. NTSTATUS
  1430. AtalkTdiReceiveDgram(
  1431. IN PIRP pIrp,
  1432. IN PIO_STACK_LOCATION pIrpSp,
  1433. IN OUT PATALK_DEV_CTX pCtx
  1434. )
  1435. /*++
  1436. Routine Description:
  1437. This routine receives a datagram.
  1438. Arguments:
  1439. Return Value:
  1440. STATUS_PENDING if successfully started
  1441. Error otherwise.
  1442. --*/
  1443. {
  1444. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  1445. if (pCtx->adc_DevType == ATALK_DEV_DDP)
  1446. {
  1447. PDDP_ADDROBJ pDdpAddr;
  1448. PTDI_REQUEST_KERNEL_RECEIVEDG parameters =
  1449. (PTDI_REQUEST_KERNEL_RECEIVEDG)&pIrpSp->Parameters;
  1450. pDdpAddr = (PDDP_ADDROBJ)pIrpSp->FileObject->FsContext;
  1451. if (!(VALID_DDP_ADDROBJ(pDdpAddr)))
  1452. {
  1453. ASSERT(0);
  1454. error = ATALK_INVALID_ADDRESS;
  1455. return(AtalkErrorToNtStatus(error));
  1456. }
  1457. error = AtalkDdpReceive(pDdpAddr,
  1458. pIrp->MdlAddress,
  1459. (USHORT)AtalkSizeMdlChain(pIrp->MdlAddress),
  1460. parameters->ReceiveFlags,
  1461. atalkTdiRecvDgramComplete,
  1462. pIrp);
  1463. }
  1464. return AtalkErrorToNtStatus(error);
  1465. }
  1466. NTSTATUS
  1467. AtalkTdiSend(
  1468. IN PIRP pIrp,
  1469. IN PIO_STACK_LOCATION pIrpSp,
  1470. IN OUT PATALK_DEV_CTX pCtx
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. This routine sends the data specified. (used by PAP/ADSP only)
  1475. Arguments:
  1476. Return Value:
  1477. STATUS_SUCCESS if successfully completed
  1478. STATUS_PENDING if successfully started
  1479. Error otherwise.
  1480. --*/
  1481. {
  1482. PTDI_REQUEST_KERNEL_SEND parameters;
  1483. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  1484. PVOID pConnObj= pIrpSp->FileObject->FsContext;
  1485. parameters = (PTDI_REQUEST_KERNEL_SEND)&pIrpSp->Parameters;
  1486. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  1487. (pCtx->adc_DevType == ATALK_DEV_ADSP))
  1488. do
  1489. {
  1490. // Now depending on the requested device...
  1491. switch (pCtx->adc_DevType)
  1492. {
  1493. case ATALK_DEV_ADSP:
  1494. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  1495. {
  1496. ASSERT(0);
  1497. error = ATALK_INVALID_CONNECTION;
  1498. break;
  1499. }
  1500. error = AtalkAdspWrite(pConnObj,
  1501. pIrp->MdlAddress,
  1502. (USHORT)parameters->SendLength,
  1503. parameters->SendFlags,
  1504. pIrp,
  1505. atalkTdiGenericWriteComplete);
  1506. if (!ATALK_SUCCESS(error))
  1507. {
  1508. DBGPRINT(DBG_COMP_ADSP, DBG_LEVEL_INFO,
  1509. ("AtalkAdspWrite: Failed for conn %lx.%lx error %lx\n",
  1510. pConnObj, ((PADSP_CONNOBJ)pConnObj)->adspco_Flags, error));
  1511. }
  1512. break;
  1513. case ATALK_DEV_PAP:
  1514. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  1515. {
  1516. ASSERT(0);
  1517. error = ATALK_INVALID_CONNECTION;
  1518. break;
  1519. }
  1520. error = AtalkPapWrite(pConnObj,
  1521. pIrp->MdlAddress,
  1522. (USHORT)parameters->SendLength,
  1523. parameters->SendFlags,
  1524. pIrp,
  1525. atalkTdiGenericWriteComplete);
  1526. if (!ATALK_SUCCESS(error))
  1527. {
  1528. DBGPRINT(DBG_COMP_PAP, DBG_LEVEL_INFO,
  1529. ("AtalkPapWrite: Failed for conn %lx.%lx error %lx\n",
  1530. pConnObj, ((PPAP_CONNOBJ)pConnObj)->papco_Flags, error));
  1531. }
  1532. break;
  1533. }
  1534. } while (FALSE);
  1535. return AtalkErrorToNtStatus(error);
  1536. }
  1537. NTSTATUS
  1538. AtalkTdiReceive(
  1539. IN PIRP pIrp,
  1540. IN PIO_STACK_LOCATION pIrpSp,
  1541. IN OUT PATALK_DEV_CTX pCtx
  1542. )
  1543. /*++
  1544. Routine Description:
  1545. This routine receives data. (used by PAP/ADSP only)
  1546. Arguments:
  1547. Return Value:
  1548. STATUS_SUCCESS if successfully completed
  1549. STATUS_PENDING if successfully started
  1550. Error otherwise.
  1551. --*/
  1552. {
  1553. ATALK_ERROR error = ATALK_INVALID_REQUEST;
  1554. PVOID pConnObj= pIrpSp->FileObject->FsContext;
  1555. PTDI_REQUEST_KERNEL_RECEIVE parameters =
  1556. (PTDI_REQUEST_KERNEL_RECEIVE)&pIrpSp->Parameters;
  1557. if ((pCtx->adc_DevType == ATALK_DEV_PAP) ||
  1558. (pCtx->adc_DevType == ATALK_DEV_ASPC)||
  1559. (pCtx->adc_DevType == ATALK_DEV_ADSP))
  1560. do
  1561. {
  1562. // Now depending on the requested device...
  1563. switch (pCtx->adc_DevType)
  1564. {
  1565. case ATALK_DEV_PAP:
  1566. if (!(VALID_PAPCO((PPAP_CONNOBJ)pConnObj)))
  1567. {
  1568. ASSERT(0);
  1569. error = ATALK_INVALID_CONNECTION;
  1570. break;
  1571. }
  1572. error = AtalkPapRead(pConnObj,
  1573. pIrp->MdlAddress,
  1574. (USHORT)parameters->ReceiveLength,
  1575. parameters->ReceiveFlags,
  1576. pIrp,
  1577. atalkTdiGenericReadComplete);
  1578. if (!ATALK_SUCCESS(error))
  1579. {
  1580. DBGPRINT(DBG_COMP_PAP, DBG_LEVEL_INFO,
  1581. ("AtalkPapRead: Failed for conn %lx.%lx error %lx\n",
  1582. pConnObj, ((PPAP_CONNOBJ)pConnObj)->papco_Flags, error));
  1583. }
  1584. break;
  1585. case ATALK_DEV_ADSP:
  1586. if (!(VALID_ADSPCO((PADSP_CONNOBJ)pConnObj)))
  1587. {
  1588. ASSERT(0);
  1589. error = ATALK_INVALID_CONNECTION;
  1590. break;
  1591. }
  1592. AtalkLockAdspIfNecessary();
  1593. error = AtalkAdspRead(pConnObj,
  1594. pIrp->MdlAddress,
  1595. (USHORT)parameters->ReceiveLength,
  1596. parameters->ReceiveFlags,
  1597. pIrp,
  1598. atalkTdiGenericReadComplete);
  1599. AtalkUnlockAdspIfNecessary();
  1600. if (!ATALK_SUCCESS(error))
  1601. {
  1602. DBGPRINT(DBG_COMP_ADSP, DBG_LEVEL_INFO,
  1603. ("AtalkAdspRead: Failed for conn %lx.%lx error %lx\n",
  1604. pConnObj, ((PADSP_CONNOBJ)pConnObj)->adspco_Flags, error));
  1605. }
  1606. break;
  1607. case ATALK_DEV_ASPC:
  1608. if (!(VALID_ASPCCO((PASPC_CONNOBJ)pConnObj)))
  1609. {
  1610. ASSERT(0);
  1611. error = ATALK_INVALID_CONNECTION;
  1612. break;
  1613. }
  1614. error = AtalkAspCGetAttn(pConnObj,
  1615. pIrp->MdlAddress,
  1616. (USHORT)parameters->ReceiveLength,
  1617. parameters->ReceiveFlags,
  1618. pIrp,
  1619. atalkTdiGenericReadComplete);
  1620. if (!ATALK_SUCCESS(error))
  1621. {
  1622. DBGPRINT(DBG_COMP_ASP, DBG_LEVEL_INFO,
  1623. ("AtalkAspCGetAttn: Failed for conn %lx.%lx error %lx\n",
  1624. pConnObj, ((PASPC_CONNOBJ)pConnObj)->aspcco_Flags, error));
  1625. }
  1626. break;
  1627. }
  1628. } while (FALSE);
  1629. return AtalkErrorToNtStatus(error);
  1630. }
  1631. NTSTATUS
  1632. AtalkTdiAction(
  1633. IN PIRP pIrp,
  1634. IN PIO_STACK_LOCATION pIrpSp,
  1635. IN OUT PATALK_DEV_CTX pCtx
  1636. )
  1637. /*++
  1638. Routine Description:
  1639. This routine is the dispatch routine for all the TdiAction primitives
  1640. for all the providers
  1641. Arguments:
  1642. Return Value:
  1643. STATUS_SUCCESS if successfully completed
  1644. STATUS_PENDING if successfully started
  1645. Error otherwise.
  1646. --*/
  1647. {
  1648. NTSTATUS status = STATUS_SUCCESS;
  1649. ATALK_ERROR error = ATALK_NO_ERROR;
  1650. USHORT bufLen;
  1651. USHORT actionCode, Flags;
  1652. PTDI_ACTION_HEADER pActionHdr;
  1653. PMDL pMdl = pIrp->MdlAddress;
  1654. PVOID pObject;
  1655. USHORT ObjectType;
  1656. USHORT DevType;
  1657. BOOLEAN freeHdr = FALSE;
  1658. do
  1659. {
  1660. if (pMdl == NULL)
  1661. {
  1662. status = STATUS_INVALID_PARAMETER;
  1663. break;
  1664. }
  1665. bufLen = (USHORT)AtalkSizeMdlChain(pIrp->MdlAddress);
  1666. // If we atleast do not have the action header, return
  1667. if (bufLen < sizeof(TDI_ACTION_HEADER))
  1668. {
  1669. status = STATUS_INVALID_PARAMETER;
  1670. ASSERT(0);
  1671. break;
  1672. }
  1673. if (AtalkIsMdlFragmented(pMdl))
  1674. {
  1675. ULONG bytesCopied;
  1676. if ((pActionHdr = AtalkAllocMemory(sizeof(TDI_ACTION_HEADER))) == NULL)
  1677. {
  1678. status = STATUS_INSUFFICIENT_RESOURCES;
  1679. break;
  1680. }
  1681. freeHdr = TRUE;
  1682. // Copy the header to this buffer
  1683. status = TdiCopyMdlToBuffer(pMdl,
  1684. 0, // SrcOff
  1685. pActionHdr,
  1686. 0, // Dest Off
  1687. sizeof(TDI_ACTION_HEADER),
  1688. &bytesCopied);
  1689. ASSERT(NT_SUCCESS(status) && (bytesCopied == sizeof(TDI_ACTION_HEADER)));
  1690. if (!NT_SUCCESS(status))
  1691. break;
  1692. }
  1693. else
  1694. {
  1695. pActionHdr = (PTDI_ACTION_HEADER)MmGetSystemAddressForMdlSafe(
  1696. pMdl, NormalPagePriority);
  1697. if (pActionHdr == NULL) {
  1698. ASSERT(0);
  1699. status = STATUS_INSUFFICIENT_RESOURCES;
  1700. break;
  1701. }
  1702. }
  1703. DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_INFO,
  1704. ("AtalkTdiAction - code %lx BufLen %d SysAddress %lx\n",
  1705. pActionHdr->ActionCode, bufLen, pActionHdr));
  1706. // If the MATK identifier is not present, we return
  1707. if (pActionHdr->TransportId != MATK)
  1708. {
  1709. status = STATUS_INVALID_DEVICE_REQUEST;
  1710. break;
  1711. }
  1712. actionCode = pActionHdr->ActionCode;
  1713. if ((actionCode < MIN_COMMON_ACTIONCODE) ||
  1714. (actionCode > MAX_ALLACTIONCODES))
  1715. {
  1716. DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_ERR,
  1717. ("AtalkTdiAction - Invalid action code %d\n", actionCode));
  1718. status = STATUS_INVALID_PARAMETER;
  1719. break;
  1720. }
  1721. if (bufLen < AtalkActionDispatch[actionCode]._MinBufLen)
  1722. {
  1723. DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_ERR,
  1724. ("AtalkTdiAction - Minbuflen %d Expected %d\n",
  1725. bufLen, AtalkActionDispatch[actionCode]._MinBufLen));
  1726. status = STATUS_BUFFER_TOO_SMALL;
  1727. break;
  1728. }
  1729. // if someone is trying to open ASP via usermode, reject it!
  1730. if ((AtalkActionDispatch[actionCode]._OpCode == ACTION_ASP_BIND) &&
  1731. (pIrp->RequestorMode != KernelMode))
  1732. {
  1733. status = STATUS_INVALID_PARAMETER;
  1734. ASSERT(0);
  1735. break;
  1736. }
  1737. Flags = AtalkActionDispatch[actionCode]._Flags;
  1738. pObject = (PVOID)pIrpSp->FileObject->FsContext;
  1739. ObjectType = (USHORT)((ULONG_PTR)(pIrpSp->FileObject->FsContext2) & 0xFF);
  1740. DevType = (USHORT)((ULONG_PTR)(pIrpSp->FileObject->FsContext2) >> 16);
  1741. // Convert control channel operations to Ddp
  1742. if (ObjectType == TDI_CONTROL_CHANNEL_FILE)
  1743. DevType = ATALK_DEV_DDP;
  1744. // Verify the device type is that expected. Either the request
  1745. // should be valid for any device or the type of device for the
  1746. // request should match the type of device expected.
  1747. if ((AtalkActionDispatch[actionCode]._DeviceType != ATALK_DEV_ANY) &&
  1748. ((pCtx->adc_DevType != AtalkActionDispatch[actionCode]._DeviceType) ||
  1749. (DevType != AtalkActionDispatch[actionCode]._DeviceType)))
  1750. {
  1751. status = STATUS_INVALID_DEVICE_REQUEST;
  1752. break;
  1753. }
  1754. // Verify the object - it has to be one of those specified as valid
  1755. // in the dispatch table for this action call.
  1756. ASSERT(ObjectType & (DFLAG_ADDR | DFLAG_CNTR | DFLAG_CONN));
  1757. switch (ObjectType)
  1758. {
  1759. case TDI_TRANSPORT_ADDRESS_FILE:
  1760. if (!(Flags & DFLAG_ADDR))
  1761. status = STATUS_INVALID_HANDLE;
  1762. break;
  1763. case TDI_CONNECTION_FILE:
  1764. if (!(Flags & DFLAG_CONN))
  1765. status = STATUS_INVALID_HANDLE;
  1766. break;
  1767. case TDI_CONTROL_CHANNEL_FILE:
  1768. if (!(Flags & DFLAG_CNTR))
  1769. status = STATUS_INVALID_HANDLE;
  1770. break;
  1771. default:
  1772. status = STATUS_INVALID_HANDLE;
  1773. break;
  1774. }
  1775. } while (FALSE);
  1776. if (!NT_SUCCESS(status))
  1777. {
  1778. if (freeHdr)
  1779. {
  1780. AtalkFreeMemory(pActionHdr);
  1781. }
  1782. return status;
  1783. }
  1784. // Handle the requests based on the action code.
  1785. // Use the table to call the appropriate routine
  1786. do
  1787. {
  1788. PACTREQ pActReq;
  1789. USHORT offset = AtalkActionDispatch[actionCode]._ActionBufSize;
  1790. USHORT size = bufLen - offset;
  1791. // If DFLAG_MDL is set, then we know we have to create the mdl.
  1792. //
  1793. // NOTE: User can pass in invalid sizes...
  1794. // Also, it is assumed that BuildMdl will not change
  1795. // value of the mdl unless it can successfully build
  1796. // all of it. Therefore, error cases must preserve
  1797. // value of NULL.
  1798. //
  1799. // First allocate an action request structure.
  1800. // !!!This memory should be zeroed out as we depend on extra mdl pointer to
  1801. // be NULL!!!
  1802. if ((pActReq = AtalkAllocZeroedMemory(sizeof(ACTREQ))) == NULL)
  1803. {
  1804. status = STATUS_INSUFFICIENT_RESOURCES;
  1805. break;
  1806. }
  1807. #if DBG
  1808. pActReq->ar_Signature = ACTREQ_SIGNATURE;
  1809. #endif
  1810. pActReq->ar_pIrp = pIrp;
  1811. pActReq->ar_DevType = DevType;
  1812. pActReq->ar_pParms = (PBYTE)pActionHdr + sizeof(TDI_ACTION_HEADER);
  1813. pActReq->ar_Completion = atalkTdiActionComplete;
  1814. pActReq->ar_ActionCode = actionCode;
  1815. pActReq->ar_pAMdl = NULL;
  1816. pActReq->ar_MdlSize = 0;
  1817. if (Flags & DFLAG_MDL)
  1818. {
  1819. ASSERT((size >= 0) && ((offset+size) <= bufLen));
  1820. pActReq->ar_MdlSize = size;
  1821. if ((size < 0) || ((offset+size) > bufLen))
  1822. {
  1823. AtalkFreeMemory(pActReq);
  1824. status = STATUS_INVALID_PARAMETER;
  1825. break;
  1826. }
  1827. // If size is zero, we go on to the next mdl.
  1828. // IoAllocateMdl will fail for a 0-length mdl
  1829. // If size < 0, we will hit the error later.
  1830. if (size != 0)
  1831. {
  1832. DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_INFO,
  1833. ("AtalkTdiAction - Size of mdl %lx\n", size));
  1834. pActReq->ar_pAMdl = AtalkSubsetAmdl(pMdl, // MasterMdl
  1835. offset, // ByteOffset,
  1836. size); // SubsetMdlSize,
  1837. if (pActReq->ar_pAMdl == NULL)
  1838. {
  1839. AtalkFreeMemory(pActReq);
  1840. status = STATUS_INSUFFICIENT_RESOURCES;
  1841. break;
  1842. }
  1843. }
  1844. }
  1845. // Now call the dispatch routine
  1846. error = (*AtalkActionDispatch[actionCode]._Dispatch)(pObject, pActReq);
  1847. if (!ATALK_SUCCESS(error))
  1848. {
  1849. // Call the generic completion routine and then return
  1850. // pending. That will free up the mdl's and the actreq.
  1851. atalkTdiActionComplete(error, pActReq);
  1852. }
  1853. status = STATUS_PENDING;
  1854. } while (FALSE);
  1855. return status;
  1856. }
  1857. NTSTATUS
  1858. AtalkTdiQueryInformation(
  1859. IN PIRP pIrp,
  1860. IN PIO_STACK_LOCATION pIrpSp,
  1861. IN OUT PATALK_DEV_CTX pCtx
  1862. )
  1863. /*++
  1864. Routine Description:
  1865. This routine will satisfy the query for the object indicated in the Request. It
  1866. supports the following query types-
  1867. TDI_QUERY_PROVIDER_INFO
  1868. The provider information structure for the provider that the object belongs to.
  1869. TDI_QUERY_ADDRESS_INFO
  1870. The address information for the address object passed in.
  1871. TDI_QUERY_CONNECTION_INFO **NOT SUPPORTED**
  1872. The connection information for the connection object passed in.
  1873. TDI_QUERY_PROVIDER_STATISTICS **NOT SUPPORTED**
  1874. The provider statistics - per provider statistics. All actions on a particular
  1875. file object corresponds to activity on the provider of that file object. So each
  1876. provider context structure will have the provider statistics structure which will
  1877. be returned in this call.
  1878. Arguments:
  1879. Return Value:
  1880. STATUS_SUCCESS if successfully completed
  1881. STATUS_PENDING if successfully started
  1882. Error otherwise.
  1883. --*/
  1884. {
  1885. PVOID pObject;
  1886. USHORT ObjectType;
  1887. USHORT DevType;
  1888. USHORT bufLen;
  1889. ULONG BytesWritten;
  1890. NTSTATUS status = STATUS_SUCCESS;
  1891. PTDI_REQUEST_KERNEL_QUERY_INFORMATION pQuery;
  1892. pObject = (PVOID)pIrpSp->FileObject->FsContext;
  1893. ObjectType = (USHORT)((ULONG_PTR)(pIrpSp->FileObject->FsContext2) & 0xFF);
  1894. DevType = (USHORT)((ULONG_PTR)(pIrpSp->FileObject->FsContext2) >> 16);
  1895. pQuery = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&pIrpSp->Parameters;
  1896. BytesWritten = 0;
  1897. pIrp->IoStatus.Information = 0;
  1898. bufLen = (USHORT)AtalkSizeMdlChain(pIrp->MdlAddress);
  1899. switch (pQuery->QueryType)
  1900. {
  1901. case TDI_QUERY_ADDRESS_INFO:
  1902. if (bufLen < sizeof(TDI_ADDRESS_INFO))
  1903. {
  1904. status = STATUS_BUFFER_TOO_SMALL;
  1905. break;
  1906. }
  1907. switch (DevType)
  1908. {
  1909. case ATALK_DEV_DDP:
  1910. ASSERT(ObjectType == TDI_TRANSPORT_ADDRESS_FILE);
  1911. AtalkDdpQuery(pObject,
  1912. pIrp->MdlAddress,
  1913. &BytesWritten);
  1914. break;
  1915. case ATALK_DEV_PAP:
  1916. AtalkPapQuery(pObject,
  1917. ObjectType,
  1918. pIrp->MdlAddress,
  1919. &BytesWritten);
  1920. break;
  1921. case ATALK_DEV_ADSP:
  1922. AtalkAdspQuery(pObject,
  1923. ObjectType,
  1924. pIrp->MdlAddress,
  1925. &BytesWritten);
  1926. break;
  1927. case ATALK_DEV_ASPC:
  1928. case ATALK_DEV_ASP:
  1929. status = STATUS_INVALID_DEVICE_REQUEST;
  1930. break;
  1931. default:
  1932. // The device type in the Ctx field can never be anything
  1933. // other than the above! Internal protocol error. KeBugCheck.
  1934. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  1935. ("AtalkTdiQueryInformation: Invalid device type\n"));
  1936. status = STATUS_INVALID_DEVICE_REQUEST;
  1937. break;
  1938. }
  1939. break;
  1940. case TDI_QUERY_CONNECTION_INFO:
  1941. // Statistics on a connection. Not supported.
  1942. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  1943. ("AtalkTdiQueryInformation: TDI_QUERY_CONNECTION_INFO not supported\n"));
  1944. ASSERT(0);
  1945. status = STATUS_NOT_IMPLEMENTED;
  1946. break;
  1947. case TDI_QUERY_PROVIDER_INFO:
  1948. if (bufLen < sizeof(TDI_PROVIDER_INFO))
  1949. {
  1950. status = STATUS_BUFFER_TOO_SMALL;
  1951. break;
  1952. }
  1953. status = TdiCopyBufferToMdl(&pCtx->adc_ProvInfo,
  1954. 0,
  1955. sizeof (TDI_PROVIDER_INFO),
  1956. pIrp->MdlAddress,
  1957. 0,
  1958. &BytesWritten);
  1959. break;
  1960. case TDI_QUERY_PROVIDER_STATISTICS:
  1961. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  1962. ("AtalkTdiQueryInformation: TDI_QUERY_PROVIDER_STATISTICS not supported\n"));
  1963. ASSERT(0);
  1964. status = STATUS_NOT_IMPLEMENTED;
  1965. break;
  1966. default:
  1967. status = STATUS_INVALID_DEVICE_REQUEST;
  1968. break;
  1969. }
  1970. pIrp->IoStatus.Information = BytesWritten;
  1971. return status;
  1972. }
  1973. NTSTATUS
  1974. AtalkTdiSetInformation(
  1975. IN PIRP pIrp,
  1976. IN PIO_STACK_LOCATION pIrpSp,
  1977. IN OUT PATALK_DEV_CTX pCtx
  1978. )
  1979. /*++
  1980. Routine Description:
  1981. This routine
  1982. Arguments:
  1983. Return Value:
  1984. STATUS_SUCCESS if successfully completed
  1985. STATUS_PENDING if successfully started
  1986. Error otherwise.
  1987. --*/
  1988. {
  1989. NTSTATUS status;
  1990. do
  1991. {
  1992. // Now depending on the requested device...
  1993. switch (pCtx->adc_DevType)
  1994. {
  1995. case ATALK_DEV_DDP:
  1996. case ATALK_DEV_PAP:
  1997. case ATALK_DEV_ADSP:
  1998. case ATALK_DEV_ASPC:
  1999. status = STATUS_SUCCESS;
  2000. break;
  2001. case ATALK_DEV_ASP:
  2002. status = STATUS_INVALID_DEVICE_REQUEST;
  2003. break;
  2004. default:
  2005. // The device type in the Ctx field can never be anything
  2006. // other than the above! Internal protocol error. KeBugCheck.
  2007. status = STATUS_INVALID_DEVICE_REQUEST;
  2008. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2009. ("AtalkTdiSetInformation: Invalid device type\n"));
  2010. break;
  2011. }
  2012. } while (FALSE);
  2013. return status;
  2014. }
  2015. NTSTATUS
  2016. AtalkTdiSetEventHandler(
  2017. IN PIRP pIrp,
  2018. IN PIO_STACK_LOCATION pIrpSp,
  2019. IN OUT PATALK_DEV_CTX pCtx
  2020. )
  2021. /*++
  2022. Routine Description:
  2023. This routine
  2024. Arguments:
  2025. Return Value:
  2026. STATUS_SUCCESS if successfully completed
  2027. STATUS_PENDING if successfully started
  2028. Error otherwise.
  2029. --*/
  2030. {
  2031. PVOID pObject;
  2032. PDDP_ADDROBJ pDdpAddr;
  2033. PADSP_ADDROBJ pAdspAddr;
  2034. PPAP_ADDROBJ pPapAddr;
  2035. PASPC_ADDROBJ pAspAddr;
  2036. USHORT objectType;
  2037. USHORT devType;
  2038. KIRQL OldIrql;
  2039. NTSTATUS status = STATUS_SUCCESS;
  2040. do
  2041. {
  2042. PTDI_REQUEST_KERNEL_SET_EVENT parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&pIrpSp->Parameters;
  2043. pObject = (PVOID)pIrpSp->FileObject->FsContext;
  2044. objectType = (USHORT)((ULONG_PTR)(pIrpSp->FileObject->FsContext2) & 0xFF);
  2045. devType = (USHORT)((ULONG_PTR)(pIrpSp->FileObject->FsContext2) >> 16);
  2046. if (objectType != TDI_TRANSPORT_ADDRESS_FILE)
  2047. {
  2048. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2049. ("AtalkTdiSetEventHandler: returning STATUS_INVALID_ADDRESS\n"));
  2050. status = STATUS_INVALID_ADDRESS;
  2051. break;
  2052. }
  2053. switch (parameters->EventType)
  2054. {
  2055. case TDI_EVENT_RECEIVE_DATAGRAM:
  2056. if (devType != ATALK_DEV_DDP)
  2057. {
  2058. status = STATUS_INVALID_DEVICE_REQUEST;
  2059. break;
  2060. }
  2061. pDdpAddr = (PDDP_ADDROBJ)pObject;
  2062. if (!(VALID_DDP_ADDROBJ(pDdpAddr)))
  2063. {
  2064. ASSERT(0);
  2065. status = STATUS_INVALID_ADDRESS;
  2066. break;
  2067. }
  2068. ACQUIRE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, &OldIrql);
  2069. // Allocate event info if null.
  2070. if (pDdpAddr->ddpao_EventInfo == NULL)
  2071. {
  2072. pDdpAddr->ddpao_EventInfo =
  2073. AtalkAllocZeroedMemory(sizeof(DDPEVENT_INFO));
  2074. }
  2075. if (pDdpAddr->ddpao_EventInfo != NULL)
  2076. {
  2077. pDdpAddr->ddpao_Flags |= DDPAO_DGRAM_EVENT;
  2078. if ((pDdpAddr->ddpao_EventInfo->ev_RcvDgramHandler =
  2079. (PTDI_IND_RECEIVE_DATAGRAM)parameters->EventHandler) == NULL)
  2080. {
  2081. pDdpAddr->ddpao_Flags &= ~DDPAO_DGRAM_EVENT;
  2082. }
  2083. pDdpAddr->ddpao_EventInfo->ev_RcvDgramCtx = parameters->EventContext;
  2084. }
  2085. else
  2086. {
  2087. status = STATUS_INSUFFICIENT_RESOURCES;
  2088. }
  2089. RELEASE_SPIN_LOCK(&pDdpAddr->ddpao_Lock, OldIrql);
  2090. break;
  2091. case TDI_EVENT_ERROR:
  2092. break;
  2093. case TDI_EVENT_CONNECT:
  2094. switch (devType)
  2095. {
  2096. case ATALK_DEV_ADSP:
  2097. pAdspAddr = (PADSP_ADDROBJ)pObject;
  2098. if (!(VALID_ADSPAO(pAdspAddr)))
  2099. {
  2100. ASSERT(0);
  2101. status = STATUS_INVALID_ADDRESS;
  2102. break;
  2103. }
  2104. ACQUIRE_SPIN_LOCK(&pAdspAddr->adspao_Lock, &OldIrql);
  2105. if (pAdspAddr->adspao_Flags & ADSPAO_CONNECT)
  2106. {
  2107. status = STATUS_INVALID_ADDRESS;
  2108. }
  2109. else
  2110. {
  2111. pAdspAddr->adspao_ConnHandler = (PTDI_IND_CONNECT)parameters->EventHandler;
  2112. pAdspAddr->adspao_ConnHandlerCtx = parameters->EventContext;
  2113. pAdspAddr->adspao_Flags |= ADSPAO_LISTENER;
  2114. }
  2115. RELEASE_SPIN_LOCK(&pAdspAddr->adspao_Lock, OldIrql);
  2116. break;
  2117. case ATALK_DEV_PAP:
  2118. pPapAddr = (PPAP_ADDROBJ)pObject;
  2119. if (!(VALID_PAPAO(pPapAddr)))
  2120. {
  2121. ASSERT(0);
  2122. status = STATUS_INVALID_ADDRESS;
  2123. break;
  2124. }
  2125. ACQUIRE_SPIN_LOCK(&pPapAddr->papao_Lock, &OldIrql);
  2126. if (pPapAddr->papao_Flags & PAPAO_CONNECT)
  2127. {
  2128. status = STATUS_INVALID_ADDRESS;
  2129. }
  2130. else
  2131. {
  2132. pPapAddr->papao_Flags |= (PAPAO_LISTENER | PAPAO_UNBLOCKED);
  2133. // If we are setting a null handler, set it to blocked.
  2134. if ((pPapAddr->papao_ConnHandler = (PTDI_IND_CONNECT)parameters->EventHandler) == NULL)
  2135. {
  2136. // Oops. block. Dont care about listens being posted here.
  2137. pPapAddr->papao_Flags &= ~PAPAO_UNBLOCKED;
  2138. }
  2139. pPapAddr->papao_ConnHandlerCtx = parameters->EventContext;
  2140. }
  2141. RELEASE_SPIN_LOCK(&pPapAddr->papao_Lock, OldIrql);
  2142. if (NT_SUCCESS(status))
  2143. {
  2144. // Prime the listener.
  2145. if (!ATALK_SUCCESS(AtalkPapPrimeListener(pPapAddr)))
  2146. {
  2147. TMPLOGERR();
  2148. }
  2149. }
  2150. break;
  2151. case ATALK_DEV_ASPC:
  2152. // No listens here. Client side only.
  2153. status = STATUS_INVALID_ADDRESS;
  2154. break;
  2155. default:
  2156. status = STATUS_INVALID_DEVICE_REQUEST;
  2157. break;
  2158. }
  2159. break;
  2160. case TDI_EVENT_RECEIVE:
  2161. switch (devType)
  2162. {
  2163. case ATALK_DEV_ADSP:
  2164. pAdspAddr = (PADSP_ADDROBJ)pObject;
  2165. if (!(VALID_ADSPAO(pAdspAddr)))
  2166. {
  2167. ASSERT(0);
  2168. status = STATUS_INVALID_ADDRESS;
  2169. break;
  2170. }
  2171. ACQUIRE_SPIN_LOCK(&pAdspAddr->adspao_Lock, &OldIrql);
  2172. pAdspAddr->adspao_RecvHandler = (PTDI_IND_RECEIVE)parameters->EventHandler;
  2173. pAdspAddr->adspao_RecvHandlerCtx = parameters->EventContext;
  2174. RELEASE_SPIN_LOCK(&pAdspAddr->adspao_Lock, OldIrql);
  2175. break;
  2176. case ATALK_DEV_PAP:
  2177. pPapAddr = (PPAP_ADDROBJ)pObject;
  2178. if (!(VALID_PAPAO(pPapAddr)))
  2179. {
  2180. ASSERT(0);
  2181. status = STATUS_INVALID_ADDRESS;
  2182. break;
  2183. }
  2184. ACQUIRE_SPIN_LOCK(&pPapAddr->papao_Lock, &OldIrql);
  2185. pPapAddr->papao_RecvHandler = (PTDI_IND_RECEIVE)parameters->EventHandler;
  2186. pPapAddr->papao_RecvHandlerCtx = parameters->EventContext;
  2187. RELEASE_SPIN_LOCK(&pPapAddr->papao_Lock, OldIrql);
  2188. break;
  2189. case ATALK_DEV_ASPC:
  2190. // No receives in asp client
  2191. status = STATUS_SUCCESS;
  2192. break;
  2193. default:
  2194. status = STATUS_INVALID_DEVICE_REQUEST;
  2195. break;
  2196. }
  2197. break;
  2198. case TDI_EVENT_RECEIVE_EXPEDITED:
  2199. switch (devType)
  2200. {
  2201. case ATALK_DEV_ADSP:
  2202. pAdspAddr = (PADSP_ADDROBJ)pObject;
  2203. if (!(VALID_ADSPAO(pAdspAddr)))
  2204. {
  2205. ASSERT(0);
  2206. status = STATUS_INVALID_ADDRESS;
  2207. break;
  2208. }
  2209. ACQUIRE_SPIN_LOCK(&pAdspAddr->adspao_Lock, &OldIrql);
  2210. pAdspAddr->adspao_ExpRecvHandler = (PTDI_IND_RECEIVE_EXPEDITED)parameters->EventHandler;
  2211. pAdspAddr->adspao_ExpRecvHandlerCtx = parameters->EventContext;
  2212. RELEASE_SPIN_LOCK(&pAdspAddr->adspao_Lock, OldIrql);
  2213. break;
  2214. case ATALK_DEV_ASPC:
  2215. pAspAddr = (PASPC_ADDROBJ)pObject;
  2216. if (!(VALID_ASPCAO(pAspAddr)))
  2217. {
  2218. ASSERT(0);
  2219. status = STATUS_INVALID_ADDRESS;
  2220. break;
  2221. }
  2222. ACQUIRE_SPIN_LOCK(&pAspAddr->aspcao_Lock, &OldIrql);
  2223. pAspAddr->aspcao_ExpRecvHandler = (PTDI_IND_RECEIVE_EXPEDITED)parameters->EventHandler;
  2224. pAspAddr->aspcao_ExpRecvHandlerCtx = parameters->EventContext;
  2225. RELEASE_SPIN_LOCK(&pAspAddr->aspcao_Lock, OldIrql);
  2226. break;
  2227. default:
  2228. status = STATUS_INVALID_DEVICE_REQUEST;
  2229. break;
  2230. }
  2231. break;
  2232. case TDI_EVENT_DISCONNECT:
  2233. switch (devType)
  2234. {
  2235. case ATALK_DEV_ADSP:
  2236. pAdspAddr = (PADSP_ADDROBJ)pObject;
  2237. if (!(VALID_ADSPAO(pAdspAddr)))
  2238. {
  2239. ASSERT(0);
  2240. status = STATUS_INVALID_ADDRESS;
  2241. break;
  2242. }
  2243. ACQUIRE_SPIN_LOCK(&pAdspAddr->adspao_Lock, &OldIrql);
  2244. pAdspAddr->adspao_DisconnectHandler = (PTDI_IND_DISCONNECT)parameters->EventHandler;
  2245. pAdspAddr->adspao_DisconnectHandlerCtx = parameters->EventContext;
  2246. RELEASE_SPIN_LOCK(&pAdspAddr->adspao_Lock, OldIrql);
  2247. break;
  2248. case ATALK_DEV_PAP:
  2249. pPapAddr = (PPAP_ADDROBJ)pObject;
  2250. if (!(VALID_PAPAO(pPapAddr)))
  2251. {
  2252. ASSERT(0);
  2253. status = STATUS_INVALID_ADDRESS;
  2254. break;
  2255. }
  2256. ACQUIRE_SPIN_LOCK(&pPapAddr->papao_Lock, &OldIrql);
  2257. pPapAddr->papao_DisconnectHandler = (PTDI_IND_DISCONNECT)parameters->EventHandler;
  2258. pPapAddr->papao_DisconnectHandlerCtx = parameters->EventContext;
  2259. RELEASE_SPIN_LOCK(&pPapAddr->papao_Lock, OldIrql);
  2260. break;
  2261. case ATALK_DEV_ASPC:
  2262. pAspAddr = (PASPC_ADDROBJ)pObject;
  2263. if (!(VALID_ASPCAO(pAspAddr)))
  2264. {
  2265. ASSERT(0);
  2266. status = STATUS_INVALID_ADDRESS;
  2267. break;
  2268. }
  2269. ACQUIRE_SPIN_LOCK(&pAspAddr->aspcao_Lock, &OldIrql);
  2270. pAspAddr->aspcao_DisconnectHandler = (PTDI_IND_DISCONNECT)parameters->EventHandler;
  2271. pAspAddr->aspcao_DisconnectHandlerCtx= parameters->EventContext;
  2272. RELEASE_SPIN_LOCK(&pAspAddr->aspcao_Lock, OldIrql);
  2273. break;
  2274. default:
  2275. status = STATUS_INVALID_DEVICE_REQUEST;
  2276. break;
  2277. }
  2278. break;
  2279. case TDI_EVENT_SEND_POSSIBLE:
  2280. switch (devType)
  2281. {
  2282. case ATALK_DEV_ADSP:
  2283. pAdspAddr = (PADSP_ADDROBJ)pObject;
  2284. if (!(VALID_ADSPAO(pAdspAddr)))
  2285. {
  2286. ASSERT(0);
  2287. status = STATUS_INVALID_ADDRESS;
  2288. break;
  2289. }
  2290. ACQUIRE_SPIN_LOCK(&pAdspAddr->adspao_Lock, &OldIrql);
  2291. pAdspAddr->adspao_SendPossibleHandler = (PTDI_IND_SEND_POSSIBLE)parameters->EventHandler;
  2292. pAdspAddr->adspao_SendPossibleHandlerCtx = parameters->EventContext;
  2293. RELEASE_SPIN_LOCK(&pAdspAddr->adspao_Lock, OldIrql);
  2294. break;
  2295. case ATALK_DEV_PAP:
  2296. pPapAddr = (PPAP_ADDROBJ)pObject;
  2297. if (!(VALID_PAPAO(pPapAddr)))
  2298. {
  2299. ASSERT(0);
  2300. status = STATUS_INVALID_ADDRESS;
  2301. break;
  2302. }
  2303. ACQUIRE_SPIN_LOCK(&pPapAddr->papao_Lock, &OldIrql);
  2304. pPapAddr->papao_SendPossibleHandler = (PTDI_IND_SEND_POSSIBLE)parameters->EventHandler;
  2305. pPapAddr->papao_SendPossibleHandlerCtx = parameters->EventContext;
  2306. RELEASE_SPIN_LOCK(&pPapAddr->papao_Lock, OldIrql);
  2307. break;
  2308. case ATALK_DEV_ASPC:
  2309. // No sends in asp client
  2310. status = STATUS_SUCCESS;
  2311. break;
  2312. default:
  2313. status = STATUS_INVALID_DEVICE_REQUEST;
  2314. break;
  2315. }
  2316. break;
  2317. default:
  2318. status = STATUS_INVALID_PARAMETER;
  2319. }
  2320. #if DBG
  2321. // Avoid assertions in AFD.
  2322. status = STATUS_SUCCESS;
  2323. #endif
  2324. } while (FALSE);
  2325. return status;
  2326. }
  2327. VOID
  2328. AtalkTdiCancel(
  2329. IN OUT PATALK_DEV_OBJ pDevObj,
  2330. IN PIRP pIrp
  2331. )
  2332. /*++
  2333. Routine Description:
  2334. This routine handles cancellation of IO requests
  2335. Arguments:
  2336. Return Value:
  2337. --*/
  2338. {
  2339. PIO_STACK_LOCATION pIrpSp;
  2340. PVOID pObject;
  2341. PATALK_DEV_CTX pCtx;
  2342. PVOID FsContext2;
  2343. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  2344. pObject = pIrpSp->FileObject->FsContext;
  2345. FsContext2 = pIrpSp->FileObject->FsContext2;
  2346. pCtx = &pDevObj->Ctx;
  2347. ASSERT(((LONG_PTR)FsContext2 >> 16) == pCtx->adc_DevType);
  2348. IoReleaseCancelSpinLock (pIrp->CancelIrql);
  2349. switch (pCtx->adc_DevType)
  2350. {
  2351. case ATALK_DEV_DDP:
  2352. break;
  2353. case ATALK_DEV_ASPC:
  2354. if (FsContext2 == (PVOID)((ULONG_PTR)(TDI_CONNECTION_FILE + (pCtx->adc_DevType << 16))))
  2355. {
  2356. AtalkAspCCleanupConnection((PASPC_CONNOBJ)pObject);
  2357. }
  2358. else
  2359. {
  2360. AtalkAspCCleanupAddress((PASPC_ADDROBJ)pObject);
  2361. }
  2362. break;
  2363. case ATALK_DEV_ASP:
  2364. // We only handle cancellation of IO requests on connection objects.
  2365. if (FsContext2 == (PVOID)((ULONG_PTR)(TDI_CONNECTION_FILE + (pCtx->adc_DevType << 16))))
  2366. AtalkAspCleanupConnection((PASP_CONNOBJ)pObject);
  2367. break;
  2368. case ATALK_DEV_PAP:
  2369. if (FsContext2 == (PVOID)((ULONG_PTR)(TDI_CONNECTION_FILE + (pCtx->adc_DevType << 16))))
  2370. {
  2371. AtalkPapCleanupConnection((PPAP_CONNOBJ)pObject);
  2372. }
  2373. else
  2374. {
  2375. AtalkPapCleanupAddress((PPAP_ADDROBJ)pObject);
  2376. }
  2377. break;
  2378. case ATALK_DEV_ADSP:
  2379. if (FsContext2 == (PVOID)((ULONG_PTR)(TDI_CONNECTION_FILE + (pCtx->adc_DevType << 16))))
  2380. AtalkAdspCleanupConnection((PADSP_CONNOBJ)pObject);
  2381. else AtalkAdspCleanupAddress((PADSP_ADDROBJ)pObject);
  2382. break;
  2383. case ATALK_DEV_ARAP:
  2384. ArapCancelIrp(pIrp);
  2385. break;
  2386. default:
  2387. // The device type in the Ctx field can never be anything
  2388. // other than the above! Internal protocol error.
  2389. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2390. ("AtalkTdiCancel: Invalid device type\n"));
  2391. break;
  2392. }
  2393. }
  2394. VOID
  2395. AtalkQueryInitProviderInfo(
  2396. IN ATALK_DEV_TYPE DeviceType,
  2397. IN OUT PTDI_PROVIDER_INFO ProviderInfo
  2398. )
  2399. {
  2400. //
  2401. // Initialize to defaults first
  2402. //
  2403. RtlZeroMemory((PVOID)ProviderInfo, sizeof(TDI_PROVIDER_INFO));
  2404. ProviderInfo->Version = ATALK_TDI_PROVIDERINFO_VERSION;
  2405. KeQuerySystemTime (&ProviderInfo->StartTime);
  2406. switch (DeviceType)
  2407. {
  2408. case ATALK_DEV_DDP:
  2409. ProviderInfo->MaxDatagramSize = ATALK_DDP_PINFODGRAMSIZE;
  2410. ProviderInfo->ServiceFlags = ATALK_DDP_PINFOSERVICEFLAGS;
  2411. break;
  2412. case ATALK_DEV_PAP:
  2413. ProviderInfo->MaxSendSize = ATALK_PAP_PINFOSENDSIZE;
  2414. ProviderInfo->ServiceFlags = ATALK_PAP_PINFOSERVICEFLAGS;
  2415. break;
  2416. case ATALK_DEV_ADSP:
  2417. ProviderInfo->MaxSendSize = ATALK_ADSP_PINFOSENDSIZE;
  2418. ProviderInfo->ServiceFlags = ATALK_ADSP_PINFOSERVICEFLAGS;
  2419. break;
  2420. case ATALK_DEV_ASP:
  2421. ProviderInfo->MaxSendSize = ATALK_ASP_PINFOSENDSIZE;
  2422. ProviderInfo->ServiceFlags = ATALK_ASP_PINFOSERVICEFLAGS;
  2423. break;
  2424. case ATALK_DEV_ARAP:
  2425. ProviderInfo->MaxSendSize = ATALK_ARAP_PINFOSENDSIZE;
  2426. ProviderInfo->ServiceFlags = ATALK_ARAP_PINFOSERVICEFLAGS;
  2427. break;
  2428. case ATALK_DEV_ASPC:
  2429. ProviderInfo->MaxSendSize = ATALK_ASP_PINFOSENDSIZE;
  2430. ProviderInfo->ServiceFlags = ATALK_ASP_PINFOSERVICEFLAGS;
  2431. break;
  2432. default:
  2433. KeBugCheck(0);
  2434. }
  2435. }
  2436. LOCAL VOID FASTCALL
  2437. atalkTdiSendDgramComplete(
  2438. IN NDIS_STATUS Status,
  2439. IN PSEND_COMPL_INFO pSendInfo
  2440. )
  2441. {
  2442. PDDP_ADDROBJ pAddr = (PDDP_ADDROBJ)(pSendInfo->sc_Ctx1);
  2443. PBUFFER_DESC pBufDesc = (PBUFFER_DESC)(pSendInfo->sc_Ctx2);
  2444. PIRP pIrp = (PIRP)(pSendInfo->sc_Ctx3);
  2445. ASSERT(VALID_DDP_ADDROBJ(pAddr));
  2446. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2447. ("atalkTdiSendDgramComplete: Status %lx, addr %lx\n", Status, pAddr));
  2448. AtalkFreeBuffDesc(pBufDesc);
  2449. pIrp->CancelRoutine = NULL;
  2450. TdiCompleteRequest(pIrp,
  2451. ((Status == NDIS_STATUS_SUCCESS) ?
  2452. STATUS_SUCCESS: STATUS_UNSUCCESSFUL));
  2453. }
  2454. LOCAL VOID
  2455. atalkTdiRecvDgramComplete(
  2456. IN ATALK_ERROR ErrorCode,
  2457. IN PAMDL pReadBuf,
  2458. IN USHORT ReadLen,
  2459. IN PATALK_ADDR pSrcAddr,
  2460. IN PIRP pIrp
  2461. )
  2462. {
  2463. PIO_STACK_LOCATION pIrpSp;
  2464. PTDI_REQUEST_KERNEL_RECEIVEDG parameters;
  2465. PTDI_CONNECTION_INFORMATION returnInfo;
  2466. PTA_APPLETALK_ADDRESS remoteAddress;
  2467. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2468. ("atalkTdiRecvDgramComplete: %lx\n", ErrorCode));
  2469. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  2470. parameters = (PTDI_REQUEST_KERNEL_RECEIVEDG)&pIrpSp->Parameters;
  2471. // Set length in the info field and call the completion routine.
  2472. pIrp->CancelRoutine = NULL;
  2473. pIrp->IoStatus.Information = (ULONG)ReadLen;
  2474. if (ATALK_SUCCESS(ErrorCode))
  2475. {
  2476. ASSERT(parameters != NULL);
  2477. if (parameters != NULL)
  2478. {
  2479. parameters->ReceiveLength = (ULONG)ReadLen;
  2480. try {
  2481. returnInfo =
  2482. (PTDI_CONNECTION_INFORMATION)parameters->ReturnDatagramInformation;
  2483. ASSERT(returnInfo != NULL);
  2484. if (returnInfo != NULL)
  2485. {
  2486. if (returnInfo->RemoteAddressLength >= sizeof(TA_APPLETALK_ADDRESS))
  2487. {
  2488. // Fill in the remote address
  2489. remoteAddress = (PTA_APPLETALK_ADDRESS)returnInfo->RemoteAddress;
  2490. ASSERT(remoteAddress != NULL);
  2491. if (remoteAddress != NULL)
  2492. {
  2493. // Copy the remote address from where the datagram was received
  2494. ATALKADDR_TO_TDI(
  2495. remoteAddress,
  2496. pSrcAddr);
  2497. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_ERR,
  2498. ("AtalkAddrRecvDgComp - Net %x Node %x Socket %x\n",
  2499. remoteAddress->Address[0].Address[0].Network,
  2500. remoteAddress->Address[0].Address[0].Node,
  2501. remoteAddress->Address[0].Address[0].Socket));
  2502. }
  2503. }
  2504. }
  2505. } except( EXCEPTION_EXECUTE_HANDLER ) {
  2506. ErrorCode = GetExceptionCode();
  2507. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2508. ("atalkTdiRecvDgramComplete: exception occured %lx\n", ErrorCode));
  2509. }
  2510. }
  2511. }
  2512. ASSERT (ErrorCode != ATALK_PENDING);
  2513. TdiCompleteRequest(pIrp, AtalkErrorToNtStatus(ErrorCode));
  2514. }
  2515. LOCAL VOID
  2516. atalkTdiActionComplete(
  2517. IN ATALK_ERROR ErrorCode,
  2518. IN PACTREQ pActReq
  2519. )
  2520. {
  2521. PIRP pIrp = pActReq->ar_pIrp;
  2522. ASSERT (VALID_ACTREQ(pActReq));
  2523. if (pActReq->ar_pAMdl != NULL)
  2524. AtalkFreeAMdl(pActReq->ar_pAMdl);
  2525. AtalkFreeMemory(pActReq);
  2526. pIrp->CancelRoutine = NULL;
  2527. ASSERT (ErrorCode != ATALK_PENDING);
  2528. TdiCompleteRequest(pIrp, AtalkErrorToNtStatus(ErrorCode));
  2529. }
  2530. LOCAL VOID
  2531. atalkTdiGenericComplete(
  2532. IN ATALK_ERROR ErrorCode,
  2533. IN PIRP pIrp
  2534. )
  2535. {
  2536. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  2537. ("atalkTdiGenericComplete: Completing %lx with %lx\n",
  2538. pIrp, AtalkErrorToNtStatus(ErrorCode)));
  2539. pIrp->CancelRoutine = NULL;
  2540. ASSERT (ErrorCode != ATALK_PENDING);
  2541. TdiCompleteRequest(pIrp, AtalkErrorToNtStatus(ErrorCode));
  2542. }
  2543. LOCAL VOID
  2544. atalkTdiCloseAddressComplete(
  2545. IN ATALK_ERROR ErrorCode,
  2546. IN PIRP pIrp
  2547. )
  2548. {
  2549. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  2550. ("atalkTdiCloseAddressComplete: Completing %lx with %lx\n",
  2551. pIrp, AtalkErrorToNtStatus(ErrorCode)));
  2552. pIrp->CancelRoutine = NULL;
  2553. ASSERT (ErrorCode != ATALK_PENDING);
  2554. AtalkUnlockTdiIfNecessary();
  2555. TdiCompleteRequest(pIrp, AtalkErrorToNtStatus(ErrorCode));
  2556. }
  2557. LOCAL VOID
  2558. atalkTdiGenericReadComplete(
  2559. IN ATALK_ERROR ErrorCode,
  2560. IN PAMDL ReadBuf,
  2561. IN USHORT ReadLen,
  2562. IN ULONG ReadFlags,
  2563. IN PIRP pIrp
  2564. )
  2565. {
  2566. ASSERT(pIrp->IoStatus.Status != STATUS_UNSUCCESSFUL);
  2567. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  2568. ("atalkTdiGenericReadComplete: Irp %lx Status %lx Info %lx\n",
  2569. pIrp, pIrp->IoStatus.Status, ReadLen));
  2570. pIrp->CancelRoutine = NULL;
  2571. pIrp->IoStatus.Information = (ULONG)ReadLen;
  2572. ASSERT (ErrorCode != ATALK_PENDING);
  2573. TdiCompleteRequest(pIrp, AtalkErrorToNtStatus(ErrorCode));
  2574. }
  2575. VOID
  2576. atalkTdiGenericWriteComplete(
  2577. IN ATALK_ERROR ErrorCode,
  2578. IN PAMDL WriteBuf,
  2579. IN USHORT WriteLen,
  2580. IN PIRP pIrp
  2581. )
  2582. {
  2583. ASSERT(pIrp->IoStatus.Status != STATUS_UNSUCCESSFUL);
  2584. if (pIrp->IoStatus.Status == STATUS_UNSUCCESSFUL)
  2585. {
  2586. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_ERR,
  2587. ("atalkTdiGenericWriteComplete: Irp %lx Status %lx Info %lx\n",
  2588. pIrp, pIrp->IoStatus.Status, WriteLen));
  2589. }
  2590. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_INFO,
  2591. ("atalkTdiGenericWriteComplete: Irp %lx Status %lx Info %lx\n",
  2592. pIrp, pIrp->IoStatus.Status, WriteLen));
  2593. pIrp->CancelRoutine = NULL;
  2594. pIrp->IoStatus.Information = (ULONG)WriteLen;
  2595. ASSERT (ErrorCode != ATALK_PENDING);
  2596. TdiCompleteRequest(pIrp, AtalkErrorToNtStatus(ErrorCode));
  2597. }
  2598. LOCAL VOID
  2599. atalkQueuedLockUnlock(
  2600. IN PQLU pQLU
  2601. )
  2602. {
  2603. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  2604. AtalkLockUnlock(FALSE,
  2605. pQLU->qlu_pLockSection);
  2606. AtalkPortDereference(pQLU->qlu_pPortDesc);
  2607. AtalkFreeMemory(pQLU);
  2608. }
  2609. VOID
  2610. AtalkLockInit(
  2611. IN PLOCK_SECTION pLs,
  2612. IN PVOID Address
  2613. )
  2614. {
  2615. pLs->ls_LockHandle = MmLockPagableCodeSection(Address);
  2616. MmUnlockPagableImageSection(pLs->ls_LockHandle);
  2617. }
  2618. VOID
  2619. AtalkLockUnlock(
  2620. IN BOOLEAN Lock,
  2621. IN PLOCK_SECTION pLs
  2622. )
  2623. {
  2624. KIRQL OldIrql;
  2625. BOOLEAN DoForReal;
  2626. // We cannot call the MmLock/MmUnlock routines at Dpc. So if we are called at
  2627. // DISPATCH, just queue ourselves. Also we only get unlock requests at DISPATCH,
  2628. // Lock requests are only at LOW_LEVEL. So failure to allocate memory can be
  2629. // IGNORED since that will only have the effect of failure to unlock.
  2630. if (KeGetCurrentIrql() == DISPATCH_LEVEL)
  2631. {
  2632. PQLU pQLU;
  2633. ATALK_ERROR Error;
  2634. ASSERT (!Lock || (pLs->ls_LockCount > 0));
  2635. if (Lock)
  2636. {
  2637. ASSERT (pLs->ls_LockCount > 0);
  2638. ACQUIRE_SPIN_LOCK_DPC(&AtalkPgLkLock);
  2639. pLs->ls_LockCount ++;
  2640. RELEASE_SPIN_LOCK_DPC(&AtalkPgLkLock);
  2641. }
  2642. else
  2643. {
  2644. if ((pQLU = AtalkAllocMemory(sizeof(QLU))) != NULL)
  2645. {
  2646. pQLU->qlu_pPortDesc = AtalkPortList;
  2647. AtalkPortReferenceByPtrDpc(pQLU->qlu_pPortDesc, &Error);
  2648. if (ATALK_SUCCESS(Error))
  2649. {
  2650. pQLU->qlu_pLockSection = pLs;
  2651. ExInitializeWorkItem(&pQLU->qlu_WQI, atalkQueuedLockUnlock, pQLU);
  2652. ExQueueWorkItem(&pQLU->qlu_WQI, CriticalWorkQueue);
  2653. }
  2654. else
  2655. {
  2656. AtalkFreeMemory(pQLU);
  2657. }
  2658. }
  2659. }
  2660. return;
  2661. }
  2662. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  2663. // We need to serialize the operations here. Note that a spin-lock will not do the
  2664. // job since the MmLock/MmUnlock routines cannot be called with the spin-lock held
  2665. KeWaitForSingleObject(&AtalkPgLkMutex,
  2666. Executive,
  2667. KernelMode,
  2668. TRUE,
  2669. (PLARGE_INTEGER)NULL);
  2670. ASSERT (pLs->ls_LockHandle != NULL);
  2671. DoForReal = FALSE;
  2672. ACQUIRE_SPIN_LOCK(&AtalkPgLkLock, &OldIrql);
  2673. if (Lock)
  2674. {
  2675. if (pLs->ls_LockCount == 0)
  2676. {
  2677. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_WARN,
  2678. ("AtalkLockUnlock: Locking %d\n", pLs - AtalkPgLkSection));
  2679. DoForReal = TRUE;
  2680. }
  2681. pLs->ls_LockCount ++;
  2682. }
  2683. else
  2684. {
  2685. ASSERT (pLs->ls_LockCount > 0);
  2686. pLs->ls_LockCount --;
  2687. if (pLs->ls_LockCount == 0)
  2688. {
  2689. DBGPRINT(DBG_COMP_TDI, DBG_LEVEL_WARN,
  2690. ("AtalkLockUnlock: Unlocking %d\n", pLs - AtalkPgLkSection));
  2691. DoForReal = TRUE;
  2692. }
  2693. }
  2694. RELEASE_SPIN_LOCK(&AtalkPgLkLock, OldIrql);
  2695. if (DoForReal)
  2696. {
  2697. if (Lock)
  2698. {
  2699. MmLockPagableSectionByHandle(pLs->ls_LockHandle);
  2700. }
  2701. else
  2702. {
  2703. MmUnlockPagableImageSection(pLs->ls_LockHandle);
  2704. }
  2705. }
  2706. // LeaveCriticalSection
  2707. KeReleaseMutex(&AtalkPgLkMutex, FALSE);
  2708. }
  2709. VOID
  2710. atalkWaitDefaultPort(
  2711. VOID
  2712. )
  2713. {
  2714. TIME Time;
  2715. #define ONE_SEC_IN_100ns -10000000L // 1sec in 100ns units
  2716. if ((AtalkDefaultPort == NULL) ||
  2717. ((AtalkDefaultPort->pd_Flags & (PD_USER_NODE_1 | PD_USER_NODE_2)) == 0))
  2718. {
  2719. // Make sure we can indeed wait
  2720. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  2721. Time.QuadPart = Int32x32To64((LONG)20, ONE_SEC_IN_100ns);
  2722. KeWaitForSingleObject(&AtalkDefaultPortEvent, Executive, KernelMode, FALSE, &Time);
  2723. }
  2724. }