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.

1530 lines
43 KiB

  1. /*++
  2. Copyright (c) 1989-1994 Microsoft Corporation
  3. Module Name:
  4. Winsif.c
  5. Abstract:
  6. This module implements all the code surrounding the WINS interface to
  7. netbt that allows WINS to share the same 137 socket as netbt.
  8. Author:
  9. Jim Stewart (Jimst) 1-30-94
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. VOID
  14. NbtCancelWinsIrp(
  15. IN PDEVICE_OBJECT DeviceContext,
  16. IN PIRP pIrp
  17. );
  18. VOID
  19. NbtCancelWinsSendIrp(
  20. IN PDEVICE_OBJECT DeviceContext,
  21. IN PIRP pIrp
  22. );
  23. VOID
  24. WinsDgramCompletion(
  25. IN tDGRAM_SEND_TRACKING *pTracker,
  26. IN NTSTATUS status,
  27. IN ULONG Length
  28. );
  29. NTSTATUS
  30. CheckIfLocalNameActive(
  31. IN tREM_ADDRESS *pSendAddr
  32. );
  33. PVOID
  34. WinsAllocMem(
  35. IN tWINS_INFO *pWinsContext,
  36. IN ULONG Size,
  37. IN BOOLEAN Rcv
  38. );
  39. VOID
  40. WinsFreeMem(
  41. IN tWINS_INFO *pWinsContext,
  42. IN PVOID pBuffer,
  43. IN ULONG Size,
  44. IN BOOLEAN Rcv
  45. );
  46. VOID
  47. InitiateRefresh (
  48. );
  49. BOOLEAN RefreshedYet;
  50. //
  51. // take this define from Winsock.h since including winsock.h causes
  52. // redefinition problems with various types.
  53. //
  54. #define AF_UNIX 1
  55. #define AF_INET 2
  56. //******************* Pageable Routine Declarations ****************
  57. #ifdef ALLOC_PRAGMA
  58. #pragma CTEMakePageable(PAGENBT, NTCloseWinsAddr)
  59. #pragma CTEMakePageable(PAGENBT, InitiateRefresh)
  60. #pragma CTEMakePageable(PAGENBT, PassNamePduToWins)
  61. #pragma CTEMakePageable(PAGENBT, NbtCancelWinsIrp)
  62. #pragma CTEMakePageable(PAGENBT, NbtCancelWinsSendIrp)
  63. #pragma CTEMakePageable(PAGENBT, CheckIfLocalNameActive)
  64. #pragma CTEMakePageable(PAGENBT, WinsDgramCompletion)
  65. #pragma CTEMakePageable(PAGENBT, WinsFreeMem)
  66. #pragma CTEMakePageable(PAGENBT, WinsAllocMem)
  67. #endif
  68. //******************* Pageable Routine Declarations ****************
  69. tWINS_INFO *pWinsInfo;
  70. LIST_ENTRY FreeWinsList;
  71. HANDLE NbtDiscardableCodeHandle={0};
  72. tDEVICECONTEXT *pWinsDeviceContext = NULL;
  73. ULONG LastWinsSignature = 0x8000;
  74. #define COUNT_MAX 10
  75. //----------------------------------------------------------------------------
  76. NTSTATUS
  77. NTOpenWinsAddr(
  78. IN tDEVICECONTEXT *pDeviceContext,
  79. IN PIRP pIrp,
  80. IN tIPADDRESS IpAddress
  81. )
  82. /*++
  83. Routine Description:
  84. This Routine handles opening the Wins Object that is used by
  85. by WINS to send and receive name service datagrams on port 137.
  86. Arguments:
  87. pIrp - a ptr to an IRP
  88. Return Value:
  89. NTSTATUS - status of the request
  90. --*/
  91. {
  92. PIO_STACK_LOCATION pIrpSp;
  93. NTSTATUS status;
  94. tWINS_INFO *pWins;
  95. CTELockHandle OldIrq;
  96. //
  97. // Page in the Wins Code, if it hasn't already been paged in.
  98. //
  99. if ((!NbtDiscardableCodeHandle) &&
  100. (!(NbtDiscardableCodeHandle = MmLockPagableCodeSection (NTCloseWinsAddr))))
  101. {
  102. return (STATUS_UNSUCCESSFUL);
  103. }
  104. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  105. //
  106. // if the WINs endpoint structure is not allocated, then allocate it
  107. // and initialize it.
  108. //
  109. if (pWinsInfo)
  110. {
  111. status = STATUS_UNSUCCESSFUL;
  112. }
  113. else if (!(pWins = NbtAllocMem(sizeof(tWINS_INFO),NBT_TAG('v'))))
  114. {
  115. status = STATUS_INSUFFICIENT_RESOURCES;
  116. }
  117. else
  118. {
  119. CTEZeroMemory(pWins,sizeof(tWINS_INFO));
  120. pWins->Verify = NBT_VERIFY_WINS_ACTIVE;
  121. InitializeListHead(&pWins->Linkage);
  122. InitializeListHead(&pWins->RcvList);
  123. InitializeListHead(&pWins->SendList);
  124. pWins->RcvMemoryMax = NbtConfig.MaxDgramBuffering;
  125. pWins->SendMemoryMax = NbtConfig.MaxDgramBuffering;
  126. pWins->IpAddress = IpAddress;
  127. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  128. pWins->pDeviceContext= GetDeviceWithIPAddress(IpAddress);
  129. pWins->WinsSignature = LastWinsSignature++;
  130. pWinsInfo = pWins;
  131. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  132. pIrpSp->FileObject->FsContext = (PVOID) pWinsInfo;
  133. pIrpSp->FileObject->FsContext2 = (PVOID) NBT_WINS_TYPE;
  134. RefreshedYet = FALSE;
  135. status = STATUS_SUCCESS;
  136. }
  137. IF_DBG(NBT_DEBUG_WINS)
  138. KdPrint(("Nbt:Open Wins Address Rcvd, status= %X\n",status));
  139. return(status);
  140. }
  141. //----------------------------------------------------------------------------
  142. NTSTATUS
  143. NTCleanUpWinsAddr(
  144. IN tDEVICECONTEXT *pDeviceContext,
  145. IN PIRP pIrp
  146. )
  147. /*++
  148. Routine Description:
  149. This Routine handles closing the Wins Object that is used by
  150. by WINS to send and receive name service datagrams on port 137.
  151. Arguments:
  152. pIrp - a ptr to an IRP
  153. Return Value:
  154. NTSTATUS - status of the request
  155. --*/
  156. {
  157. PIO_STACK_LOCATION pIrpSp;
  158. NTSTATUS status;
  159. CTELockHandle OldIrq;
  160. PLIST_ENTRY pHead, pEntry;
  161. tWINSRCV_BUFFER *pRcv;
  162. tWINS_INFO *pWins = NULL;
  163. PIRP pSendIrp, pRcvIrp;
  164. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  165. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  166. pWins = pIrpSp->FileObject->FsContext;
  167. if (pWinsInfo && (pWins == pWinsInfo))
  168. {
  169. ASSERT (NBT_VERIFY_HANDLE (pWins, NBT_VERIFY_WINS_ACTIVE));
  170. pWins->Verify = NBT_VERIFY_WINS_DOWN;
  171. //
  172. // prevent any more dgram getting queued up
  173. //
  174. pWinsInfo = NULL;
  175. //
  176. // free any rcv buffers that may be queued up
  177. //
  178. pHead = &pWins->RcvList;
  179. while (!IsListEmpty(pHead))
  180. {
  181. IF_DBG(NBT_DEBUG_WINS)
  182. KdPrint(("Nbt.NTCleanUpWinsAddr: Freeing Rcv buffered for Wins\n"));
  183. pEntry = RemoveHeadList(pHead);
  184. pRcv = CONTAINING_RECORD(pEntry,tWINSRCV_BUFFER,Linkage);
  185. WinsFreeMem (pWins, pRcv, pRcv->DgramLength,TRUE);
  186. }
  187. //
  188. // return any Send buffers that may be queued up
  189. //
  190. pHead = &pWins->SendList;
  191. while (!IsListEmpty(pHead))
  192. {
  193. IF_DBG(NBT_DEBUG_WINS)
  194. KdPrint(("Nbt.NTCleanUpWinsAddr: Freeing Send Wins Address!\n"));
  195. pEntry = RemoveHeadList(pHead);
  196. pSendIrp = CONTAINING_RECORD(pEntry,IRP,Tail.Overlay.ListEntry);
  197. CTESpinFree (&NbtConfig. JointLock, OldIrq);
  198. NbtCancelCancelRoutine (pSendIrp);
  199. CTEIoComplete (pSendIrp, STATUS_CANCELLED, 0);
  200. CTESpinLock (&NbtConfig.JointLock, OldIrq);
  201. }
  202. pWins->pDeviceContext = NULL;
  203. InsertTailList (&FreeWinsList, &pWins->Linkage);
  204. //
  205. // Complete any Rcv Irps that may be hanging on this request
  206. //
  207. if (pRcvIrp = pWins->RcvIrp)
  208. {
  209. pWins->RcvIrp = NULL;
  210. pRcvIrp->IoStatus.Status = STATUS_CANCELLED;
  211. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  212. NbtCancelCancelRoutine (pRcvIrp);
  213. CTEIoComplete (pRcvIrp, STATUS_CANCELLED, 0);
  214. }
  215. else
  216. {
  217. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  218. }
  219. status = STATUS_SUCCESS;
  220. }
  221. else
  222. {
  223. ASSERT (0);
  224. status = STATUS_INVALID_HANDLE;
  225. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  226. }
  227. IF_DBG(NBT_DEBUG_WINS)
  228. KdPrint(("Nbt.NTCleanUpWinsAddr: pWins=<%p>, status=<%x>\n", pWins, status));
  229. return(status);
  230. }
  231. //----------------------------------------------------------------------------
  232. NTSTATUS
  233. NTCloseWinsAddr(
  234. IN tDEVICECONTEXT *pDeviceContext,
  235. IN PIRP pIrp
  236. )
  237. /*++
  238. Routine Description:
  239. This Routine handles closing the Wins Object that is used by
  240. by WINS to send and receive name service datagrams on port 137.
  241. Arguments:
  242. pIrp - a ptr to an IRP
  243. Return Value:
  244. NTSTATUS - status of the request
  245. --*/
  246. {
  247. PIO_STACK_LOCATION pIrpSp;
  248. NTSTATUS status;
  249. CTELockHandle OldIrq;
  250. tWINS_INFO *pWins = NULL;
  251. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  252. //
  253. // if the WINs endpoint structure is allocated, then deallocate it
  254. //
  255. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  256. pWins = pIrpSp->FileObject->FsContext;
  257. if (NBT_VERIFY_HANDLE (pWins, NBT_VERIFY_WINS_DOWN))
  258. {
  259. pWins->Verify += 10;
  260. RemoveEntryList (&pWins->Linkage);
  261. CTEMemFree (pWins);
  262. pIrpSp->FileObject->FsContext2 = (PVOID)NBT_CONTROL_TYPE;
  263. status = STATUS_SUCCESS;
  264. }
  265. else
  266. {
  267. ASSERT (0);
  268. status = STATUS_INVALID_HANDLE;
  269. }
  270. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  271. IF_DBG(NBT_DEBUG_WINS)
  272. KdPrint(("Nbt.NTCloseWinsAddr: pWins=<%p>, status=<%x>\n", pWins, status));
  273. return(status);
  274. }
  275. //----------------------------------------------------------------------------
  276. NTSTATUS
  277. WinsSetInformation(
  278. IN tWINS_INFO *pWins,
  279. IN tWINS_SET_INFO *pWinsSetInfo
  280. )
  281. {
  282. CTELockHandle OldIrq;
  283. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  284. if ((pWins == pWinsInfo) &&
  285. (pWinsSetInfo->IpAddress))
  286. {
  287. pWins->IpAddress = pWinsSetInfo->IpAddress;
  288. pWins->pDeviceContext = GetDeviceWithIPAddress (pWinsSetInfo->IpAddress);
  289. }
  290. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  291. return (STATUS_SUCCESS);
  292. }
  293. //----------------------------------------------------------------------------
  294. VOID
  295. InitiateRefresh (
  296. )
  297. /*++
  298. Routine Description:
  299. This routine tries to refresh all names with WINS on THIS node.
  300. Arguments:
  301. pIrp - Wins Rcv Irp
  302. Return Value:
  303. STATUS_PENDING if the buffer is to be held on to , the normal case.
  304. Notes:
  305. --*/
  306. {
  307. CTELockHandle OldIrq;
  308. PLIST_ENTRY pHead;
  309. PLIST_ENTRY pEntry;
  310. ULONG Count;
  311. ULONG NumberNames;
  312. //
  313. // be sure all net cards have this card as the primary wins
  314. // server since Wins has to answer name queries for this
  315. // node.
  316. //
  317. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  318. if (!(NodeType & BNODE))
  319. {
  320. LONG i;
  321. Count = 0;
  322. NumberNames = 0;
  323. for (i=0 ;i < NbtConfig.pLocalHashTbl->lNumBuckets ;i++ )
  324. {
  325. pHead = &NbtConfig.pLocalHashTbl->Bucket[i];
  326. pEntry = pHead;
  327. while ((pEntry = pEntry->Flink) != pHead)
  328. {
  329. NumberNames++;
  330. }
  331. }
  332. while (Count < COUNT_MAX)
  333. {
  334. if (!(NbtConfig.GlobalRefreshState & NBT_G_REFRESHING_NOW))
  335. {
  336. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  337. ReRegisterLocalNames(NULL, FALSE);
  338. break;
  339. }
  340. else
  341. {
  342. LARGE_INTEGER Timout;
  343. NTSTATUS Locstatus;
  344. IF_DBG(NBT_DEBUG_WINS)
  345. KdPrint(("Nbt:Waiting for Refresh to finish, so names can be reregistered\n"));
  346. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  347. //
  348. // set a timeout that should be long enough to wait
  349. // for all names to fail registration with a down
  350. // wins server.
  351. //
  352. // 2 sec*3 retries * 8 names / 5 = 9 seconds a shot.
  353. // for a total of 90 seconds max.
  354. //
  355. Timout.QuadPart = Int32x32To64(
  356. MILLISEC_TO_100NS/(COUNT_MAX/2),
  357. (NbtConfig.uRetryTimeout*NbtConfig.uNumRetries)
  358. *NumberNames);
  359. Timout.QuadPart = -(Timout.QuadPart);
  360. //
  361. // wait for a few seconds and try again.
  362. //
  363. Locstatus = KeDelayExecutionThread(
  364. KernelMode,
  365. FALSE, // Alertable
  366. &Timout); // Timeout
  367. Count++;
  368. if (Count < COUNT_MAX)
  369. {
  370. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  371. }
  372. }
  373. }
  374. }
  375. else
  376. {
  377. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  378. }
  379. }
  380. //----------------------------------------------------------------------------
  381. NTSTATUS
  382. RcvIrpFromWins(
  383. IN PCTE_IRP pIrp
  384. )
  385. /*++
  386. Routine Description:
  387. This function takes the rcv irp posted by WINS and decides if there are
  388. any datagram queued waiting to go up to WINS. If so then the datagram
  389. is copied to the WINS buffer and passed back up. Otherwise the irp is
  390. held by Netbt until a datagram does come in.
  391. Arguments:
  392. pIrp - Wins Rcv Irp
  393. Return Value:
  394. STATUS_PENDING if the buffer is to be held on to , the normal case.
  395. Notes:
  396. --*/
  397. {
  398. NTSTATUS status;
  399. NTSTATUS Locstatus;
  400. tREM_ADDRESS *pWinsBuffer;
  401. tWINSRCV_BUFFER *pBuffer;
  402. PLIST_ENTRY pEntry;
  403. CTELockHandle OldIrq;
  404. tWINS_INFO *pWins;
  405. PIO_STACK_LOCATION pIrpSp;
  406. PMDL pMdl;
  407. ULONG CopyLength;
  408. ULONG DgramLength;
  409. ULONG BufferLength;
  410. status = STATUS_INVALID_HANDLE;
  411. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  412. pWins = pIrpSp->FileObject->FsContext;
  413. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  414. if (!RefreshedYet)
  415. {
  416. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  417. InitiateRefresh();
  418. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  419. RefreshedYet = TRUE;
  420. }
  421. if ((!pWins) || (pWins != pWinsInfo))
  422. {
  423. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  424. NTIoComplete(pIrp,status,0);
  425. return(status);
  426. }
  427. if (!IsListEmpty(&pWins->RcvList))
  428. {
  429. //
  430. // There is at least one datagram waiting to be received
  431. //
  432. pEntry = RemoveHeadList(&pWins->RcvList);
  433. pBuffer = CONTAINING_RECORD(pEntry,tWINSRCV_BUFFER,Linkage);
  434. //
  435. // Copy the datagram and the source address to WINS buffer and return to WINS
  436. //
  437. if ((pMdl = pIrp->MdlAddress) &&
  438. (pWinsBuffer = MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, HighPagePriority)))
  439. {
  440. BufferLength = MmGetMdlByteCount(pMdl);
  441. DgramLength = pBuffer->DgramLength;
  442. CopyLength = (DgramLength <= BufferLength) ? DgramLength : BufferLength;
  443. CTEMemCopy ((PVOID)pWinsBuffer, (PVOID)&pBuffer->Address.Family, CopyLength);
  444. ASSERT(pWinsBuffer->Port);
  445. ASSERT(pWinsBuffer->IpAddress);
  446. if (CopyLength < DgramLength)
  447. {
  448. Locstatus = STATUS_BUFFER_OVERFLOW;
  449. }
  450. else
  451. {
  452. Locstatus = STATUS_SUCCESS;
  453. }
  454. }
  455. else
  456. {
  457. CopyLength = 0;
  458. Locstatus = STATUS_UNSUCCESSFUL;
  459. }
  460. //
  461. // subtract from the total amount buffered for WINS since we are
  462. // passing a datagram up to WINS now.
  463. //
  464. pWins->RcvMemoryAllocated -= pBuffer->DgramLength;
  465. CTEMemFree(pBuffer);
  466. //
  467. // pass the irp up to WINS
  468. //
  469. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  470. IF_DBG(NBT_DEBUG_WINS)
  471. KdPrint(("Nbt:Returning Wins rcv Irp immediately with queued dgram, status=%X,pIrp=%X\n"
  472. ,status,pIrp));
  473. pIrp->IoStatus.Information = CopyLength;
  474. pIrp->IoStatus.Status = Locstatus;
  475. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  476. return(STATUS_SUCCESS);
  477. }
  478. if (pWins->RcvIrp)
  479. {
  480. status = STATUS_NOT_SUPPORTED;
  481. }
  482. else
  483. {
  484. status = NTCheckSetCancelRoutine(pIrp, NbtCancelWinsIrp, NULL);
  485. if (NT_SUCCESS(status))
  486. {
  487. IF_DBG(NBT_DEBUG_WINS)
  488. KdPrint(("Nbt:Holding onto Wins Rcv Irp, pIrp =%Xstatus=%X\n", status,pIrp));
  489. pWins->RcvIrp = pIrp;
  490. status = STATUS_PENDING;
  491. }
  492. }
  493. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  494. if (!NT_SUCCESS(status))
  495. {
  496. NTIoComplete(pIrp,status,0);
  497. }
  498. return(status);
  499. }
  500. //----------------------------------------------------------------------------
  501. NTSTATUS
  502. PassNamePduToWins (
  503. IN tDEVICECONTEXT *pDeviceContext,
  504. IN PVOID pSrcAddress,
  505. IN tNAMEHDR UNALIGNED *pNameSrv,
  506. IN ULONG uNumBytes
  507. )
  508. /*++
  509. Routine Description:
  510. This function is used to allow NBT to pass name query service Pdu's to
  511. WINS. Wins posts a Rcv irp to Netbt. If the Irp is here then simply
  512. copy the data to the irp and return it, otherwise buffer the data up
  513. to a maximum # of bytes. Beyond that limit the datagrams are discarded.
  514. If Retstatus is not success then the pdu will also be processed by
  515. nbt. This allows nbt to process packets when wins pauses and
  516. its list of queued buffers is exceeded.
  517. Arguments:
  518. pDeviceContext - card that the request can in on
  519. pSrcAddress - source address
  520. pNameSrv - ptr to the datagram
  521. uNumBytes - length of datagram
  522. Return Value:
  523. STATUS_PENDING if the buffer is to be held on to , the normal case.
  524. Notes:
  525. --*/
  526. {
  527. NTSTATUS Retstatus;
  528. NTSTATUS status;
  529. tREM_ADDRESS *pWinsBuffer;
  530. PCTE_IRP pIrp;
  531. CTELockHandle OldIrq;
  532. PTRANSPORT_ADDRESS pSourceAddress;
  533. ULONG SrcAddress;
  534. SHORT SrcPort;
  535. //
  536. // Get the source port and ip address, since WINS needs this information.
  537. //
  538. pSourceAddress = (PTRANSPORT_ADDRESS)pSrcAddress;
  539. SrcAddress = ((PTDI_ADDRESS_IP)&pSourceAddress->Address[0].Address[0])->in_addr;
  540. SrcPort = ((PTDI_ADDRESS_IP)&pSourceAddress->Address[0].Address[0])->sin_port;
  541. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  542. Retstatus = STATUS_SUCCESS;
  543. if (pWinsInfo)
  544. {
  545. if (!pWinsInfo->RcvIrp)
  546. {
  547. //
  548. // Queue the name query pdu if we have not exeeded our current queue
  549. // length
  550. //
  551. if (pWinsInfo->RcvMemoryAllocated < pWinsInfo->RcvMemoryMax)
  552. {
  553. tWINSRCV_BUFFER *pBuffer;
  554. pBuffer = NbtAllocMem(uNumBytes + sizeof(tWINSRCV_BUFFER)+8,NBT_TAG('v'));
  555. if (pBuffer)
  556. {
  557. //
  558. // check if it is a name reg from this node
  559. //
  560. if (pNameSrv->AnCount == WINS_SIGNATURE)
  561. {
  562. pNameSrv->AnCount = 0;
  563. pBuffer->Address.Family = AF_UNIX;
  564. }
  565. else
  566. {
  567. pBuffer->Address.Family = AF_INET;
  568. }
  569. CTEMemCopy((PUCHAR)((PUCHAR)pBuffer + sizeof(tWINSRCV_BUFFER)),
  570. (PVOID)pNameSrv,uNumBytes);
  571. pBuffer->Address.Port = SrcPort;
  572. pBuffer->Address.IpAddress = SrcAddress;
  573. pBuffer->Address.LengthOfBuffer = uNumBytes;
  574. ASSERT(pBuffer->Address.Port);
  575. ASSERT(pBuffer->Address.IpAddress);
  576. // total amount allocated
  577. pBuffer->DgramLength = uNumBytes + sizeof(tREM_ADDRESS);
  578. //
  579. // Keep track of the total amount buffered so that we don't
  580. // eat up all non-paged pool buffering for WINS
  581. //
  582. pWinsInfo->RcvMemoryAllocated += pBuffer->DgramLength;
  583. IF_DBG(NBT_DEBUG_WINS)
  584. KdPrint(("Nbt:Buffering Wins Rcv - no Irp, status=%X\n"));
  585. InsertTailList(&pWinsInfo->RcvList,&pBuffer->Linkage);
  586. }
  587. }
  588. else
  589. {
  590. // this ret status will allow netbt to process the packet.
  591. //
  592. Retstatus = STATUS_INSUFFICIENT_RESOURCES;
  593. }
  594. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  595. }
  596. else
  597. {
  598. PMDL pMdl;
  599. ULONG CopyLength;
  600. ULONG BufferLength;
  601. //
  602. // The recv irp is here so copy the data to its buffer and
  603. // pass it up to WINS
  604. //
  605. pIrp = pWinsInfo->RcvIrp;
  606. pWinsInfo->RcvIrp = NULL;
  607. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  608. //
  609. // Copy the datagram and the source address to WINS buffer and return to WINS
  610. //
  611. if ((!(pMdl = pIrp->MdlAddress)) ||
  612. ((BufferLength = MmGetMdlByteCount(pMdl)) < sizeof(tREM_ADDRESS)) ||
  613. (!(pWinsBuffer = MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, HighPagePriority))))
  614. {
  615. status = STATUS_INSUFFICIENT_RESOURCES;
  616. CopyLength = 0;
  617. }
  618. else
  619. {
  620. if (BufferLength >= (uNumBytes + sizeof(tREM_ADDRESS)))
  621. {
  622. CopyLength = uNumBytes;
  623. }
  624. else
  625. {
  626. CopyLength = BufferLength - sizeof(tREM_ADDRESS);
  627. }
  628. //
  629. // check if it is a name reg from this node
  630. //
  631. if (pNameSrv->AnCount == WINS_SIGNATURE)
  632. {
  633. pNameSrv->AnCount = 0;
  634. pWinsBuffer->Family = AF_UNIX;
  635. }
  636. else
  637. {
  638. pWinsBuffer->Family = AF_INET;
  639. }
  640. CTEMemCopy((PVOID)((PUCHAR)pWinsBuffer + sizeof(tREM_ADDRESS)), (PVOID)pNameSrv, CopyLength);
  641. pWinsBuffer->Port = SrcPort;
  642. pWinsBuffer->IpAddress = SrcAddress;
  643. pWinsBuffer->LengthOfBuffer = uNumBytes;
  644. ASSERT(pWinsBuffer->Port);
  645. ASSERT(pWinsBuffer->IpAddress);
  646. //
  647. // pass the irp up to WINS
  648. //
  649. if (CopyLength < uNumBytes)
  650. {
  651. status = STATUS_BUFFER_OVERFLOW;
  652. }
  653. else
  654. {
  655. status = STATUS_SUCCESS;
  656. }
  657. IF_DBG(NBT_DEBUG_WINS)
  658. KdPrint(("Nbt:Returning Wins Rcv Irp - data from net, Length=%X,pIrp=%X\n"
  659. ,uNumBytes,pIrp));
  660. }
  661. NTIoComplete(pIrp,status,CopyLength);
  662. }
  663. }
  664. else
  665. {
  666. //
  667. // this ret status will allow netbt to process the packet.
  668. //
  669. Retstatus = STATUS_INSUFFICIENT_RESOURCES;
  670. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  671. }
  672. return(Retstatus);
  673. }
  674. //----------------------------------------------------------------------------
  675. VOID
  676. NbtCancelWinsIrp(
  677. IN PDEVICE_OBJECT DeviceContext,
  678. IN PIRP pIrp
  679. )
  680. /*++
  681. Routine Description:
  682. This routine handles the cancelling a WinsRcv Irp. It must release the
  683. cancel spin lock before returning re: IoCancelIrp().
  684. Arguments:
  685. Return Value:
  686. The final status from the operation.
  687. --*/
  688. {
  689. KIRQL OldIrq;
  690. PIO_STACK_LOCATION pIrpSp;
  691. tWINS_INFO *pWins;
  692. IF_DBG(NBT_DEBUG_WINS)
  693. KdPrint(("Nbt.NbtCancelWinsIrp: Got a Cancel !!! *****************\n"));
  694. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  695. pWins = (tWINS_INFO *)pIrpSp->FileObject->FsContext;
  696. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  697. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  698. //
  699. // Be sure that PassNamePduToWins has not taken the RcvIrp for a
  700. // Rcv just now.
  701. //
  702. if ((NBT_VERIFY_HANDLE (pWins, NBT_VERIFY_WINS_ACTIVE)) &&
  703. (pWins->RcvIrp == pIrp))
  704. {
  705. pWins->RcvIrp = NULL;
  706. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  707. pIrp->IoStatus.Status = STATUS_CANCELLED;
  708. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  709. }
  710. else
  711. {
  712. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  713. }
  714. }
  715. //----------------------------------------------------------------------------
  716. VOID
  717. NbtCancelWinsSendIrp(
  718. IN PDEVICE_OBJECT DeviceContext,
  719. IN PIRP pIrp
  720. )
  721. /*++
  722. Routine Description:
  723. This routine handles the cancelling a WinsRcv Irp. It must release the
  724. cancel spin lock before returning re: IoCancelIrp().
  725. Arguments:
  726. Return Value:
  727. The final status from the operation.
  728. --*/
  729. {
  730. KIRQL OldIrq;
  731. PLIST_ENTRY pHead;
  732. PLIST_ENTRY pEntry;
  733. PIO_STACK_LOCATION pIrpSp;
  734. tWINS_INFO *pWins;
  735. BOOLEAN Found;
  736. PIRP pIrpList;
  737. IF_DBG(NBT_DEBUG_WINS)
  738. KdPrint(("Nbt.NbtCancelWinsSendIrp: Got a Cancel !!! *****************\n"));
  739. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  740. pWins = (tWINS_INFO *)pIrpSp->FileObject->FsContext;
  741. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  742. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  743. if (pWins == pWinsInfo)
  744. {
  745. //
  746. // find the matching irp on the list and remove it
  747. //
  748. pHead = &pWinsInfo->SendList;
  749. pEntry = pHead;
  750. Found = FALSE;
  751. while ((pEntry = pEntry->Flink) != pHead)
  752. {
  753. pIrpList = CONTAINING_RECORD(pEntry,IRP,Tail.Overlay.ListEntry);
  754. if (pIrp == pIrpList)
  755. {
  756. RemoveEntryList(pEntry);
  757. Found = TRUE;
  758. }
  759. }
  760. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  761. if (Found)
  762. {
  763. pIrp->IoStatus.Status = STATUS_CANCELLED;
  764. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  765. }
  766. }
  767. else
  768. {
  769. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  770. }
  771. }
  772. //----------------------------------------------------------------------------
  773. NTSTATUS
  774. WinsSendDatagram(
  775. IN tDEVICECONTEXT *pDeviceContext,
  776. IN PIRP pIrp,
  777. IN BOOLEAN MustSend)
  778. /*++
  779. Routine Description:
  780. This Routine handles sending a datagram down to the transport. MustSend
  781. it set true by the Send Completion routine when it attempts to send
  782. one of the queued datagrams, in case we still don't pass the memory
  783. allocated check and refuse to do the send - sends will just stop then without
  784. this boolean.
  785. Arguments:
  786. pIrp - a ptr to an IRP
  787. Return Value:
  788. NTSTATUS - status of the request
  789. --*/
  790. {
  791. PIO_STACK_LOCATION pIrpSp;
  792. NTSTATUS status;
  793. tWINS_INFO *pWins;
  794. tREM_ADDRESS *pSendAddr;
  795. PVOID pDgram;
  796. ULONG DgramLength;
  797. tDGRAM_SEND_TRACKING *pTracker;
  798. CTELockHandle OldIrq;
  799. BOOLEAN fIsWinsDevice = FALSE;
  800. ULONG DataSize;
  801. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  802. pWins = (tWINS_INFO *)pIrpSp->FileObject->FsContext;
  803. status = STATUS_UNSUCCESSFUL;
  804. if (!(pSendAddr = (tREM_ADDRESS *) MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, HighPagePriority)))
  805. {
  806. pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  807. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  808. return STATUS_INSUFFICIENT_RESOURCES;
  809. }
  810. //
  811. // Bug# 234600: Check if the DataSize is correct
  812. //
  813. DataSize = MmGetMdlByteCount (pIrp->MdlAddress);
  814. if ((DataSize < sizeof(tREM_ADDRESS)) ||
  815. ((DataSize - sizeof(tREM_ADDRESS)) < pSendAddr->LengthOfBuffer))
  816. {
  817. pIrp->IoStatus.Status = STATUS_INVALID_BLOCK_LENGTH;
  818. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  819. return STATUS_INVALID_BLOCK_LENGTH;
  820. }
  821. //
  822. // check if it is a name that is registered on this machine
  823. //
  824. if (pSendAddr->Family == AF_UNIX)
  825. {
  826. status = CheckIfLocalNameActive(pSendAddr);
  827. }
  828. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  829. if ((pWins) &&
  830. (pWins == pWinsInfo))
  831. {
  832. if (pDeviceContext == pWinsDeviceContext)
  833. {
  834. fIsWinsDevice = TRUE;
  835. if (!(pDeviceContext = pWinsInfo->pDeviceContext) ||
  836. !(NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_WINS, TRUE)))
  837. {
  838. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  839. // status = STATUS_INVALID_HANDLE;
  840. status = STATUS_SUCCESS;
  841. pIrp->IoStatus.Status = status;
  842. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  843. return (status);
  844. }
  845. }
  846. if ((pWins->SendMemoryAllocated < pWins->SendMemoryMax) || MustSend)
  847. {
  848. if (pSendAddr->IpAddress != 0)
  849. {
  850. DgramLength = pSendAddr->LengthOfBuffer;
  851. pDgram = WinsAllocMem (pWins, DgramLength, FALSE);
  852. if (pDgram)
  853. {
  854. CTEMemCopy(pDgram, (PVOID)((PUCHAR)pSendAddr+sizeof(tREM_ADDRESS)), DgramLength);
  855. //
  856. // get a buffer for tracking Dgram Sends
  857. //
  858. status = GetTracker(&pTracker, NBT_TRACKER_SEND_WINS_DGRAM);
  859. if (NT_SUCCESS(status))
  860. {
  861. pTracker->SendBuffer.pBuffer = NULL;
  862. pTracker->SendBuffer.Length = 0;
  863. pTracker->SendBuffer.pDgramHdr = pDgram;
  864. pTracker->SendBuffer.HdrLength = DgramLength;
  865. pTracker->pClientIrp = NULL;
  866. pTracker->pDeviceContext = pDeviceContext;
  867. pTracker->pNameAddr = NULL;
  868. pTracker->pDestName = NULL;
  869. pTracker->UnicodeDestName = NULL;
  870. pTracker->pClientEle = NULL;
  871. pTracker->AllocatedLength = DgramLength;
  872. pTracker->ClientContext = IntToPtr(pWins->WinsSignature);
  873. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  874. // send the Datagram...
  875. status = UdpSendDatagram (pTracker,
  876. ntohl(pSendAddr->IpAddress),
  877. WinsDgramCompletion,
  878. pTracker, // context for completion
  879. (USHORT)ntohs(pSendAddr->Port),
  880. NBT_NAME_SERVICE);
  881. IF_DBG(NBT_DEBUG_WINS)
  882. KdPrint(("Nbt:Doing Wins Send, status=%X\n",status));
  883. // sending the datagram could return status pending,
  884. // but since we have buffered the dgram, return status
  885. // success to the client
  886. //
  887. status = STATUS_SUCCESS;
  888. //
  889. // Fill in the sent size
  890. //
  891. pIrp->IoStatus.Information = DgramLength;
  892. }
  893. else
  894. {
  895. WinsFreeMem (pWins, (PVOID)pDgram,DgramLength,FALSE);
  896. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  897. status = STATUS_INSUFFICIENT_RESOURCES;
  898. }
  899. }
  900. else
  901. {
  902. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  903. status = STATUS_INSUFFICIENT_RESOURCES;
  904. }
  905. }
  906. else
  907. {
  908. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  909. status = STATUS_INVALID_PARAMETER;
  910. }
  911. pIrp->IoStatus.Status = status;
  912. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  913. }
  914. else
  915. {
  916. IF_DBG(NBT_DEBUG_WINS)
  917. KdPrint(("Nbt:Holding onto Buffering Wins Send, status=%X\n"));
  918. //
  919. // Hold onto the datagram till memory frees up
  920. //
  921. InsertTailList(&pWins->SendList,&pIrp->Tail.Overlay.ListEntry);
  922. status = NTCheckSetCancelRoutine(pIrp,NbtCancelWinsSendIrp,NULL);
  923. if (!NT_SUCCESS(status))
  924. {
  925. RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
  926. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  927. NTIoComplete(pIrp,status,0);
  928. }
  929. else
  930. {
  931. status = STATUS_PENDING;
  932. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  933. }
  934. }
  935. if (fIsWinsDevice)
  936. {
  937. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_WINS, FALSE);
  938. }
  939. }
  940. else
  941. {
  942. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  943. status = STATUS_INVALID_HANDLE;
  944. pIrp->IoStatus.Status = status;
  945. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  946. }
  947. return(status);
  948. }
  949. //----------------------------------------------------------------------------
  950. NTSTATUS
  951. CheckIfLocalNameActive(
  952. IN tREM_ADDRESS *pSendAddr
  953. )
  954. /*++
  955. Routine Description
  956. This routine checks if this is a name query response and if the
  957. name is still active on the local node.
  958. Arguments:
  959. pMdl = ptr to WINS Mdl
  960. Return Values:
  961. VOID
  962. --*/
  963. {
  964. NTSTATUS status;
  965. tNAMEHDR UNALIGNED *pNameHdr;
  966. tNAMEADDR *pResp;
  967. UCHAR pName[NETBIOS_NAME_SIZE];
  968. PUCHAR pScope;
  969. ULONG lNameSize;
  970. CTELockHandle OldIrq;
  971. pNameHdr = (tNAMEHDR UNALIGNED *)((PUCHAR)pSendAddr + sizeof(tREM_ADDRESS));
  972. //
  973. // Be sure it is a name query PDU that we are checking
  974. //
  975. if (((pNameHdr->OpCodeFlags & NM_FLAGS_MASK) == OP_QUERY) ||
  976. ((pNameHdr->OpCodeFlags & NM_FLAGS_MASK) == OP_RELEASE))
  977. {
  978. status = ConvertToAscii ((PCHAR)&pNameHdr->NameRR.NameLength,
  979. pSendAddr->LengthOfBuffer,
  980. pName,
  981. &pScope,
  982. &lNameSize);
  983. if (NT_SUCCESS(status))
  984. {
  985. //
  986. // see if the name is still active in the local hash table
  987. //
  988. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  989. status = FindInHashTable(NbtConfig.pLocalHashTbl, pName, pScope, &pResp);
  990. if ((pNameHdr->OpCodeFlags & NM_FLAGS_MASK) == OP_QUERY)
  991. {
  992. if (NT_SUCCESS(status))
  993. {
  994. //
  995. // if not resolved then set to negative name query resp.
  996. //
  997. if (!(pResp->NameTypeState & STATE_RESOLVED))
  998. {
  999. pNameHdr->OpCodeFlags |= htons(NAME_ERROR);
  1000. }
  1001. }
  1002. //
  1003. // We can have a scenario where the local machine was a DC
  1004. // at one time, so it set the UNIX to tell Wins when registering
  1005. // the local name.A However, once that machine is downgraded,
  1006. // Wins will still have the UNIX flag set for that record if
  1007. // there were other DC's also present.
  1008. // Thus, we can have the following scenario where the machine
  1009. // is currently not a DC, but the UNIX flag is set in the response
  1010. // so we should not mark the name in Error. This would not
  1011. // be a problem if the client is configured with other Wins
  1012. // server addresses, but otherwise it could cause problems!
  1013. // Bug # 54659
  1014. //
  1015. else if (pName[NETBIOS_NAME_SIZE-1] != SPECIAL_GROUP_SUFFIX)
  1016. {
  1017. pNameHdr->OpCodeFlags |= htons(NAME_ERROR);
  1018. }
  1019. }
  1020. else
  1021. {
  1022. //
  1023. // check if it is a release response - if so we must have
  1024. // received a name release request, so mark the name in
  1025. // conflict and return a positive release response.
  1026. //
  1027. // Note: The case we are looking at here is if another Wins
  1028. // sent a NameRelease demand for some name to the local machine.
  1029. // Since we pass all name releases up to Wins, NetBT will
  1030. // not get a chance to determine if it is a local name when
  1031. // the release first came in.
  1032. // Typically, Wins should make the call properly as to whether
  1033. // NetBT should mark the local name in conflict or not, but
  1034. // it has been observed that Wins displayed inconsistent behavior
  1035. // setting the UNIX flag only if the local machine was the last
  1036. // to register/refresh the name (Bug # 431042).
  1037. // For now, we will remove this functionality for Group names.
  1038. //
  1039. if (pNameHdr->OpCodeFlags & OP_RESPONSE)
  1040. {
  1041. //
  1042. // Bug # 206192: If we are sending the response to
  1043. // ourselves, don't put the name into conflict
  1044. // (could be due to NbtStat -RR!)
  1045. //
  1046. if (NT_SUCCESS(status) &&
  1047. (pResp->NameTypeState & STATE_RESOLVED) &&
  1048. (pResp->NameTypeState & NAMETYPE_UNIQUE) &&
  1049. !(pNameHdr->OpCodeFlags & FL_RCODE) && // Only for positive name release response
  1050. !(SrcIsUs(ntohl(pSendAddr->IpAddress))))
  1051. {
  1052. NbtLogEvent (EVENT_NBT_NAME_RELEASE, pSendAddr->IpAddress, 0x122);
  1053. pResp->NameTypeState &= ~NAME_STATE_MASK;
  1054. pResp->NameTypeState |= STATE_CONFLICT;
  1055. pResp->ConflictMask |= pResp->AdapterMask;
  1056. }
  1057. }
  1058. }
  1059. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1060. }
  1061. }
  1062. //
  1063. // the name is not in the local table so fail the datagram send attempt
  1064. //
  1065. return(STATUS_SUCCESS);
  1066. }
  1067. //----------------------------------------------------------------------------
  1068. VOID
  1069. WinsDgramCompletion(
  1070. IN tDGRAM_SEND_TRACKING *pTracker,
  1071. IN NTSTATUS status,
  1072. IN ULONG Length
  1073. )
  1074. /*++
  1075. Routine Description
  1076. This routine cleans up after a data gram send.
  1077. Arguments:
  1078. pTracker
  1079. status
  1080. Length
  1081. Return Values:
  1082. VOID
  1083. --*/
  1084. {
  1085. CTELockHandle OldIrq;
  1086. LIST_ENTRY *pEntry;
  1087. PIRP pIrp;
  1088. BOOLEAN MustSend;
  1089. #ifdef _PNP_POWER_
  1090. tDEVICECONTEXT *pDeviceContext;
  1091. #endif
  1092. //
  1093. // free the buffer used for sending the data and the tracker - note
  1094. // that the datagram header and the send buffer are allocated as one
  1095. // chunk.
  1096. //
  1097. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1098. if ((pWinsInfo) &&
  1099. (pTracker->ClientContext == IntToPtr(pWinsInfo->WinsSignature)))
  1100. {
  1101. WinsFreeMem(pWinsInfo,
  1102. (PVOID)pTracker->SendBuffer.pDgramHdr,
  1103. pTracker->AllocatedLength,
  1104. FALSE);
  1105. if (!IsListEmpty(&pWinsInfo->SendList))
  1106. {
  1107. #ifdef _PNP_POWER_
  1108. //
  1109. // If there are no devices available to send this request on,
  1110. // complete all pending requests gracefully
  1111. //
  1112. if (!(pDeviceContext = pWinsInfo->pDeviceContext) ||
  1113. !(NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_WINS, TRUE)))
  1114. {
  1115. status = STATUS_PLUGPLAY_NO_DEVICE;
  1116. while (!IsListEmpty(&pWinsInfo->SendList))
  1117. {
  1118. pEntry = RemoveHeadList(&pWinsInfo->SendList);
  1119. pIrp = CONTAINING_RECORD(pEntry,IRP,Tail.Overlay.ListEntry);
  1120. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1121. NbtCancelCancelRoutine (pIrp);
  1122. pIrp->IoStatus.Status = status;
  1123. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  1124. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1125. }
  1126. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1127. FreeTracker (pTracker, RELINK_TRACKER);
  1128. return;
  1129. }
  1130. #endif // _PNP_POWER_
  1131. IF_DBG(NBT_DEBUG_WINS)
  1132. KdPrint(("Nbt:Sending another Wins Dgram that is Queued to go\n"));
  1133. pEntry = RemoveHeadList(&pWinsInfo->SendList);
  1134. pIrp = CONTAINING_RECORD(pEntry,IRP,Tail.Overlay.ListEntry);
  1135. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1136. NbtCancelCancelRoutine (pIrp);
  1137. //
  1138. // Send this next datagram
  1139. //
  1140. status = WinsSendDatagram(pDeviceContext,
  1141. pIrp,
  1142. MustSend = TRUE);
  1143. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_WINS, FALSE);
  1144. }
  1145. else
  1146. {
  1147. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1148. }
  1149. }
  1150. else
  1151. {
  1152. //
  1153. // just free the memory since WINS has closed its address handle.
  1154. //
  1155. CTEMemFree((PVOID)pTracker->SendBuffer.pDgramHdr);
  1156. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1157. }
  1158. FreeTracker (pTracker, RELINK_TRACKER);
  1159. }
  1160. //----------------------------------------------------------------------------
  1161. PVOID
  1162. WinsAllocMem(
  1163. IN tWINS_INFO *pWinsContext,
  1164. IN ULONG Size,
  1165. IN BOOLEAN Rcv
  1166. )
  1167. /*++
  1168. Routine Description:
  1169. This Routine handles allocating memory and keeping track of how
  1170. much has been allocated.
  1171. Arguments:
  1172. Size - number of bytes to allocate
  1173. Rcv - boolean that indicates if it is rcv or send buffering
  1174. Return Value:
  1175. ptr to the memory allocated
  1176. --*/
  1177. {
  1178. if (Rcv)
  1179. {
  1180. if (pWinsContext->RcvMemoryAllocated > pWinsContext->RcvMemoryMax)
  1181. {
  1182. return NULL;
  1183. }
  1184. else
  1185. {
  1186. pWinsContext->RcvMemoryAllocated += Size;
  1187. return (NbtAllocMem(Size,NBT_TAG('v')));
  1188. }
  1189. }
  1190. else
  1191. {
  1192. if (pWinsContext->SendMemoryAllocated > pWinsContext->SendMemoryMax)
  1193. {
  1194. return(NULL);
  1195. }
  1196. else
  1197. {
  1198. pWinsContext->SendMemoryAllocated += Size;
  1199. return(NbtAllocMem(Size,NBT_TAG('v')));
  1200. }
  1201. }
  1202. }
  1203. //----------------------------------------------------------------------------
  1204. VOID
  1205. WinsFreeMem(
  1206. IN tWINS_INFO *pWinsContext,
  1207. IN PVOID pBuffer,
  1208. IN ULONG Size,
  1209. IN BOOLEAN Rcv
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. This Routine handles freeing memory and keeping track of how
  1214. much has been allocated.
  1215. Arguments:
  1216. pBuffer - buffer to free
  1217. Size - number of bytes to allocate
  1218. Rcv - boolean that indicates if it is rcv or send buffering
  1219. Return Value:
  1220. none
  1221. --*/
  1222. {
  1223. if (pWinsContext)
  1224. {
  1225. if (Rcv)
  1226. {
  1227. pWinsContext->RcvMemoryAllocated -= Size;
  1228. }
  1229. else
  1230. {
  1231. pWinsContext->SendMemoryAllocated -= Size;
  1232. }
  1233. }
  1234. CTEMemFree(pBuffer);
  1235. }