Leaked source code of windows server 2003
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.

1355 lines
36 KiB

  1. /*++
  2. Copyright (c) 1989-1994 Microsoft Corporation
  3. Module Name;
  4. Rt.c
  5. Abstract;
  6. Author;
  7. Revision History;
  8. TODO: Get rid of ref/Deref since the RTINFO structure will not be destroyed
  9. Use a common alloc/free function (with the rest of ipx)
  10. Allocate tagged memory
  11. Optimize code more
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // function prototypes
  17. //
  18. VOID
  19. RtIrpCancel(
  20. IN PDEVICE_OBJECT Device,
  21. IN PIRP pIrp
  22. );
  23. PVOID
  24. RtAllocMem(
  25. IN ULONG Size
  26. );
  27. VOID
  28. RtFreeMem(
  29. IN PVOID pBuffer,
  30. IN ULONG Size
  31. );
  32. NTSTATUS
  33. NTCheckSetCancelRoutine(
  34. IN PIRP pIrp,
  35. IN PVOID CancelRoutine,
  36. IN PDEVICE pDevice
  37. );
  38. VOID
  39. NTIoComplete(
  40. IN PIRP pIrp,
  41. IN NTSTATUS Status,
  42. IN ULONG SentLength);
  43. NTSTATUS
  44. CleanupRtAddress(
  45. IN PDEVICE pDevice,
  46. IN PIRP pIrp);
  47. NTSTATUS
  48. CloseRtAddress(
  49. IN PDEVICE pDevice,
  50. IN PIRP pIrp);
  51. NTSTATUS
  52. SendIrpFromRt (
  53. IN PDEVICE pDevice,
  54. IN PIRP pIrp
  55. );
  56. NTSTATUS
  57. RcvIrpFromRt (
  58. IN PDEVICE pDevice,
  59. IN PIRP pIrp
  60. );
  61. NTSTATUS
  62. PassDgToRt (
  63. IN PDEVICE pDevice,
  64. IN PIPX_DATAGRAM_OPTIONS2 pContext,
  65. IN ULONG Index,
  66. IN VOID UNALIGNED *pDgrm,
  67. IN ULONG uNumBytes
  68. );
  69. VOID
  70. IpxDerefRt(
  71. PRT_INFO pRt
  72. );
  73. VOID
  74. IpxRefRt(
  75. PRT_INFO pRt
  76. );
  77. VOID
  78. IpxDestroyRt(
  79. IN PRT_INFO pRt
  80. );
  81. #define ALLOC_PRAGMA 1
  82. #define CTEMakePageable(x, y) alloc_text(x,y)
  83. #define AllocMem(_BytesToAlloc) IpxAllocateMemory(_BytesToAlloc, MEMORY_PACKET, "RT MEMORY")
  84. #define FreeMem(_Memory, _BytesAllocated) IpxFreeMemory(_Memory, _BytesAllocated, MEMORY_PACKET, "RT MEMORY")
  85. #define IpxVerifyRt(pRt) // \
  86. // if ((pRt->Type != IPX_RT_SIGNATURE) || (pRt->Size != sizeof(RT_INFO))) { return STATUS_INVALID_ADDRESS; }
  87. //******************* Pageable Routine Declarations ****************
  88. #ifdef ALLOC_PRAGMA
  89. #pragma CTEMakePageable(PAGERT, CloseRtAddress)
  90. #pragma CTEMakePageable(PAGERT, CleanupRtAddress)
  91. #pragma CTEMakePageable(PAGERT, RcvIrpFromRt)
  92. #pragma CTEMakePageable(PAGERT, SendIrpFromRt)
  93. #pragma CTEMakePageable(PAGERT, PassDgToRt)
  94. #pragma CTEMakePageable(PAGERT, RtIrpCancel)
  95. #pragma CTEMakePageable(PAGERT, NTCheckSetCancelRoutine)
  96. #pragma CTEMakePageable(PAGERT, NTIoComplete)
  97. #pragma CTEMakePageable(PAGERT, RtFreeMem)
  98. #pragma CTEMakePageable(PAGERT, RtAllocMem)
  99. #pragma CTEMakePageable(PAGERT, IpxRefRt)
  100. #pragma CTEMakePageable(PAGERT, IpxDerefRt)
  101. #pragma CTEMakePageable(PAGERT, IpxDestroyRt)
  102. #endif
  103. //******************* Pageable Routine Declarations ****************
  104. HANDLE IpxRtDiscardableCodeHandle={0};
  105. PRT_INFO pRtInfo; //contains info about all rt opened end points
  106. NTSTATUS
  107. OpenRtAddress(
  108. IN PDEVICE pDevice,
  109. IN PREQUEST pIrp
  110. )
  111. {
  112. PRT_INFO pRt;
  113. CTELockHandle OldIrq;
  114. NTSTATUS status;
  115. ULONG SaveReqCode;
  116. IpxPrint0("OpenRtAddress - entered\n");
  117. //
  118. // if the RTINFO endpoint structure is not allocated, then allocate it
  119. // and initialize it. But first get the device lock. This gurantees that
  120. // we can not have two irps doing the creation at the same time
  121. //
  122. CTEGetLock(&pDevice->Lock, &OldIrq);
  123. if (!pRtInfo)
  124. {
  125. pRt = AllocMem(sizeof(RT_INFO));
  126. //
  127. // Do this after locking the pagable rtns.
  128. //
  129. // pRtInfo = pRt; //store it in pRtInfo. When irps come down from RM,
  130. // we can compare pRt passed in them with pRtInfo
  131. if (pRt)
  132. {
  133. RtlZeroMemory(pRt,sizeof(RT_INFO));
  134. IpxPrint1("OpenRtAddress: Initializing CompletedIrps for pRt=(%lx)\n", pRt);
  135. pRt->RcvMemoryMax = RT_MAX_BUFF_MEM; // max. memory we can allocate
  136. pRt->Type = IPX_RT_SIGNATURE;
  137. pRt->Size = sizeof(RT_INFO);
  138. pRt->pDevice = pDevice;
  139. IpxPrint1("OpenRtAddress: pRtInfo=(%lx)\n", pRt);
  140. IpxPrint1("Completed Irp list is (%lx)\n", IsListEmpty(&pRt->CompletedIrps));
  141. #if DBG
  142. RtlCopyMemory(pRt->Signature, "RTIF", sizeof("RTIF") - 1);
  143. #endif
  144. InitializeListHead(&pRt->CompletedIrps);
  145. InitializeListHead(&pRt->HolderIrpsList);
  146. }
  147. CTEFreeLock(&pDevice->Lock, OldIrq);
  148. }
  149. else
  150. {
  151. pRt = pRtInfo;
  152. CTEFreeLock(&pDevice->Lock, OldIrq);
  153. IpxPrint1("OpenRtAddress: RTINFO found = (%lx)\n", pRtInfo);
  154. }
  155. if (pRt)
  156. {
  157. // Page in the Rt Code, if it hasn't already been paged in.
  158. //
  159. if (!IpxRtDiscardableCodeHandle)
  160. {
  161. IpxRtDiscardableCodeHandle = MmLockPagableCodeSection( CloseRtAddress );
  162. pRtInfo = pRt; //store it in pRtInfo. When irps come down from RM,
  163. // we can compare pRt passed in them with pRtInfo
  164. }
  165. //
  166. // it could fail to lock the pages so check for that
  167. //
  168. if (IpxRtDiscardableCodeHandle)
  169. {
  170. ULONG i;
  171. status = STATUS_SUCCESS;
  172. IpxReferenceRt(pRtInfo, RT_CREATE);
  173. //
  174. // Find an empty slot and mark it open
  175. //
  176. CTEGetLock(&pRt->Lock, &OldIrq);
  177. for (i=0; i<IPX_RT_MAX_ADDRESSES; i++)
  178. {
  179. if (pRt->AddFl[i].State == RT_EMPTY)
  180. {
  181. break;
  182. }
  183. }
  184. if (i < IPX_RT_MAX_ADDRESSES)
  185. {
  186. pRt->AddFl[i].State = RT_OPEN;
  187. pRt->NoOfAdds++;
  188. pRt->AddFl[i].NoOfRcvIrps = 0; //Why wasn't this initialized before?
  189. InitializeListHead(&pRt->AddFl[i].RcvList);
  190. InitializeListHead(&pRt->AddFl[i].RcvIrpList);
  191. }
  192. else
  193. {
  194. CTEFreeLock(&pRt->Lock, OldIrq);
  195. IpxPrint1("OpenRtAddress; All %d slots used up\n", IPX_RT_MAX_ADDRESSES);
  196. IpxDereferenceRt(pRtInfo, RT_CREATE);
  197. status = STATUS_INSUFFICIENT_RESOURCES;
  198. goto RET;
  199. }
  200. CTEFreeLock(&pRt->Lock, OldIrq);
  201. //
  202. // Found an empty slot. Initialize all relevant info. and then
  203. // open an address object.
  204. //
  205. SaveReqCode = REQUEST_CODE(pIrp);
  206. REQUEST_CODE(pIrp) = MIPX_RT_CREATE;
  207. status = IpxOpenAddressM(pDevice, pIrp, i);
  208. REQUEST_CODE(pIrp) = SaveReqCode;
  209. IpxPrint1("After IpxOpenAddressM: Completed Irp list is (%lx)\n", IsListEmpty(&pRtInfo->CompletedIrps));
  210. if (status != STATUS_SUCCESS)
  211. {
  212. IpxPrint0("OpenRtAddress; Access Denied due to OpenAddress\n");
  213. IpxDereferenceRt(pRtInfo, RT_CREATE);
  214. CTEGetLock(&pRt->Lock, &OldIrq);
  215. pRt->AddFl[i].State = RT_EMPTY;
  216. pRt->NoOfAdds--;
  217. CTEFreeLock(&pRt->Lock, OldIrq);
  218. }
  219. else
  220. {
  221. CTEGetLock(&pRt->Lock, &OldIrq);
  222. pRt->AddFl[i].AddressFile = REQUEST_OPEN_CONTEXT(pIrp);
  223. CTEFreeLock(&pRt->Lock, OldIrq);
  224. //
  225. // No need to put pRt since it is global. We stick with the addressfile here.
  226. //
  227. // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)pRt;
  228. REQUEST_OPEN_TYPE(pIrp) = UlongToPtr(ROUTER_ADDRESS_FILE + i);
  229. IpxPrint1("OpenRtAdd: Index = (%d)\n", RT_ADDRESS_INDEX(pIrp));
  230. }
  231. }
  232. else
  233. {
  234. IpxPrint1("OpenRtAddress; All %d slots used up\n", IPX_RT_MAX_ADDRESSES);
  235. status = STATUS_INSUFFICIENT_RESOURCES;
  236. }
  237. }
  238. else
  239. {
  240. IpxPrint0("OpenRtCreate; Couldn't allocate a RT_INFO structure\n");
  241. CTEAssert(FALSE); //should never happen unless system is running
  242. //out of non-paged pool
  243. status = STATUS_INSUFFICIENT_RESOURCES;
  244. }
  245. RET:
  246. IpxPrint1("OpenRtAddress status prior to return= %X\n",status);
  247. return(status);
  248. }
  249. NTSTATUS
  250. CleanupRtAddress(
  251. IN PDEVICE pDevice,
  252. IN PIRP pIrp)
  253. /*++
  254. Routine Description;
  255. This Routine handles closing the Rt Object that is used by
  256. by RT to send and receive name service datagrams on port 137.
  257. Arguments;
  258. pIrp - a ptr to an IRP
  259. Return Value;
  260. NTSTATUS - status of the request
  261. --*/
  262. {
  263. NTSTATUS status;
  264. PRT_INFO pRt;
  265. CTELockHandle OldIrq;
  266. PLIST_ENTRY pHead;
  267. #ifdef SUNDOWN
  268. ULONG_PTR Index;
  269. #else
  270. ULONG Index;
  271. #endif
  272. PLIST_ENTRY pLE;
  273. PIRP pTmpIrp;
  274. IpxPrint0("CleanupRtAddress - entered\n");
  275. //
  276. // if the endpoint structure is allocated, then deallocate it
  277. //
  278. // pRt = REQUEST_OPEN_CONTEXT(pIrp);
  279. pRt = pRtInfo;
  280. Index = RT_ADDRESS_INDEX(pIrp);
  281. IpxPrint1("CleanupRtAdd: Index = (%d)\n", Index);
  282. IpxVerifyRt(pRt);
  283. CTEAssert(pRt && (pRt == pRtInfo));
  284. CTEAssert(Index < IPX_RT_MAX_ADDRESSES);
  285. do
  286. {
  287. PLIST_ENTRY pRcvEntry;
  288. PRTRCV_BUFFER pRcv;
  289. PRT_IRP pRtAddFl = &pRt->AddFl[Index];
  290. CTEAssert(pRtAddFl->State == RT_OPEN);
  291. IpxPrint1("CleanupRtAddress: Got AF handle = (%lx)\n", pRtAddFl);
  292. IpxReferenceRt(pRt, RT_CLEANUP);
  293. status = STATUS_SUCCESS;
  294. CTEGetLock (&pRt->Lock, &OldIrq);
  295. //
  296. // prevent any more dgram getting queued up
  297. //
  298. pRtAddFl->State = RT_CLOSING;
  299. CTEFreeLock (&pRt->Lock, OldIrq);
  300. //
  301. // free any rcv buffers that may be queued up
  302. //
  303. pHead = &pRtAddFl->RcvList;
  304. while (pRcvEntry = ExInterlockedRemoveHeadList(pHead, &pRt->Lock))
  305. {
  306. pRcv = CONTAINING_RECORD(pRcvEntry,RTRCV_BUFFER,Linkage);
  307. CTEAssert(pRcv);
  308. IpxPrint1("CleanupRtAddress:Freeing buffer = (%lx)\n", pRcv);
  309. RtFreeMem(pRcv,pRcv->TotalAllocSize);
  310. }
  311. //
  312. // Complete all irps that are queued
  313. //
  314. while (pLE = ExInterlockedRemoveHeadList(&pRtAddFl->RcvIrpList, &pRt->Lock)) {
  315. //
  316. // The recv irp is here so copy the data to its buffer and
  317. // pass it up to RT
  318. //
  319. pTmpIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
  320. IpxPrint1("CleanupRtAddress: Completing Rt rcv Irp from AdFl queue pIrp=%X\n" ,pTmpIrp);
  321. pTmpIrp->IoStatus.Information = 0;
  322. pTmpIrp->IoStatus.Status = STATUS_CANCELLED;
  323. NTIoComplete(pTmpIrp, (NTSTATUS)-1, (ULONG)-1);
  324. } //end of while
  325. //
  326. // dequeue and complete any irps on the complete queue.
  327. //
  328. while (pLE = ExInterlockedRemoveHeadList(&pRt->CompletedIrps, &pRt->Lock))
  329. {
  330. pTmpIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
  331. if (RT_ADDRESS_INDEX(pTmpIrp) == Index)
  332. {
  333. IpxPrint1("CleanupRtAddress:Completing Rt rcv Irp from CompleteIrps queue pIrp=%X\n" ,pTmpIrp);
  334. pTmpIrp->IoStatus.Information = 0;
  335. pTmpIrp->IoStatus.Status = STATUS_CANCELLED;
  336. NTIoComplete(pTmpIrp, (NTSTATUS)-1, (ULONG)-1);
  337. }
  338. else
  339. {
  340. ExInterlockedInsertHeadList(&pRt->HolderIrpsList, pLE, &pRt->Lock);
  341. }
  342. }
  343. CTEGetLock(&pRt->Lock, &OldIrq);
  344. while(!IsListEmpty(&pRt->HolderIrpsList))
  345. {
  346. pLE = RemoveHeadList(&pRt->HolderIrpsList);
  347. InsertHeadList(&pRt->CompletedIrps, pLE);
  348. }
  349. CTEFreeLock(&pRt->Lock, OldIrq);
  350. //
  351. // Store AF pointer in Irp since we will now be freeing the address file
  352. // (in driver.c).
  353. //
  354. //
  355. // We always have addressfile in the Irp
  356. //
  357. // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRtAddFl->AddressFile);
  358. IpxDereferenceRt(pRt, RT_CLEANUP);
  359. } while (FALSE);
  360. IpxPrint0("CleanupRtAddress: Return\n");
  361. return(status);
  362. }
  363. NTSTATUS
  364. CloseRtAddress(
  365. IN PDEVICE pDevice,
  366. IN PIRP pIrp)
  367. {
  368. NTSTATUS status;
  369. PRT_INFO pRt;
  370. CTELockHandle OldIrq;
  371. PLIST_ENTRY pHead;
  372. #ifdef SUNDOWN
  373. ULONG_PTR Index;
  374. #else
  375. ULONG Index;
  376. #endif
  377. IpxPrint0("CloseRtAddress - entered\n");
  378. // pRt = REQUEST_OPEN_CONTEXT(pIrp);
  379. pRt = pRtInfo;
  380. Index = RT_ADDRESS_INDEX(pIrp);
  381. IpxPrint1("CloseRtAdd: Index = (%d)\n", Index);
  382. IpxVerifyRt(pRt);
  383. CTEAssert(pRt && (pRt == pRtInfo));
  384. CTEAssert(Index < IPX_RT_MAX_ADDRESSES);
  385. CTEAssert(pRt->AddFl[Index].State == RT_CLOSING);
  386. // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRt->AddFl[Index].AddressFile);
  387. //REQUEST_OPEN_TYPE(pIrp) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  388. CTEGetLock(&pRt->Lock, &OldIrq);
  389. pRt->AddFl[Index].State = RT_EMPTY;
  390. pRt->NoOfAdds--;
  391. CTEFreeLock(&pRt->Lock, OldIrq);
  392. //
  393. // THis is a counter to the RT_CREATE
  394. //
  395. IpxDereferenceRt(pRt, RT_CLOSE);
  396. return(STATUS_SUCCESS);
  397. }
  398. //----------------------------------------------------------------------------
  399. NTSTATUS
  400. SendIrpFromRt (
  401. IN PDEVICE pDevice,
  402. IN PIRP pIrp
  403. )
  404. {
  405. CTELockHandle OldIrq;
  406. NTSTATUS Status;
  407. #ifdef SUNDOWN
  408. ULONG_PTR Index;
  409. #else
  410. ULONG Index;
  411. #endif
  412. PRT_INFO pRt;
  413. IpxPrint0("SendIrpfromRt - entered\n");
  414. // pRt = REQUEST_OPEN_CONTEXT(pIrp);
  415. pRt = pRtInfo;
  416. Index = RT_ADDRESS_INDEX(pIrp);
  417. IpxVerifyRt(pRt);
  418. CTEAssert(pRt && (pRt == pRtInfo));
  419. do {
  420. //
  421. // Check if the add. file slot indicates that it is OPEN. If it is
  422. // not open, then we should return STATUS_INVALID_HANDLE. The
  423. // reason why it may not be open is if we got a cleanup/close before
  424. // this irp.
  425. //
  426. CTEGetLock(&pRt->Lock, &OldIrq);
  427. if (pRt->AddFl[Index].State != RT_OPEN)
  428. {
  429. //
  430. // free the lock, set the status and break out
  431. //
  432. CTEFreeLock (&pRt->Lock, OldIrq);
  433. Status = STATUS_INVALID_HANDLE;
  434. break;
  435. }
  436. //
  437. // Let us reference the RtInfo structure so that it does not dissapear
  438. // and also for some accounting
  439. //
  440. IpxReferenceRt(pRt, RT_SEND);
  441. IpxPrint1("SendIrpFromRt: Index = (%d)\n", Index);
  442. //
  443. // Store the AF pointer since IpxTdiSendDatagram will use it. Free
  444. // the device lock since we have nothing more to do with our structures
  445. // here.
  446. //
  447. // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRtInfo->AddFl[Index].AddressFile);
  448. CTEFreeLock (&pRt->Lock, OldIrq);
  449. Status = IpxTdiSendDatagram(pDevice->DeviceObject, pIrp);
  450. //
  451. // All done with this send. Derefernce the RtInfo structure.
  452. //
  453. IpxDereferenceRt(pRtInfo, RT_SEND);
  454. } while(FALSE);
  455. IpxPrint0("SendIrpfromRt - leaving\n");
  456. return(Status);
  457. }
  458. NTSTATUS
  459. RcvIrpFromRt (
  460. IN PDEVICE pDevice,
  461. IN PIRP pIrp
  462. )
  463. /*++
  464. Routine Description;
  465. This function takes the rcv irp posted by RT and decides if there are
  466. any datagram queued waiting to go up to RT. If so then the datagram
  467. is copied to the RT buffer and passed back up. Otherwise the irp is
  468. held by Netbt until a datagram does come in.
  469. Arguments;
  470. pDevice - not used
  471. pIrp - Rt Rcv Irp
  472. Return Value;
  473. STATUS_PENDING if the buffer is to be held on to , the normal case.
  474. Notes;
  475. --*/
  476. {
  477. NTSTATUS status;
  478. PRTRCV_BUFFER pBuffer;
  479. PLIST_ENTRY pEntry;
  480. CTELockHandle OldIrq;
  481. PRT_INFO pRt;
  482. PIPX_DATAGRAM_OPTIONS2 pRtBuffer;
  483. PRT_IRP pRtAF;
  484. #ifdef SUNDOWN
  485. ULONG_PTR Index;
  486. #else
  487. ULONG Index;
  488. #endif
  489. #if DBG
  490. ULONG NoOfRcvIrp;
  491. #endif
  492. IpxPrint0("RcvIrpfromRt - Entered\n");
  493. // pRt = REQUEST_OPEN_CONTEXT(pIrp);
  494. pRt = pRtInfo;
  495. Index = RT_ADDRESS_INDEX(pIrp);
  496. IpxPrint1("RcvIrpFromRt: Index = (%d)\n", Index);
  497. IpxVerifyRt(pRt);
  498. CTEAssert(pRt && (pRt == pRtInfo));
  499. CTEAssert(Index < IPX_RT_MAX_ADDRESSES);
  500. CTEGetLock (&pRt->Lock, &OldIrq);
  501. do
  502. {
  503. pRtAF = &pRt->AddFl[Index];
  504. if (pRtAF->State != RT_OPEN)
  505. {
  506. status = STATUS_INVALID_HANDLE;
  507. CTEFreeLock (&pRt->Lock, OldIrq);
  508. break;
  509. }
  510. IpxReferenceRt(pRt, RT_IRPIN);
  511. if (!IsListEmpty(&pRtAF->RcvList))
  512. {
  513. PMDL pMdl;
  514. ULONG CopyLength;
  515. ULONG UserBufferLengthToPass;
  516. ULONG MdlLength;
  517. //
  518. // There is at least one datagram waiting to be received
  519. //
  520. pEntry = RemoveHeadList(&pRtAF->RcvList);
  521. pBuffer = (PRTRCV_BUFFER)CONTAINING_RECORD(pEntry,RTRCV_BUFFER,
  522. Linkage);
  523. IpxPrint0("RcvIrpFromRt: Buffer dequeued\n");
  524. //
  525. // Copy the datagram and the source address to RT buffer and
  526. // return to RT
  527. //
  528. pMdl = pIrp->MdlAddress;
  529. IpxPrint2("RcvIrpFromRt: Irp=(%lx); Mdl=(%lx)\n", pIrp, pMdl);
  530. CTEAssert(pMdl);
  531. if (!pMdl)
  532. {
  533. status = STATUS_BUFFER_TOO_SMALL;
  534. CTEFreeLock (&pRt->Lock, OldIrq);
  535. IpxDereferenceRt(pRtInfo, RT_IRPIN);
  536. break;
  537. }
  538. pRtBuffer = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
  539. if (!pRtBuffer) {
  540. status = STATUS_INSUFFICIENT_RESOURCES;
  541. CTEFreeLock (&pRt->Lock, OldIrq);
  542. IpxDereferenceRt(pRtInfo, RT_IRPIN);
  543. break;
  544. }
  545. MdlLength = MmGetMdlByteCount(pMdl);
  546. UserBufferLengthToPass = pBuffer->UserBufferLengthToPass;
  547. CopyLength = (UserBufferLengthToPass <= MdlLength) ? UserBufferLengthToPass : MdlLength;
  548. IpxPrint0("RcvIrpFromRt: Copying Options\n");
  549. RtlCopyMemory((PVOID)pRtBuffer,
  550. (PVOID)&pBuffer->Options,
  551. CopyLength);
  552. //
  553. // subtract from the total amount buffered for RT since we are
  554. // passing a datagram up to RT now.
  555. //
  556. pRtInfo->RcvMemoryAllocated -= pBuffer->TotalAllocSize;
  557. RtFreeMem(pBuffer, pBuffer->TotalAllocSize);
  558. CTEAssert(pRtBuffer->DgrmOptions.LocalTarget.NicId);
  559. //
  560. // pass the irp up to RT
  561. //
  562. if (CopyLength < UserBufferLengthToPass)
  563. {
  564. status = STATUS_BUFFER_OVERFLOW;
  565. }
  566. else
  567. {
  568. status = STATUS_SUCCESS;
  569. }
  570. #if DBG
  571. NoOfRcvIrp = pRtAF->NoOfRcvIrps;
  572. #endif
  573. CTEFreeLock (&pRt->Lock, OldIrq);
  574. IpxPrint3("Returning Rt rcv Irp immediately with queued dgram, status=%X,pIrp=%X. NoOfRcvIrp=(%d)\n" ,status,pIrp, NoOfRcvIrp);
  575. pIrp->IoStatus.Information = CopyLength;
  576. pIrp->IoStatus.Status = status;
  577. }
  578. else
  579. {
  580. status = NTCheckSetCancelRoutine(pIrp,RtIrpCancel,pDevice);
  581. if (!NT_SUCCESS(status))
  582. {
  583. CTEFreeLock (&pRt->Lock, OldIrq);
  584. }
  585. else
  586. {
  587. if (pRtAF->NoOfRcvIrps++ > RT_IRP_MAX)
  588. {
  589. IpxPrint1("RcvIrpFromRt; REACHED LIMIT OF IRPS. NoOfRcvIrp=(%d)\n", pRtAF->NoOfRcvIrps);
  590. status = STATUS_INSUFFICIENT_RESOURCES;
  591. pRtAF->NoOfRcvIrps--;
  592. CTEFreeLock (&pRt->Lock, OldIrq);
  593. }
  594. else
  595. {
  596. InsertTailList(&pRtAF->RcvIrpList,REQUEST_LINKAGE(pIrp));
  597. IpxPrint2("IpxRt;Holding onto Rt Rcv Irp, pIrp =%Xstatus=%X\n", status,pIrp);
  598. status = STATUS_PENDING;
  599. CTEFreeLock(&pRt->Lock,OldIrq);
  600. }
  601. }
  602. }
  603. IpxDereferenceRt(pRtInfo, RT_IRPIN);
  604. } while(FALSE);
  605. IpxPrint0("RcvIrpfromRt - Leaving\n");
  606. return(status);
  607. }
  608. //----------------------------------------------------------------------------
  609. NTSTATUS
  610. PassDgToRt (
  611. IN PDEVICE pDevice,
  612. IN PIPX_DATAGRAM_OPTIONS2 pContext,
  613. IN ULONG Index,
  614. IN VOID UNALIGNED *pDgrm,
  615. IN ULONG uNumBytes
  616. )
  617. /*++
  618. Routine Description;
  619. This function is used to allow NBT to pass name query service Pdu's to
  620. RT. Rt posts a Rcv irp to Netbt. If the Irp is here then simply
  621. copy the data to the irp and return it, otherwise buffer the data up
  622. to a maximum # of bytes. Beyond that limit the datagrams are discarded.
  623. If Retstatus is not success then the pdu will also be processed by
  624. nbt. This allows nbt to process packets when wins pauses and
  625. its list of queued buffers is exceeded.
  626. Arguments;
  627. pDevice - card that the request can in on
  628. pSrcAddress - source address
  629. pDgrm - ptr to the datagram
  630. uNumBytes - length of datagram
  631. Return Value;
  632. STATUS_PENDING if the buffer is to be held on to , the normal case.
  633. Notes;
  634. --*/
  635. {
  636. NTSTATUS status;
  637. PIPX_DATAGRAM_OPTIONS2 pRtBuffer;
  638. PIRP pIrp;
  639. CTELockHandle OldIrq;
  640. IpxPrint0("PassDgToRt - Entered\n");
  641. //
  642. // Get the source port and ip address, since RT needs this information.
  643. //
  644. IpxPrint1("PassDgToRt: Index = (%d)\n", Index);
  645. CTEGetLock(&pRtInfo->Lock,&OldIrq);
  646. do
  647. {
  648. PRT_IRP pRtAF = &pRtInfo->AddFl[Index];
  649. if (pRtAF->State != RT_OPEN)
  650. {
  651. CTEFreeLock(&pRtInfo->Lock,OldIrq);
  652. // 301920
  653. status = STATUS_UNSUCCESSFUL;
  654. break;
  655. }
  656. IpxReferenceRt(pRtInfo, RT_BUFF);
  657. if (IsListEmpty(&pRtAF->RcvIrpList))
  658. {
  659. IpxPrint0("PassDgToRt: No Rcv Irp\n");
  660. if (pRtInfo->RcvMemoryAllocated < pRtInfo->RcvMemoryMax)
  661. {
  662. PRTRCV_BUFFER pBuffer;
  663. pBuffer = RtAllocMem(uNumBytes + sizeof(RTRCV_BUFFER));
  664. if (pBuffer)
  665. {
  666. pBuffer->TotalAllocSize = uNumBytes + sizeof(RTRCV_BUFFER);
  667. //
  668. // Copy the user data
  669. //
  670. RtlCopyMemory(
  671. (PUCHAR)((PUCHAR)pBuffer + OFFSET_PKT_IN_RCVBUFF),
  672. (PVOID)pDgrm,uNumBytes);
  673. pBuffer->Options.DgrmOptions.LocalTarget.NicId =
  674. pContext->DgrmOptions.LocalTarget.NicId;
  675. pBuffer->Options.LengthOfExtraOpInfo = 0;
  676. //
  677. // total amount allocated for user
  678. //
  679. pBuffer->UserBufferLengthToPass = uNumBytes + OFFSET_PKT_IN_OPTIONS;
  680. CTEAssert(pContext->DgrmOptions.LocalTarget.NicId);
  681. IpxPrint2("PassDgToRt: Nic Id is (%d). BufferLength is (%lx)\n", pContext->DgrmOptions.LocalTarget.NicId, uNumBytes);
  682. //
  683. // Keep track of the total amount buffered so that we don't
  684. // eat up all non-paged pool buffering for RT
  685. //
  686. pRtInfo->RcvMemoryAllocated += pBuffer->TotalAllocSize;
  687. IpxPrint0("IpxRt;Buffering Rt Rcv - no Irp, status=%X\n");
  688. InsertTailList(&pRtAF->RcvList,&pBuffer->Linkage);
  689. IpxPrint0("PassDgToRt: Buffer Queued\n");
  690. status = STATUS_SUCCESS;
  691. }
  692. else
  693. {
  694. IpxPrint0("PassDgToRt; Could not allocate buffer\n");
  695. status = STATUS_INSUFFICIENT_RESOURCES;
  696. }
  697. }
  698. else
  699. {
  700. // this ret status will allow netbt to process the packet.
  701. //
  702. IpxPrint0("PassDgToRt; Dropping Pkt\n");
  703. status = STATUS_INSUFFICIENT_RESOURCES;
  704. }
  705. CTEFreeLock(&pRtInfo->Lock,OldIrq);
  706. }
  707. else
  708. {
  709. PMDL pMdl;
  710. ULONG CopyLength;
  711. ULONG DgrmLength;
  712. ULONG MdlBufferLength;
  713. ULONG BytesToCopy;
  714. PLIST_ENTRY pLE;
  715. //
  716. // The recv irp is here so copy the data to its buffer and
  717. // pass it up to RT
  718. //
  719. pLE = RemoveHeadList(&pRtAF->RcvIrpList);
  720. pIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
  721. (*(REQUEST_LINKAGE(pIrp))).Flink = NULL;
  722. (*(REQUEST_LINKAGE(pIrp))).Blink = NULL;
  723. //
  724. // Copy the datagram and the source address to RT buffer and
  725. // return to RT
  726. //
  727. pMdl = pIrp->MdlAddress;
  728. IpxPrint2("PassDgToRt: Irp=(%lx); Mdl=(%lx)\n", pIrp, pMdl);
  729. CTEAssert(pMdl);
  730. pRtBuffer = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
  731. if (!pRtBuffer) {
  732. CopyLength = 0;
  733. status = STATUS_INSUFFICIENT_RESOURCES;
  734. } else {
  735. MdlBufferLength = MmGetMdlByteCount(pMdl);
  736. DgrmLength = uNumBytes;
  737. BytesToCopy = DgrmLength + OFFSET_PKT_IN_OPTIONS;
  738. CopyLength = (BytesToCopy <= MdlBufferLength) ? BytesToCopy : MdlBufferLength;
  739. IpxPrint2("PassDgToRt: Copy Length = (%d); Mdl Buffer Length is (%d)\n", CopyLength, MdlBufferLength);
  740. //
  741. // Copy user datagram into pRtBuffer
  742. //
  743. RtlCopyMemory((PVOID)((PUCHAR)pRtBuffer + OFFSET_PKT_IN_OPTIONS),
  744. (PVOID)pDgrm,
  745. CopyLength-OFFSET_PKT_IN_OPTIONS);
  746. IpxPrint1("Data copied is (%.12s)\n", (PUCHAR)((PUCHAR)pRtBuffer + OFFSET_PKT_IN_OPTIONS + sizeof(IPX_HEADER)));
  747. pRtBuffer->DgrmOptions.LocalTarget.NicId = pContext->DgrmOptions.LocalTarget.NicId;
  748. pRtBuffer->LengthOfExtraOpInfo = 0;
  749. IpxPrint3("PassDgToRt: Copy to RcvIrp;Nic Id is (%d/%d). BufferLength is (%lx)\n", pContext->DgrmOptions.LocalTarget.NicId, pRtBuffer->DgrmOptions.LocalTarget.NicId, uNumBytes);
  750. // CTEAssert(pContext->DgrmOptions.LocalTarget.NicId);
  751. //
  752. // pass the irp up to RT
  753. //
  754. if (CopyLength < BytesToCopy)
  755. {
  756. status = STATUS_BUFFER_OVERFLOW;
  757. }
  758. else
  759. {
  760. status = STATUS_SUCCESS;
  761. }
  762. }
  763. InsertTailList(&pRtInfo->CompletedIrps, REQUEST_LINKAGE(pIrp));
  764. pRtAF->NoOfRcvIrps--;
  765. IpxPrint4("PassDgToRt;Returning Rt Rcv Irp - data from net, Length=%X,pIrp=%X; status = (%d). NoOfRcvIrp = (%d)\n" ,uNumBytes,pIrp, status, pRtAF->NoOfRcvIrps);
  766. pIrp->IoStatus.Status = status;
  767. pIrp->IoStatus.Information = CopyLength;
  768. CTEFreeLock(&pRtInfo->Lock,OldIrq);
  769. }
  770. IpxDereferenceRt(pRtInfo, RT_BUFF);
  771. } while (FALSE);
  772. IpxPrint0("PassDgToRt - Entered\n");
  773. return(status);
  774. }
  775. //----------------------------------------------------------------------------
  776. VOID
  777. RtIrpCancel(
  778. IN PDEVICE_OBJECT pDeviceObject,
  779. IN PIRP pIrp
  780. )
  781. /*++
  782. Routine Description;
  783. This routine handles the cancelling a RtRcv Irp. It must release the
  784. cancel spin lock before returning re; IoCancelIrp().
  785. Arguments;
  786. Return Value;
  787. The final status from the operation.
  788. --*/
  789. {
  790. KIRQL OldIrq;
  791. PRT_INFO pRt;
  792. PDEVICE pDevice = IpxDevice;
  793. #ifdef SUNDOWN
  794. ULONG_PTR Index;
  795. #else
  796. ULONG Index;
  797. #endif
  798. PIRP pTmpIrp;
  799. IpxPrint0("RtIrpCancel;Got a Rt Irp Cancel !!! *****************\n");
  800. Index = RT_ADDRESS_INDEX(pIrp);
  801. IpxPrint1("RtIrpCancel: Index = (%d)\n", Index);
  802. // pRt = (PRT_INFO)REQUEST_OPEN_CONTEXT(pIrp);
  803. pRt = pRtInfo;
  804. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  805. if ((pRt->Type != IPX_RT_SIGNATURE) || (pRt->Size != sizeof(RT_INFO))) {
  806. return;
  807. }
  808. //
  809. // Be sure that PassNamePduToRt has not taken the RcvIrp for a
  810. // Rcv just now.
  811. //
  812. CTEGetLock(&pRt->Lock,&OldIrq);
  813. if (pRt && (pRt == pRtInfo) && (*(REQUEST_LINKAGE(pIrp))).Flink != NULL)
  814. {
  815. PRT_IRP pRtAF = &pRt->AddFl[Index];
  816. RemoveEntryList(REQUEST_LINKAGE(pIrp));
  817. pIrp->IoStatus.Status = STATUS_CANCELLED;
  818. pRtAF->NoOfRcvIrps--;
  819. CTEFreeLock(&pRt->Lock,OldIrq);
  820. IpxPrint1("RtIrpCancel;Completing Request. NoOfRcvIrp = (%d)\n", pRtAF->NoOfRcvIrps);
  821. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  822. } else {
  823. CTEFreeLock(&pRt->Lock,OldIrq);
  824. }
  825. }
  826. //----------------------------------------------------------------------------
  827. PVOID
  828. RtAllocMem(
  829. IN ULONG Size
  830. )
  831. /*++
  832. Routine Description;
  833. This Routine handles allocating memory and keeping track of how
  834. much has been allocated.
  835. Arguments;
  836. Size - number of bytes to allocate
  837. Rcv - boolean that indicates if it is rcv or send buffering
  838. Return Value;
  839. ptr to the memory allocated
  840. --*/
  841. {
  842. if (pRtInfo->RcvMemoryAllocated > pRtInfo->RcvMemoryMax)
  843. {
  844. return NULL;
  845. }
  846. else
  847. {
  848. pRtInfo->RcvMemoryAllocated += Size;
  849. return (AllocMem(Size));
  850. }
  851. }
  852. //----------------------------------------------------------------------------
  853. VOID
  854. RtFreeMem(
  855. IN PVOID pBuffer,
  856. IN ULONG Size
  857. )
  858. /*++
  859. Routine Description;
  860. This Routine handles freeing memory and keeping track of how
  861. much has been allocated.
  862. Arguments;
  863. pBuffer - buffer to free
  864. Size - number of bytes to allocate
  865. Rcv - boolean that indicates if it is rcv or send buffering
  866. Return Value;
  867. none
  868. --*/
  869. {
  870. if (pRtInfo)
  871. {
  872. pRtInfo->RcvMemoryAllocated -= Size;
  873. }
  874. FreeMem(pBuffer, Size);
  875. }
  876. //----------------------------------------------------------------------------
  877. VOID
  878. NTIoComplete(
  879. IN PIRP pIrp,
  880. IN NTSTATUS Status,
  881. IN ULONG SentLength)
  882. /*++
  883. Routine Description;
  884. This Routine handles calling the NT I/O system to complete an I/O.
  885. Arguments;
  886. status - a completion status for the Irp
  887. Return Value;
  888. NTSTATUS - status of the request
  889. --*/
  890. {
  891. KIRQL OldIrq;
  892. if (Status != -1)
  893. {
  894. pIrp->IoStatus.Status = Status;
  895. }
  896. // use -1 as a flag to mean do not adjust the sent length since it is
  897. // already set
  898. if (SentLength != -1)
  899. {
  900. pIrp->IoStatus.Information = SentLength;
  901. }
  902. #if DBG
  903. if (SentLength != -1)
  904. {
  905. if ( (Status != STATUS_SUCCESS) &&
  906. (Status != STATUS_PENDING) &&
  907. (Status != STATUS_INVALID_DEVICE_REQUEST) &&
  908. (Status != STATUS_INVALID_PARAMETER) &&
  909. (Status != STATUS_IO_TIMEOUT) &&
  910. (Status != STATUS_BUFFER_OVERFLOW) &&
  911. (Status != STATUS_BUFFER_TOO_SMALL) &&
  912. (Status != STATUS_INVALID_HANDLE) &&
  913. (Status != STATUS_INSUFFICIENT_RESOURCES) &&
  914. (Status != STATUS_CANCELLED) &&
  915. (Status != STATUS_DUPLICATE_NAME) &&
  916. (Status != STATUS_TOO_MANY_NAMES) &&
  917. (Status != STATUS_TOO_MANY_SESSIONS) &&
  918. (Status != STATUS_REMOTE_NOT_LISTENING) &&
  919. (Status != STATUS_BAD_NETWORK_PATH) &&
  920. (Status != STATUS_HOST_UNREACHABLE) &&
  921. (Status != STATUS_CONNECTION_REFUSED) &&
  922. (Status != STATUS_WORKING_SET_QUOTA) &&
  923. (Status != STATUS_REMOTE_DISCONNECT) &&
  924. (Status != STATUS_LOCAL_DISCONNECT) &&
  925. (Status != STATUS_LINK_FAILED) &&
  926. (Status != STATUS_SHARING_VIOLATION) &&
  927. (Status != STATUS_UNSUCCESSFUL) &&
  928. (Status != STATUS_ACCESS_VIOLATION) &&
  929. (Status != STATUS_NONEXISTENT_EA_ENTRY) )
  930. {
  931. IpxPrint1("returning unusual status = %X\n",Status);
  932. }
  933. }
  934. #endif
  935. IpxPrint1("Irp Status is %d\n", pIrp->IoStatus.Status);
  936. //
  937. // set the Irps cancel routine to null or the system may bugcheck
  938. // with a bug code of CANCEL_STATE_IN_COMPLETED_IRP
  939. //
  940. // refer to IoCancelIrp() ..\ntos\io\iosubs.c
  941. //
  942. IoAcquireCancelSpinLock(&OldIrq);
  943. IoSetCancelRoutine(pIrp,NULL);
  944. IoReleaseCancelSpinLock(OldIrq);
  945. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  946. }
  947. //----------------------------------------------------------------------------
  948. NTSTATUS
  949. NTCheckSetCancelRoutine(
  950. IN PIRP pIrp,
  951. IN PVOID CancelRoutine,
  952. IN PDEVICE pDevice
  953. )
  954. /*++
  955. Routine Description;
  956. This Routine sets the cancel routine for an Irp.
  957. Arguments;
  958. status - a completion status for the Irp
  959. Return Value;
  960. NTSTATUS - status of the request
  961. --*/
  962. {
  963. NTSTATUS status;
  964. IpxPrint1("CheckSetCancelRoutine: Entered. Irp = (%lx)\n", pIrp);
  965. //
  966. // Check if the irp was cancelled yet and if not, then set the
  967. // irp cancel routine.
  968. //
  969. IoAcquireCancelSpinLock(&pIrp->CancelIrql);
  970. if (pIrp->Cancel)
  971. {
  972. pIrp->IoStatus.Status = STATUS_CANCELLED;
  973. status = STATUS_CANCELLED;
  974. }
  975. else
  976. {
  977. // setup the cancel routine
  978. IoMarkIrpPending(pIrp);
  979. IoSetCancelRoutine(pIrp,CancelRoutine);
  980. status = STATUS_SUCCESS;
  981. }
  982. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  983. return(status);
  984. }
  985. VOID
  986. IpxRefRt(
  987. PRT_INFO pRt
  988. )
  989. /*++
  990. Routine Description;
  991. This routine increments the reference count on a device context.
  992. Arguments;
  993. Binding - Pointer to a transport device context object.
  994. Return Value;
  995. none.
  996. --*/
  997. {
  998. (VOID)InterlockedIncrement (&pRt->ReferenceCount);
  999. // CTEAssert (pRt->ReferenceCount > 0); // not perfect, but...
  1000. // IpxPrint1("RefRt: RefCount is (%d)\n", pRt->ReferenceCount);
  1001. } /* IpxRefRt */
  1002. VOID
  1003. IpxDerefRt(
  1004. PRT_INFO pRt
  1005. )
  1006. /*++
  1007. Routine Description;
  1008. This routine dereferences a device context by decrementing the
  1009. reference count contained in the structure. Currently, we don't
  1010. do anything special when the reference count drops to zero, but
  1011. we could dynamically unload stuff then.
  1012. Arguments;
  1013. Binding - Pointer to a transport device context object.
  1014. Return Value;
  1015. none.
  1016. --*/
  1017. {
  1018. LONG result;
  1019. result = InterlockedDecrement (&pRt->ReferenceCount);
  1020. // IpxPrint1("DerefRt: RefCount is (%d)\n", pRt->ReferenceCount);
  1021. // CTEAssert (result >= 0);
  1022. #if 0
  1023. if (result == 0) {
  1024. IpxDestroyRt (pRt);
  1025. }
  1026. #endif
  1027. } /* IpxDerefRt */
  1028. VOID
  1029. IpxDestroyRt(
  1030. IN PRT_INFO pRt
  1031. )
  1032. /*++
  1033. Routine Description;
  1034. This routine destroys a binding structure.
  1035. Arguments;
  1036. Binding - Pointer to a transport binding structure.
  1037. Return Value;
  1038. None.
  1039. --*/
  1040. {
  1041. IpxPrint0("Destroying Rt\n");
  1042. FreeMem (pRt, sizeof(RT_INFO));
  1043. pRtInfo = NULL;
  1044. return;
  1045. } /* IpxDestroyRt */