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.

757 lines
14 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. This module contains all debug-related code.
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. arvindm 06-13-96 Created
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. #include "ntddk.h"
  15. #include <cxport.h>
  16. #include "ndis.h"
  17. #include "debug.h"
  18. #if DBG
  19. #ifdef ATMARP_WIN98
  20. INT AaDebugLevel=AAD_WARNING;
  21. INT AaMcDebugLevel=AAD_WARNING;
  22. #else
  23. INT AaDebugLevel=AAD_WARNING;
  24. INT AaMcDebugLevel=AAD_WARNING;
  25. #endif
  26. INT AaDataDebugLevel=0;
  27. INT AadBigDataLength=8000;
  28. INT AaSkipAll = 0;
  29. PAAD_ALLOCATION AadMemoryHead = (PAAD_ALLOCATION)NULL;
  30. PAAD_ALLOCATION AadMemoryTail = (PAAD_ALLOCATION)NULL;
  31. ULONG AadAllocCount = 0; // how many allocated so far (unfreed)
  32. NDIS_SPIN_LOCK AadMemoryLock;
  33. BOOLEAN AadInitDone = FALSE;
  34. PVOID
  35. AaAuditAllocMem(
  36. PVOID pPointer,
  37. ULONG Size,
  38. ULONG FileNumber,
  39. ULONG LineNumber
  40. )
  41. {
  42. PVOID pBuffer;
  43. PAAD_ALLOCATION pAllocInfo;
  44. if (!AadInitDone)
  45. {
  46. NdisAllocateSpinLock(&(AadMemoryLock));
  47. AadInitDone = TRUE;
  48. }
  49. NdisAllocateMemoryWithTag(
  50. (PVOID *)&pAllocInfo,
  51. Size+FIELD_OFFSET(AAD_ALLOCATION, UserData),
  52. (ULONG)'CPRA'
  53. );
  54. if (pAllocInfo == (PAAD_ALLOCATION)NULL)
  55. {
  56. AADEBUGP(AAD_VERY_LOUD+50,
  57. ("AaAuditAllocMem: file %d, line %d, Size %d failed!\n",
  58. FileNumber, LineNumber, Size));
  59. pBuffer = NULL;
  60. }
  61. else
  62. {
  63. pBuffer = (PVOID)&(pAllocInfo->UserData);
  64. AA_SET_MEM(pBuffer, 0xaf, Size);
  65. pAllocInfo->Signature = AAD_MEMORY_SIGNATURE;
  66. pAllocInfo->FileNumber = FileNumber;
  67. pAllocInfo->LineNumber = LineNumber;
  68. pAllocInfo->Size = Size;
  69. pAllocInfo->Location = pPointer;
  70. pAllocInfo->Next = (PAAD_ALLOCATION)NULL;
  71. NdisAcquireSpinLock(&(AadMemoryLock));
  72. pAllocInfo->Prev = AadMemoryTail;
  73. if (AadMemoryTail == (PAAD_ALLOCATION)NULL)
  74. {
  75. // empty list
  76. AadMemoryHead = AadMemoryTail = pAllocInfo;
  77. }
  78. else
  79. {
  80. AadMemoryTail->Next = pAllocInfo;
  81. }
  82. AadMemoryTail = pAllocInfo;
  83. AadAllocCount++;
  84. NdisReleaseSpinLock(&(AadMemoryLock));
  85. }
  86. AADEBUGP(AAD_VERY_LOUD+100,
  87. ("AaAuditAllocMem: file %c%c%c%c, line %d, %d bytes, [0x%x] <- 0x%x\n",
  88. (CHAR)(FileNumber & 0xff),
  89. (CHAR)((FileNumber >> 8) & 0xff),
  90. (CHAR)((FileNumber >> 16) & 0xff),
  91. (CHAR)((FileNumber >> 24) & 0xff),
  92. LineNumber, Size, pPointer, pBuffer));
  93. return (pBuffer);
  94. }
  95. VOID
  96. AaAuditFreeMem(
  97. PVOID Pointer
  98. )
  99. {
  100. PAAD_ALLOCATION pAllocInfo;
  101. pAllocInfo = STRUCT_OF(AAD_ALLOCATION, Pointer, UserData);
  102. if (pAllocInfo->Signature != AAD_MEMORY_SIGNATURE)
  103. {
  104. AADEBUGP(AAD_ERROR,
  105. ("AaAuditFreeMem: unknown buffer 0x%x!\n", Pointer));
  106. #ifdef DBG
  107. DbgBreakPoint();
  108. #endif
  109. return;
  110. }
  111. NdisAcquireSpinLock(&(AadMemoryLock));
  112. pAllocInfo->Signature = (ULONG)'DEAD';
  113. if (pAllocInfo->Prev != (PAAD_ALLOCATION)NULL)
  114. {
  115. pAllocInfo->Prev->Next = pAllocInfo->Next;
  116. }
  117. else
  118. {
  119. AadMemoryHead = pAllocInfo->Next;
  120. }
  121. if (pAllocInfo->Next != (PAAD_ALLOCATION)NULL)
  122. {
  123. pAllocInfo->Next->Prev = pAllocInfo->Prev;
  124. }
  125. else
  126. {
  127. AadMemoryTail = pAllocInfo->Prev;
  128. }
  129. AadAllocCount--;
  130. NdisReleaseSpinLock(&(AadMemoryLock));
  131. NdisFreeMemory(pAllocInfo, 0, 0);
  132. }
  133. VOID
  134. AaAuditShutdown(
  135. VOID
  136. )
  137. {
  138. if (AadInitDone)
  139. {
  140. if (AadAllocCount != 0)
  141. {
  142. AADEBUGP(AAD_ERROR, ("AuditShutdown: unfreed memory, %d blocks!\n",
  143. AadAllocCount));
  144. AADEBUGP(AAD_ERROR, ("MemoryHead: 0x%x, MemoryTail: 0x%x\n",
  145. AadMemoryHead, AadMemoryTail));
  146. DbgBreakPoint();
  147. {
  148. PAAD_ALLOCATION pAllocInfo;
  149. while (AadMemoryHead != (PAAD_ALLOCATION)NULL)
  150. {
  151. pAllocInfo = AadMemoryHead;
  152. AADEBUGP(AAD_INFO, ("AuditShutdown: will free 0x%x\n", pAllocInfo));
  153. AaAuditFreeMem(&(pAllocInfo->UserData));
  154. }
  155. }
  156. }
  157. AadInitDone = FALSE;
  158. }
  159. }
  160. #define MAX_HD_LENGTH 128
  161. VOID
  162. DbgPrintHexDump(
  163. IN PUCHAR pBuffer,
  164. IN ULONG Length
  165. )
  166. /*++
  167. Routine Description:
  168. Print a hex dump of the given contiguous buffer. If the length
  169. is too long, we truncate it.
  170. Arguments:
  171. pBuffer - Points to start of data to be dumped
  172. Length - Length of above.
  173. Return Value:
  174. None
  175. --*/
  176. {
  177. ULONG i;
  178. if (Length > MAX_HD_LENGTH)
  179. {
  180. Length = MAX_HD_LENGTH;
  181. }
  182. for (i = 0; i < Length; i++)
  183. {
  184. //
  185. // Check if we are at the end of a line
  186. //
  187. if ((i > 0) && ((i & 0xf) == 0))
  188. {
  189. DbgPrint("\n");
  190. }
  191. //
  192. // Print addr if we are at start of a new line
  193. //
  194. if ((i & 0xf) == 0)
  195. {
  196. DbgPrint("%08x ", pBuffer);
  197. }
  198. DbgPrint(" %02x", *pBuffer++);
  199. }
  200. //
  201. // Terminate the last line.
  202. //
  203. if (Length > 0)
  204. {
  205. DbgPrint("\n");
  206. }
  207. }
  208. VOID
  209. DbgPrintAtmAddr(
  210. IN PCHAR pString,
  211. IN ATM_ADDRESS UNALIGNED * pAddr
  212. )
  213. {
  214. ULONG i;
  215. ULONG NumOfDigits;
  216. PUCHAR pSrc, pDst;
  217. UCHAR AddrString[(ATM_ADDRESS_LENGTH*2) + 1];
  218. //
  219. // Prepare the Address string in ASCII
  220. //
  221. if ((NumOfDigits = pAddr->NumberOfDigits) > ATM_ADDRESS_LENGTH)
  222. {
  223. NumOfDigits = ATM_ADDRESS_LENGTH;
  224. }
  225. pSrc = pAddr->Address;
  226. pDst = AddrString;
  227. for (i = 0; i < NumOfDigits; i++, pSrc++)
  228. {
  229. *pDst = ((*pSrc) >> 4);
  230. *pDst += (((*pDst) > 9) ? ('A' - 10) : '0');
  231. pDst++;
  232. *pDst = ((*pSrc) & 0x0F);
  233. *pDst += (((*pDst) > 9) ? ('A' - 10) : '0');
  234. pDst++;
  235. }
  236. *pDst = '\0';
  237. DbgPrint("%s%s\n", pString, AddrString);
  238. }
  239. VOID
  240. DbgPrintMapping(
  241. IN PCHAR pString,
  242. IN UCHAR UNALIGNED * pIpAddr,
  243. IN ATM_ADDRESS UNALIGNED * pAtmAddr
  244. )
  245. {
  246. DbgPrint("ATMARPC: %s %d.%d.%d.%d -> ",
  247. pString,
  248. ((PUCHAR)pIpAddr)[0],
  249. ((PUCHAR)pIpAddr)[1],
  250. ((PUCHAR)pIpAddr)[2],
  251. ((PUCHAR)pIpAddr)[3]
  252. );
  253. DbgPrintAtmAddr("", pAtmAddr);
  254. }
  255. ULONG OutstandingSends = 0;
  256. VOID
  257. AaCoSendPackets(
  258. IN NDIS_HANDLE NdisVcHandle,
  259. IN PNDIS_PACKET * PacketArray,
  260. IN UINT PacketCount
  261. )
  262. {
  263. PNDIS_PACKET pNdisPacket;
  264. UINT c;
  265. NDIS_STATUS Status;
  266. PNDIS_BUFFER pNdisBuffer;
  267. PULONG pContext;
  268. for (c = 0; c < PacketCount; c++)
  269. {
  270. pNdisPacket = PacketArray[c];
  271. AA_ASSERT(pNdisPacket->Private.Head != NULL);
  272. Status = NDIS_GET_PACKET_STATUS(pNdisPacket);
  273. AA_ASSERT(Status != NDIS_STATUS_FAILURE);
  274. pContext = (PULONG)&(pNdisPacket->WrapperReserved[0]);
  275. *pContext = 'AaAa';
  276. }
  277. NdisInterlockedIncrement(&OutstandingSends);
  278. NdisCoSendPackets(NdisVcHandle, PacketArray, PacketCount);
  279. }
  280. #endif // DBG
  281. #if DBG_SPIN_LOCK
  282. ULONG AadSpinLockInitDone = 0;
  283. NDIS_SPIN_LOCK AadLockLock;
  284. VOID
  285. AtmArpAllocateSpinLock(
  286. IN PATMARP_LOCK pLock,
  287. IN ULONG FileNumber,
  288. IN ULONG LineNumber
  289. )
  290. {
  291. if (AadSpinLockInitDone == 0)
  292. {
  293. AadSpinLockInitDone = 1;
  294. NdisAllocateSpinLock(&(AadLockLock));
  295. }
  296. NdisAcquireSpinLock(&(AadLockLock));
  297. pLock->Signature = AAL_SIG;
  298. pLock->TouchedByFileNumber = FileNumber;
  299. pLock->TouchedInLineNumber = LineNumber;
  300. pLock->IsAcquired = 0;
  301. pLock->OwnerThread = 0;
  302. NdisAllocateSpinLock(&(pLock->NdisLock));
  303. NdisReleaseSpinLock(&(AadLockLock));
  304. }
  305. VOID
  306. AtmArpAcquireSpinLock(
  307. IN PATMARP_LOCK pLock,
  308. IN ULONG FileNumber,
  309. IN ULONG LineNumber
  310. )
  311. {
  312. PKTHREAD pThread;
  313. pThread = KeGetCurrentThread();
  314. NdisAcquireSpinLock(&(AadLockLock));
  315. if (pLock->Signature != AAL_SIG)
  316. {
  317. DbgPrint("Trying to acquire uninited lock 0x%x, File %c%c%c%c, Line %d\n",
  318. pLock,
  319. (CHAR)(FileNumber & 0xff),
  320. (CHAR)((FileNumber >> 8) & 0xff),
  321. (CHAR)((FileNumber >> 16) & 0xff),
  322. (CHAR)((FileNumber >> 24) & 0xff),
  323. LineNumber);
  324. DbgBreakPoint();
  325. }
  326. if (pLock->IsAcquired != 0)
  327. {
  328. if (pLock->OwnerThread == pThread)
  329. {
  330. DbgPrint("Detected multiple locking!: pLock 0x%x, File %c%c%c%c, Line %d\n",
  331. pLock,
  332. (CHAR)(FileNumber & 0xff),
  333. (CHAR)((FileNumber >> 8) & 0xff),
  334. (CHAR)((FileNumber >> 16) & 0xff),
  335. (CHAR)((FileNumber >> 24) & 0xff),
  336. LineNumber);
  337. DbgPrint("pLock 0x%x already acquired in File %c%c%c%c, Line %d\n",
  338. pLock,
  339. (CHAR)(pLock->TouchedByFileNumber & 0xff),
  340. (CHAR)((pLock->TouchedByFileNumber >> 8) & 0xff),
  341. (CHAR)((pLock->TouchedByFileNumber >> 16) & 0xff),
  342. (CHAR)((pLock->TouchedByFileNumber >> 24) & 0xff),
  343. pLock->TouchedInLineNumber);
  344. DbgBreakPoint();
  345. }
  346. }
  347. pLock->IsAcquired++;
  348. NdisReleaseSpinLock(&(AadLockLock));
  349. NdisAcquireSpinLock(&(pLock->NdisLock));
  350. //
  351. // Mark this lock.
  352. //
  353. pLock->OwnerThread = pThread;
  354. pLock->TouchedByFileNumber = FileNumber;
  355. pLock->TouchedInLineNumber = LineNumber;
  356. }
  357. VOID
  358. AtmArpReleaseSpinLock(
  359. IN PATMARP_LOCK pLock,
  360. IN ULONG FileNumber,
  361. IN ULONG LineNumber
  362. )
  363. {
  364. NdisDprAcquireSpinLock(&(AadLockLock));
  365. if (pLock->Signature != AAL_SIG)
  366. {
  367. DbgPrint("Trying to release uninited lock 0x%x, File %c%c%c%c, Line %d\n",
  368. pLock,
  369. (CHAR)(FileNumber & 0xff),
  370. (CHAR)((FileNumber >> 8) & 0xff),
  371. (CHAR)((FileNumber >> 16) & 0xff),
  372. (CHAR)((FileNumber >> 24) & 0xff),
  373. LineNumber);
  374. DbgBreakPoint();
  375. }
  376. if (pLock->IsAcquired == 0)
  377. {
  378. DbgPrint("Detected release of unacquired lock 0x%x, File %c%c%c%c, Line %d\n",
  379. pLock,
  380. (CHAR)(FileNumber & 0xff),
  381. (CHAR)((FileNumber >> 8) & 0xff),
  382. (CHAR)((FileNumber >> 16) & 0xff),
  383. (CHAR)((FileNumber >> 24) & 0xff),
  384. LineNumber);
  385. DbgBreakPoint();
  386. }
  387. pLock->TouchedByFileNumber = FileNumber;
  388. pLock->TouchedInLineNumber = LineNumber;
  389. pLock->IsAcquired--;
  390. pLock->OwnerThread = 0;
  391. NdisDprReleaseSpinLock(&(AadLockLock));
  392. NdisReleaseSpinLock(&(pLock->NdisLock));
  393. }
  394. #endif // DBG_SPIN_LOCK
  395. #ifdef PERF
  396. #define MAX_SEND_LOG_ENTRIES 100
  397. LARGE_INTEGER TimeFrequency;
  398. BOOLEAN SendLogInitDone = FALSE;
  399. BOOLEAN SendLogUpdate = TRUE;
  400. NDIS_SPIN_LOCK SendLogLock;
  401. AAD_SEND_LOG_ENTRY SendLog[MAX_SEND_LOG_ENTRIES];
  402. ULONG SendLogIndex = 0;
  403. PAAD_SEND_LOG_ENTRY pSendLog = SendLog;
  404. ULONG MaxSendTime;
  405. #define TIME_TO_ULONG(_pTime) *((PULONG)_pTime)
  406. VOID
  407. AadLogSendStart(
  408. IN PNDIS_PACKET pNdisPacket,
  409. IN ULONG Destination,
  410. IN PVOID pRCE
  411. )
  412. {
  413. ULONG Length;
  414. if (SendLogInitDone == FALSE)
  415. {
  416. SendLogInitDone = TRUE;
  417. (VOID)KeQueryPerformanceCounter(&TimeFrequency);
  418. MaxSendTime = (TIME_TO_ULONG(&TimeFrequency) * 2)/3;
  419. NdisAllocateSpinLock(&SendLogLock);
  420. }
  421. NdisQueryPacket(
  422. pNdisPacket,
  423. NULL,
  424. NULL,
  425. NULL,
  426. &Length
  427. );
  428. NdisAcquireSpinLock(&SendLogLock);
  429. pSendLog->Flags = AAD_SEND_FLAG_WAITING_COMPLETION;
  430. if (pRCE != NULL)
  431. {
  432. pSendLog->Flags |= AAD_SEND_FLAG_RCE_GIVEN;
  433. }
  434. pSendLog->pNdisPacket = pNdisPacket;
  435. pSendLog->Destination = Destination;
  436. pSendLog->Length = Length;
  437. pSendLog->SendTime = KeQueryPerformanceCounter(&TimeFrequency);
  438. pSendLog++;
  439. SendLogIndex++;
  440. if (SendLogIndex == MAX_SEND_LOG_ENTRIES)
  441. {
  442. SendLogIndex = 0;
  443. pSendLog = SendLog;
  444. }
  445. NdisReleaseSpinLock(&SendLogLock);
  446. }
  447. VOID
  448. AadLogSendUpdate(
  449. IN PNDIS_PACKET pNdisPacket
  450. )
  451. {
  452. PAAD_SEND_LOG_ENTRY pEntry;
  453. ULONG Index;
  454. ULONG SendTime;
  455. if (!SendLogUpdate)
  456. {
  457. return;
  458. }
  459. NdisAcquireSpinLock(&SendLogLock);
  460. pEntry = SendLog;
  461. for (Index = 0; Index < MAX_SEND_LOG_ENTRIES; Index++)
  462. {
  463. if (((pEntry->Flags & AAD_SEND_FLAG_WAITING_COMPLETION) != 0) &&
  464. (pEntry->pNdisPacket == pNdisPacket))
  465. {
  466. pEntry->SendTime = KeQueryPerformanceCounter(&TimeFrequency);
  467. break;
  468. }
  469. pEntry++;
  470. }
  471. NdisReleaseSpinLock(&SendLogLock);
  472. }
  473. VOID
  474. AadLogSendComplete(
  475. IN PNDIS_PACKET pNdisPacket
  476. )
  477. {
  478. PAAD_SEND_LOG_ENTRY pEntry;
  479. ULONG Index;
  480. ULONG SendTime;
  481. NdisAcquireSpinLock(&SendLogLock);
  482. pEntry = SendLog;
  483. for (Index = 0; Index < MAX_SEND_LOG_ENTRIES; Index++)
  484. {
  485. if (((pEntry->Flags & AAD_SEND_FLAG_WAITING_COMPLETION) != 0) &&
  486. (pEntry->pNdisPacket == pNdisPacket))
  487. {
  488. pEntry->Flags &= ~AAD_SEND_FLAG_WAITING_COMPLETION;
  489. pEntry->Flags |= AAD_SEND_FLAG_COMPLETED;
  490. pEntry->SendCompleteTime = KeQueryPerformanceCounter(&TimeFrequency);
  491. if (((pEntry->Flags & AAD_SEND_FLAG_RCE_GIVEN) != 0) &&
  492. ((SendTime = TIME_TO_ULONG(&pEntry->SendCompleteTime) -
  493. TIME_TO_ULONG(&pEntry->SendTime)) > MaxSendTime))
  494. {
  495. DbgPrint("Dest %d.%d.%d.%d, Pkt 0x%x, Len %d, Flags 0x%x, Took Long %d (0x%x)\n",
  496. ((PUCHAR)&pEntry->Destination)[0],
  497. ((PUCHAR)&pEntry->Destination)[1],
  498. ((PUCHAR)&pEntry->Destination)[2],
  499. ((PUCHAR)&pEntry->Destination)[3],
  500. pNdisPacket, pEntry->Length, pEntry->Flags, SendTime, SendTime);
  501. }
  502. break;
  503. }
  504. pEntry++;
  505. }
  506. NdisReleaseSpinLock(&SendLogLock);
  507. }
  508. VOID
  509. AadLogSendAbort(
  510. IN PNDIS_PACKET pNdisPacket
  511. )
  512. {
  513. PAAD_SEND_LOG_ENTRY pEntry;
  514. ULONG Index;
  515. ULONG SendTime;
  516. NdisAcquireSpinLock(&SendLogLock);
  517. pEntry = SendLog;
  518. for (Index = 0; Index < MAX_SEND_LOG_ENTRIES; Index++)
  519. {
  520. if (((pEntry->Flags & AAD_SEND_FLAG_WAITING_COMPLETION) != 0) &&
  521. (pEntry->pNdisPacket == pNdisPacket))
  522. {
  523. pEntry->Flags = 0;
  524. break;
  525. }
  526. pEntry++;
  527. }
  528. NdisReleaseSpinLock(&SendLogLock);
  529. }
  530. #endif // PERF
  531. #if DBG
  532. extern
  533. VOID
  534. AtmArpReferenceAtmEntryEx(
  535. IN PATMARP_ATM_ENTRY pAtmEntry,
  536. AE_REFTYPE RefType
  537. )
  538. {
  539. AA_ASSERT(RefType>=0 && RefType < AE_REFTYPE_COUNT);
  540. pAtmEntry->Refs[RefType]++;
  541. // AA_ASSERT(pAtmEntry->Refs[RefType] < 128);
  542. AtmArpReferenceAtmEntry(pAtmEntry);
  543. }
  544. extern
  545. ULONG
  546. AtmArpDereferenceAtmEntryEx(
  547. IN PATMARP_ATM_ENTRY pAtmEntry,
  548. IN AE_REFTYPE RefType,
  549. IN BOOLEAN fOkToDelete
  550. )
  551. {
  552. AA_ASSERT(RefType>=0 && RefType < AE_REFTYPE_COUNT);
  553. // AA_ASSERT(pAtmEntry->Refs[RefType]);
  554. pAtmEntry->Refs[RefType]--;
  555. if (fOkToDelete)
  556. {
  557. return AtmArpDereferenceAtmEntry(pAtmEntry);
  558. }
  559. else
  560. {
  561. AA_ASSERT(pAtmEntry->RefCount);
  562. return --(pAtmEntry->RefCount);
  563. }
  564. }
  565. extern
  566. VOID
  567. AtmArpReferenceIPEntryEx(
  568. IN PATMARP_IP_ENTRY pIpEntry,
  569. IN IE_REFTYPE RefType
  570. )
  571. {
  572. AA_ASSERT(RefType>=0 && RefType < IE_REFTYPE_COUNT);
  573. pIpEntry->Refs[RefType]++;
  574. // AA_ASSERT(pIpEntry->Refs[RefType] < 128);
  575. AtmArpReferenceIPEntry(pIpEntry);
  576. }
  577. extern
  578. ULONG
  579. AtmArpDereferenceIPEntryEx(
  580. IN PATMARP_IP_ENTRY pIpEntry,
  581. IN IE_REFTYPE RefType,
  582. IN BOOLEAN fOkToDelete
  583. )
  584. {
  585. AA_ASSERT(RefType>=0 && RefType < IE_REFTYPE_COUNT);
  586. // AA_ASSERT(pIpEntry->Refs[RefType]);
  587. pIpEntry->Refs[RefType]--;
  588. if (fOkToDelete)
  589. {
  590. return AtmArpDereferenceIPEntry(pIpEntry);
  591. }
  592. else
  593. {
  594. AA_ASSERT(pIpEntry->RefCount);
  595. return --(pIpEntry->RefCount);
  596. }
  597. }
  598. VOID
  599. AtmArpReferenceJoinEntryEx(
  600. IN PATMARP_IPMC_JOIN_ENTRY pJoinEntry,
  601. IN ULONG RefInfo
  602. )
  603. {
  604. AA_STRUCT_ASSERT(pJoinEntry, aamj);
  605. pJoinEntry->LastIncrRef = RefInfo;
  606. AtmArpReferenceJoinEntry(pJoinEntry);
  607. }
  608. ULONG
  609. AtmArpDereferenceJoinEntryEx(
  610. IN PATMARP_IPMC_JOIN_ENTRY pJoinEntry,
  611. IN ULONG RefInfo
  612. )
  613. {
  614. AA_STRUCT_ASSERT(pJoinEntry, aamj);
  615. pJoinEntry->LastDecrRef = RefInfo;
  616. return (AtmArpDereferenceJoinEntry(pJoinEntry));
  617. }
  618. #endif //DBG