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.

921 lines
19 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. This file contains the code to read the registry.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com) July 1996
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include <precomp.h>
  14. #define _FILENUM_ FILENUM_REGISTRY
  15. NTSTATUS
  16. ArpSReadGlobalConfiguration(
  17. IN PUNICODE_STRING RegistryPath
  18. )
  19. /*++
  20. Routine Description:
  21. Read the global registry.
  22. Arguments:
  23. RegistryPath - Pointer to the service section in the registry.
  24. Return Value:
  25. Error code from registry apis.
  26. --*/
  27. {
  28. NDIS_STATUS Status;
  29. NDIS_HANDLE ConfigHandle;
  30. //
  31. // Open the per-adapter registry config
  32. //
  33. NdisOpenProtocolConfiguration(&Status,
  34. &ConfigHandle,
  35. RegistryPath);
  36. if (Status == NDIS_STATUS_SUCCESS)
  37. {
  38. NDIS_STRING ArpsBufString = NDIS_STRING_CONST("ArpBuffers");
  39. NDIS_STRING FlushString = NDIS_STRING_CONST("FlushTime");
  40. PNDIS_CONFIGURATION_PARAMETER Param;
  41. //
  42. // Read number of configured buffers
  43. //
  44. NdisReadConfiguration(&Status,
  45. &Param,
  46. ConfigHandle,
  47. &ArpsBufString,
  48. NdisParameterInteger);
  49. if ((Status == NDIS_STATUS_SUCCESS) &&
  50. (Param->ParameterType == NdisParameterInteger))
  51. {
  52. ArpSBuffers = Param->ParameterData.IntegerData;
  53. }
  54. //
  55. // Should we save cache in a file ?
  56. //
  57. NdisReadConfiguration(&Status,
  58. &Param,
  59. ConfigHandle,
  60. &FlushString,
  61. NdisParameterInteger);
  62. if ((Status == NDIS_STATUS_SUCCESS) &&
  63. (Param->ParameterType == NdisParameterInteger))
  64. {
  65. ArpSFlushTime = (USHORT)(Param->ParameterData.IntegerData * MULTIPLIER);
  66. }
  67. NdisCloseConfiguration(ConfigHandle);
  68. }
  69. return NDIS_STATUS_SUCCESS;
  70. }
  71. NDIS_STATUS
  72. ArpSReadAdapterConfigFromRegistry(
  73. IN PINTF pIntF,
  74. OUT PATMARPS_CONFIG pConfig
  75. )
  76. /*++
  77. Routine Description:
  78. Read configuration for the specified interface.
  79. Arguments:
  80. pIntF - Interface
  81. pConfig - Place to return information read in.
  82. Return Value:
  83. Error code from registry apis.
  84. --*/
  85. {
  86. NDIS_STATUS Status;
  87. NDIS_HANDLE ConfigHandle;
  88. //
  89. // Open the per-adapter registry config
  90. //
  91. NdisOpenProtocolConfiguration(&Status,
  92. &ConfigHandle,
  93. &pIntF->ConfigString);
  94. if (Status == NDIS_STATUS_SUCCESS)
  95. {
  96. NDIS_STRING RegdAddrsString = NDIS_STRING_CONST("RegisteredAddresses");
  97. NDIS_STRING SelString = NDIS_STRING_CONST("Selector");
  98. NDIS_STRING McsString = NDIS_STRING_CONST("MulticastAddresses");
  99. PNDIS_CONFIGURATION_PARAMETER Param;
  100. PWSTR p;
  101. UINT i, Length;
  102. //
  103. // Read the value, if present for the selector byte to be used for the registered sap
  104. // for the std. address (as opposed to added addresses).
  105. //
  106. pConfig->SelByte = 0;
  107. NdisReadConfiguration(&Status,
  108. &Param,
  109. ConfigHandle,
  110. &SelString,
  111. NdisParameterInteger);
  112. if ((Status == NDIS_STATUS_SUCCESS) &&
  113. (Param->ParameterType == NdisParameterInteger) &&
  114. (Param->ParameterData.IntegerData <= 0xFF))
  115. {
  116. pConfig->SelByte = (UCHAR)(Param->ParameterData.IntegerData);
  117. DBGPRINT(DBG_LEVEL_INFO,
  118. ("Selector byte for interface %Z is %d\n",
  119. &pIntF->InterfaceName, pConfig->SelByte));
  120. }
  121. //
  122. // Read registered addresses here. On an interface there can be a set of
  123. // atm addresses registered. These need to be added and SAPs registered on
  124. // them.
  125. //
  126. pConfig->NumAllocedRegdAddresses = 0;
  127. pConfig->RegAddresses = NULL;
  128. NdisReadConfiguration(&Status,
  129. &Param,
  130. ConfigHandle,
  131. &RegdAddrsString,
  132. NdisParameterMultiString);
  133. if ((Status == NDIS_STATUS_SUCCESS) && (Param->ParameterType == NdisParameterMultiString))
  134. {
  135. NDIS_STRING String;
  136. //
  137. // Param now contains a list of atm addresses. Convert them into the right format and store
  138. // it in the intf structure. First determine the number of addresses.
  139. //
  140. for (p = Param->ParameterData.StringData.Buffer, i = 0;
  141. *p != L'\0';
  142. i++)
  143. {
  144. RtlInitUnicodeString(&String, p);
  145. DBGPRINT(DBG_LEVEL_INFO,
  146. ("Configured address for interface %Z - %Z\n",
  147. &pIntF->InterfaceName, &String));
  148. p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
  149. }
  150. if (i)
  151. {
  152. //
  153. // Allocate space for the addresses
  154. //
  155. pConfig->RegAddresses = (PATM_ADDRESS)ALLOC_NP_MEM(sizeof(ATM_ADDRESS) * i, POOL_TAG_ADDR);
  156. if (pConfig->RegAddresses == NULL)
  157. {
  158. LOG_ERROR(NDIS_STATUS_RESOURCES);
  159. }
  160. else
  161. {
  162. DBGPRINT(DBG_LEVEL_INFO,
  163. ("%d addresses registered for %Z\n", i, &pIntF->InterfaceName));
  164. ZERO_MEM(pConfig->RegAddresses, sizeof(ATM_ADDRESS) * i);
  165. for (i = 0, p = Param->ParameterData.StringData.Buffer;
  166. *p != L'\0';
  167. NOTHING)
  168. {
  169. RtlInitUnicodeString(&String, p);
  170. NdisConvertStringToAtmAddress(&Status, &String, &pConfig->RegAddresses[i]);
  171. if (Status == NDIS_STATUS_SUCCESS)
  172. {
  173. i++;
  174. pConfig->NumAllocedRegdAddresses ++;
  175. }
  176. else
  177. {
  178. DBGPRINT(DBG_LEVEL_ERROR,
  179. ("ArpSReadAdapterConfiguration: Failed to convert address %Z\n",
  180. &String));
  181. }
  182. p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
  183. }
  184. }
  185. }
  186. }
  187. pConfig->pMcsList = NULL;
  188. NdisReadConfiguration(&Status,
  189. &Param,
  190. ConfigHandle,
  191. &McsString,
  192. NdisParameterMultiString);
  193. if ((Status == NDIS_STATUS_SUCCESS) && (Param->ParameterType == NdisParameterMultiString))
  194. {
  195. NDIS_STRING String;
  196. //
  197. // Param now contains a list of Multicast IP Address ranges.
  198. // Each string is of the form "M.M.M.M-N.N.N.N"
  199. // Read them in.
  200. //
  201. for (p = Param->ParameterData.StringData.Buffer, i = 0;
  202. *p != L'\0';
  203. i++)
  204. {
  205. RtlInitUnicodeString(&String, p);
  206. DBGPRINT(DBG_LEVEL_INFO,
  207. ("Configured Multicast range for interface %Z - %Z\n",
  208. &pIntF->InterfaceName, &String));
  209. p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
  210. }
  211. //
  212. // Allocate space for the addresses
  213. //
  214. pConfig->pMcsList = (PMCS_ENTRY)ALLOC_NP_MEM(sizeof(MCS_ENTRY) * i, POOL_TAG_MARS);
  215. if (pConfig->pMcsList == (PMCS_ENTRY)NULL)
  216. {
  217. LOG_ERROR(NDIS_STATUS_RESOURCES);
  218. }
  219. else
  220. {
  221. DBGPRINT(DBG_LEVEL_INFO,
  222. ("%d Multicast ranges configured on %Z\n", i, &pIntF->InterfaceName));
  223. ZERO_MEM(pConfig->pMcsList, sizeof(MCS_ENTRY) * i);
  224. for (i = 0, p = Param->ParameterData.StringData.Buffer;
  225. *p != L'\0';
  226. NOTHING)
  227. {
  228. RtlInitUnicodeString(&String, p);
  229. ArpSConvertStringToIpPair(&Status, &String, &pConfig->pMcsList[i]);
  230. if (Status == NDIS_STATUS_SUCCESS)
  231. {
  232. if (i > 0)
  233. {
  234. pConfig->pMcsList[i-1].Next = &(pConfig->pMcsList[i]);
  235. }
  236. i++;
  237. }
  238. else
  239. {
  240. DBGPRINT(DBG_LEVEL_ERROR,
  241. ("ArpSReadAdapterConfiguration: Failed to convert IP Range %Z\n",
  242. &String));
  243. }
  244. p = (PWSTR)((PUCHAR)p + String.Length + sizeof(WCHAR));
  245. }
  246. }
  247. }
  248. //
  249. // Close the configuration handle
  250. //
  251. NdisCloseConfiguration(ConfigHandle);
  252. Status = NDIS_STATUS_SUCCESS;
  253. }
  254. return Status;
  255. }
  256. NDIS_STATUS
  257. ArpSReadAdapterConfiguration(
  258. IN PINTF pIntF
  259. )
  260. /*++
  261. Routine Description:
  262. Read the registry for parameters for the specified Interface.
  263. This could be in response to a reconfiguration event, in which
  264. case handle existing values/structures.
  265. Arguments:
  266. pIntF - Interface to be read in.
  267. Return Value:
  268. Error code from registry apis.
  269. --*/
  270. {
  271. NDIS_STATUS Status;
  272. ATMARPS_CONFIG AtmArpSConfig;
  273. KIRQL OldIrql;
  274. ULONG PrevNumAllocedRegdAddresses;
  275. PATM_ADDRESS PrevRegAddresses;
  276. PMCS_ENTRY PrevMcsList;
  277. Status = ArpSReadAdapterConfigFromRegistry(pIntF, &AtmArpSConfig);
  278. if (Status == NDIS_STATUS_SUCCESS)
  279. {
  280. //
  281. // Copy them into the interface structure. We could be handling a
  282. // parameter reconfig, so any space used to store old information.
  283. //
  284. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  285. //
  286. // Selector Byte:
  287. //
  288. pIntF->SelByte = AtmArpSConfig.SelByte;
  289. //
  290. // List of addresses to be registered with the switch.
  291. // Take out the old list first. We'll have to delete those
  292. // addresses (deregister them from the switch).
  293. //
  294. PrevNumAllocedRegdAddresses = pIntF->NumAllocedRegdAddresses;
  295. PrevRegAddresses = pIntF->RegAddresses;
  296. //
  297. // Get the new list in:
  298. //
  299. pIntF->NumAllocedRegdAddresses = AtmArpSConfig.NumAllocedRegdAddresses;
  300. pIntF->RegAddresses = AtmArpSConfig.RegAddresses;
  301. pIntF->NumAddressesRegd = 0; // reset count of addresses regd with switch
  302. //
  303. // Take out the old MCS list and insert the new one.
  304. //
  305. PrevMcsList = pIntF->pMcsList;
  306. pIntF->pMcsList = AtmArpSConfig.pMcsList;
  307. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  308. //
  309. // Deregister all previously registered addresses with the switch.
  310. //
  311. if (PrevNumAllocedRegdAddresses)
  312. {
  313. ArpSDeleteIntFAddresses(pIntF, PrevNumAllocedRegdAddresses, PrevRegAddresses);
  314. //
  315. // Register the new list of addresses with the switch.
  316. //
  317. ArpSQueryAndSetAddresses(pIntF);
  318. }
  319. //
  320. // Free unused memory.
  321. //
  322. if (PrevMcsList)
  323. {
  324. FREE_MEM(PrevMcsList);
  325. }
  326. if (PrevRegAddresses)
  327. {
  328. FREE_MEM(PrevRegAddresses);
  329. }
  330. }
  331. return Status;
  332. }
  333. VOID
  334. ArpSConvertStringToIpPair(
  335. OUT PNDIS_STATUS pStatus,
  336. IN PNDIS_STRING pString,
  337. IN PMCS_ENTRY pMcsEntry
  338. )
  339. /*++
  340. Routine Description:
  341. Extract a pair of IP addresses that identify a range of multicast addresses
  342. that this MCS serves, from the given string.
  343. Arguments:
  344. pStatus - Place to return status
  345. pString - Points to string containing "<IP1>-<IP2>"
  346. pMcsEntry - Entry to read into.
  347. Return Value:
  348. None. *pStatus is set to indicate the status of this call.
  349. --*/
  350. {
  351. PWSTR pMin, pMax;
  352. IPADDR Min, Max;
  353. ULONG Length;
  354. ULONG i;
  355. ARPS_PAGED_CODE();
  356. Length = pString->Length;
  357. *pStatus = NDIS_STATUS_FAILURE;
  358. do
  359. {
  360. //
  361. // Locate the '-' and replace it with a NULL char.
  362. //
  363. pMin = pString->Buffer;
  364. pMax = pString->Buffer;
  365. for (i = 0; i < Length; i++, pMax++)
  366. {
  367. if (*pMax == L'-')
  368. {
  369. *pMax++ = L'\0';
  370. break;
  371. }
  372. }
  373. if (i == Length)
  374. {
  375. break; // Didn't find '-'
  376. }
  377. if (IPConvertStringToAddress(pMin, &Min) &&
  378. IPConvertStringToAddress(pMax, &Max))
  379. {
  380. DBGPRINT(DBG_LEVEL_INFO, ("MCS pair: "));
  381. ArpSDumpIpAddr(Min, " to ");
  382. ArpSDumpIpAddr(Max, "\n");
  383. pMcsEntry->GrpAddrPair.MinAddr = Min;
  384. pMcsEntry->GrpAddrPair.MaxAddr = Max;
  385. *pStatus = NDIS_STATUS_SUCCESS;
  386. }
  387. break;
  388. }
  389. while (FALSE);
  390. }
  391. #define IP_ADDRESS_STRING_LENGTH (16+2) // +2 for double NULL on MULTI_SZ
  392. BOOLEAN
  393. IPConvertStringToAddress(
  394. IN PWCHAR AddressString,
  395. OUT PULONG IpAddress
  396. )
  397. /*++
  398. Routine Description
  399. This function converts an Internet standard 4-octet dotted decimal
  400. IP address string into a numeric IP address. Unlike inet_addr(), this
  401. routine does not support address strings of less than 4 octets nor does
  402. it support octal and hexadecimal octets.
  403. Copied from tcpip\ip\ntip.c
  404. Arguments
  405. AddressString - IP address in dotted decimal notation
  406. IpAddress - Pointer to a variable to hold the resulting address
  407. Return Value:
  408. TRUE if the address string was converted. FALSE otherwise.
  409. --*/
  410. {
  411. UNICODE_STRING unicodeString;
  412. STRING aString;
  413. UCHAR dataBuffer[IP_ADDRESS_STRING_LENGTH];
  414. NTSTATUS status;
  415. PUCHAR addressPtr, cp, startPointer, endPointer;
  416. ULONG digit, multiplier;
  417. int i;
  418. ARPS_PAGED_CODE();
  419. aString.Length = 0;
  420. aString.MaximumLength = IP_ADDRESS_STRING_LENGTH;
  421. aString.Buffer = dataBuffer;
  422. RtlInitUnicodeString(&unicodeString, AddressString);
  423. status = RtlUnicodeStringToAnsiString(
  424. &aString,
  425. &unicodeString,
  426. FALSE
  427. );
  428. if (!NT_SUCCESS(status)) {
  429. return(FALSE);
  430. }
  431. *IpAddress = 0;
  432. addressPtr = (PUCHAR) IpAddress;
  433. startPointer = dataBuffer;
  434. endPointer = dataBuffer;
  435. i = 3;
  436. while (i >= 0) {
  437. //
  438. // Collect the characters up to a '.' or the end of the string.
  439. //
  440. while ((*endPointer != '.') && (*endPointer != '\0')) {
  441. endPointer++;
  442. }
  443. if (startPointer == endPointer) {
  444. return(FALSE);
  445. }
  446. //
  447. // Convert the number.
  448. //
  449. for ( cp = (endPointer - 1), multiplier = 1, digit = 0;
  450. cp >= startPointer;
  451. cp--, multiplier *= 10
  452. ) {
  453. if ((*cp < '0') || (*cp > '9') || (multiplier > 100)) {
  454. return(FALSE);
  455. }
  456. digit += (multiplier * ((ULONG) (*cp - '0')));
  457. }
  458. if (digit > 255) {
  459. return(FALSE);
  460. }
  461. addressPtr[i] = (UCHAR) digit;
  462. //
  463. // We are finished if we have found and converted 4 octets and have
  464. // no other characters left in the string.
  465. //
  466. if ( (i-- == 0) &&
  467. ((*endPointer == '\0') || (*endPointer == ' '))
  468. ) {
  469. return(TRUE);
  470. }
  471. if (*endPointer == '\0') {
  472. return(FALSE);
  473. }
  474. startPointer = ++endPointer;
  475. }
  476. return(FALSE);
  477. }
  478. VOID
  479. ArpSReadArpCache(
  480. IN PINTF pIntF
  481. )
  482. /*++
  483. Routine Description:
  484. Read the per-adapter Arp Cache. TBD.
  485. Arguments:
  486. pIntF - Per adapter arp cache.
  487. Return Value:
  488. None
  489. --*/
  490. {
  491. HANDLE FileHandle;
  492. OBJECT_ATTRIBUTES ObjectAttributes;
  493. IO_STATUS_BLOCK IoStatus;
  494. NTSTATUS Status;
  495. LARGE_INTEGER Offset;
  496. ULONG Space, NumEntries;
  497. PDISK_HEADER DskHdr;
  498. PUCHAR Buffer;
  499. PDISK_ENTRY pDskEntry;
  500. PARP_ENTRY ArpEntry;
  501. Buffer = ALLOC_PG_MEM(DISK_BUFFER_SIZE);
  502. if (Buffer == NULL)
  503. {
  504. LOG_ERROR(NDIS_STATUS_RESOURCES);
  505. return;
  506. }
  507. InitializeObjectAttributes(&ObjectAttributes,
  508. &pIntF->FileName,
  509. OBJ_CASE_INSENSITIVE,
  510. NULL,
  511. NULL);
  512. Status = ZwCreateFile(&FileHandle,
  513. SYNCHRONIZE | FILE_READ_DATA,
  514. &ObjectAttributes,
  515. &IoStatus,
  516. NULL,
  517. 0,
  518. 0,
  519. FILE_OPEN,
  520. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY,
  521. NULL,
  522. 0);
  523. if (Status == STATUS_SUCCESS)
  524. {
  525. do
  526. {
  527. //
  528. // First read the disk header and validate it
  529. //
  530. Offset.QuadPart = 0;
  531. Status = ZwReadFile(FileHandle,
  532. NULL,
  533. NULL,
  534. NULL,
  535. &IoStatus,
  536. Buffer,
  537. DISK_BUFFER_SIZE,
  538. &Offset,
  539. NULL);
  540. if (Status != STATUS_SUCCESS)
  541. {
  542. LOG_ERROR(Status);
  543. break;
  544. }
  545. DskHdr = (PDISK_HEADER)Buffer;
  546. if ((IoStatus.Information < sizeof(DISK_HEADER)) ||
  547. (DskHdr->Signature != DISK_HDR_SIGNATURE) ||
  548. (DskHdr->Version != DISK_HDR_VERSION))
  549. {
  550. LOG_ERROR(STATUS_INVALID_LEVEL);
  551. break;
  552. }
  553. NumEntries = DskHdr->NumberOfArpEntries;
  554. Space = (ULONG) IoStatus.Information - sizeof(DISK_HEADER);
  555. pDskEntry = (PDISK_ENTRY)(Buffer + sizeof(DISK_HEADER));
  556. Offset.QuadPart = sizeof(DISK_HEADER);
  557. while (NumEntries > 0)
  558. {
  559. UINT Consumed;
  560. if ((Space < sizeof(DISK_ENTRY)) ||
  561. (Space < (sizeof(DISK_ENTRY) + pDskEntry->AtmAddr.SubAddrLen)))
  562. {
  563. Status = ZwReadFile(FileHandle,
  564. NULL,
  565. NULL,
  566. NULL,
  567. &IoStatus,
  568. Buffer,
  569. DISK_BUFFER_SIZE,
  570. &Offset,
  571. NULL);
  572. if (Status != STATUS_SUCCESS)
  573. {
  574. LOG_ERROR(Status);
  575. break;
  576. }
  577. pDskEntry = (PDISK_ENTRY)Buffer;
  578. if ((IoStatus.Information < sizeof(DISK_ENTRY)) ||
  579. (IoStatus.Information < (sizeof(DISK_ENTRY) + pDskEntry->AtmAddr.SubAddrLen)))
  580. {
  581. LOG_ERROR(STATUS_INVALID_LEVEL);
  582. break;
  583. }
  584. Space = (ULONG) IoStatus.Information - sizeof(DISK_HEADER);
  585. }
  586. ArpEntry = ArpSAddArpEntryFromDisk(pIntF, pDskEntry);
  587. ASSERT (ArpEntry != NULL);
  588. Consumed = (sizeof(DISK_ENTRY) + SIZE_4N(pDskEntry->AtmAddr.SubAddrLen));
  589. (PUCHAR)pDskEntry += Consumed;
  590. Offset.QuadPart += Consumed;
  591. Space -= Consumed;
  592. NumEntries --;
  593. }
  594. } while (FALSE);
  595. ZwClose(FileHandle);
  596. }
  597. FREE_MEM(Buffer);
  598. }
  599. BOOLEAN
  600. ArpSWriteArpCache(
  601. IN PINTF pIntF,
  602. IN PTIMER Timer,
  603. IN BOOLEAN TimerShuttingDown
  604. )
  605. /*++
  606. Routine Description:
  607. Write the per-adapter Arp Cache. TBD.
  608. Arguments:
  609. pIntF - Per adapter arp cache.
  610. Timer - FlushTimer
  611. TimerShuttingDown - Do not requeue when set.
  612. Return Value:
  613. TRUE to requeue unless TimerShuttingDown is set
  614. --*/
  615. {
  616. HANDLE FileHandle;
  617. OBJECT_ATTRIBUTES ObjectAttributes;
  618. IO_STATUS_BLOCK IoStatus;
  619. NTSTATUS Status;
  620. LARGE_INTEGER Offset;
  621. ULONG Space, i;
  622. PDISK_HEADER DskHdr;
  623. PUCHAR Buffer;
  624. PDISK_ENTRY pDskEntry;
  625. PARP_ENTRY ArpEntry;
  626. TIME SystemTime, LocalTime;
  627. ULONG CurrentTime;
  628. Buffer = ALLOC_PG_MEM(DISK_BUFFER_SIZE);
  629. if (Buffer == NULL)
  630. {
  631. LOG_ERROR(NDIS_STATUS_RESOURCES);
  632. return (!TimerShuttingDown);
  633. }
  634. KeQuerySystemTime(&SystemTime);
  635. ExSystemTimeToLocalTime(&SystemTime, &LocalTime);
  636. // Convert this to number of seconds since 1980
  637. if (!RtlTimeToSecondsSince1980(&LocalTime, &CurrentTime))
  638. {
  639. // Could not convert! Bail out.
  640. LOG_ERROR(NDIS_STATUS_BUFFER_OVERFLOW);
  641. FREE_MEM(Buffer);
  642. return (!TimerShuttingDown);
  643. }
  644. InitializeObjectAttributes(&ObjectAttributes,
  645. &pIntF->FileName,
  646. OBJ_CASE_INSENSITIVE,
  647. NULL,
  648. NULL);
  649. Status = ZwCreateFile(&FileHandle,
  650. SYNCHRONIZE | FILE_WRITE_DATA,
  651. &ObjectAttributes,
  652. &IoStatus,
  653. NULL,
  654. 0,
  655. 0,
  656. FILE_OVERWRITE_IF,
  657. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY,
  658. NULL,
  659. 0);
  660. if (Status == STATUS_SUCCESS)
  661. {
  662. do
  663. {
  664. Offset.QuadPart = 0;
  665. Space = DISK_BUFFER_SIZE - sizeof(DISK_HEADER);
  666. DskHdr = (PDISK_HEADER)Buffer;
  667. pDskEntry = (PDISK_ENTRY)(Buffer + sizeof(DISK_HEADER));
  668. DskHdr->Signature = DISK_HDR_SIGNATURE;
  669. DskHdr->Version = DISK_HDR_VERSION;
  670. DskHdr->NumberOfArpEntries = pIntF->NumCacheEntries;
  671. DskHdr->TimeStamp = CurrentTime;
  672. for (i =0; i < ARP_TABLE_SIZE; i++)
  673. {
  674. for (ArpEntry = pIntF->ArpCache[i];
  675. ArpEntry != NULL;
  676. ArpEntry = ArpEntry->Next)
  677. {
  678. UINT Size;
  679. Size = sizeof(DISK_ENTRY) + ((ArpEntry->HwAddr.SubAddress != NULL) ?
  680. SIZE_4N(ArpEntry->HwAddr.SubAddress->NumberOfDigits) : 0);
  681. if (Space < Size)
  682. {
  683. Status = ZwWriteFile(FileHandle,
  684. NULL,
  685. NULL,
  686. NULL,
  687. &IoStatus,
  688. Buffer,
  689. DISK_BUFFER_SIZE - Space,
  690. &Offset,
  691. NULL);
  692. if (Status != STATUS_SUCCESS)
  693. {
  694. LOG_ERROR(Status);
  695. break;
  696. }
  697. Space = DISK_BUFFER_SIZE;
  698. pDskEntry = (PDISK_ENTRY)Buffer;
  699. Offset.QuadPart += (DISK_BUFFER_SIZE - Space);
  700. }
  701. pDskEntry->IpAddr = ArpEntry->IpAddr;
  702. pDskEntry->AtmAddr.AddrType = (UCHAR)ArpEntry->HwAddr.Address.AddressType;
  703. pDskEntry->AtmAddr.AddrLen = (UCHAR)ArpEntry->HwAddr.Address.NumberOfDigits;
  704. COPY_MEM(pDskEntry->AtmAddr.Address,
  705. ArpEntry->HwAddr.Address.Address,
  706. pDskEntry->AtmAddr.AddrLen);
  707. pDskEntry->AtmAddr.SubAddrLen = 0;
  708. if (ArpEntry->HwAddr.SubAddress != NULL)
  709. {
  710. pDskEntry->AtmAddr.SubAddrLen = (UCHAR)ArpEntry->HwAddr.SubAddress->NumberOfDigits;
  711. pDskEntry->AtmAddr.SubAddrType = (UCHAR)ArpEntry->HwAddr.SubAddress->AddressType;
  712. COPY_MEM((PUCHAR)pDskEntry + sizeof(DISK_ENTRY),
  713. ArpEntry->HwAddr.SubAddress->Address,
  714. pDskEntry->AtmAddr.SubAddrLen);
  715. }
  716. Space -= Size;
  717. (PUCHAR)pDskEntry += Size;
  718. }
  719. if (Status != STATUS_SUCCESS)
  720. {
  721. break;
  722. }
  723. }
  724. } while (FALSE);
  725. if ((Status == STATUS_SUCCESS) && (Space < DISK_BUFFER_SIZE))
  726. {
  727. Status = ZwWriteFile(FileHandle,
  728. NULL,
  729. NULL,
  730. NULL,
  731. &IoStatus,
  732. Buffer,
  733. DISK_BUFFER_SIZE - Space,
  734. &Offset,
  735. NULL);
  736. }
  737. ZwClose(FileHandle);
  738. }
  739. FREE_MEM(Buffer);
  740. return (!TimerShuttingDown);
  741. }