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.

978 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1997, Microsoft Corporation
  4. //
  5. // File: csites.cxx
  6. //
  7. // Contents: This module contains the functions which deal with the site table
  8. //
  9. // History: 02-Dec-1997 JHarper Created.
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "headers.hxx"
  13. #pragma hdrstop
  14. #include "dfsmsrv.h"
  15. #include "csites.hxx"
  16. #include "marshal.hxx"
  17. INIT_DFS_SITENAME_INFO_MARSHAL_INFO();
  18. INIT_DFS_SITELIST_INFO_MARSHAL_INFO()
  19. INIT_DFSM_SITE_ENTRY_MARSHAL_INFO();
  20. NTSTATUS
  21. DfsSendDelete(
  22. LPWSTR ServerName);
  23. //+----------------------------------------------------------------------------
  24. //
  25. // Function: CSites::CSites
  26. //
  27. // Synopsis: Constructor for CSites - Initializes, but does not load, the site table
  28. //
  29. // Arguments: [pwszFileName] -- Name of the folder/LDAP_OBJECT to use
  30. // [pdwErr] -- On return, the result of initializing the instance
  31. //
  32. // Returns: Result returned in pdwErr argument:
  33. //
  34. // [ERROR_SUCCESS] -- Successfully initialized
  35. //
  36. // [ERROR_OUTOFMEMORY] -- Out of memory.
  37. //
  38. //-----------------------------------------------------------------------------
  39. CSites::CSites(
  40. LPWSTR pwszFileName,
  41. LPDWORD pdwErr)
  42. {
  43. DWORD dwErr = 0;
  44. IDfsVolInlineDebOut((
  45. DEB_TRACE, "CSites::+CSites(0x%x)\n",
  46. this));
  47. #if DBG
  48. if (DfsSvcVerbose)
  49. DbgPrint("+++CSites::CSites @0x%x\n", this);
  50. #endif
  51. _cRef = 0;
  52. _fDirty = FALSE;
  53. RtlZeroMemory(&_SiteTableGuid, sizeof(GUID));
  54. InitializeListHead(&_SiteTableHead);
  55. _pwszFileName = new WCHAR [wcslen(pwszFileName) + 1];
  56. if (_pwszFileName != NULL) {
  57. wcscpy(_pwszFileName, pwszFileName);
  58. } else {
  59. dwErr = ERROR_OUTOFMEMORY;
  60. }
  61. *pdwErr = dwErr;
  62. }
  63. //+----------------------------------------------------------------------------
  64. //
  65. // Function: CSites::~CSites
  66. //
  67. // Synopsis: Destructor for CSites - Deallocates the CSites object
  68. //
  69. // Arguments: None
  70. //
  71. // Returns: Nothing
  72. //
  73. //-----------------------------------------------------------------------------
  74. CSites::~CSites()
  75. {
  76. PLIST_ENTRY pListHead;
  77. PDFSM_SITE_ENTRY pSiteInfo;
  78. IDfsVolInlineDebOut((
  79. DEB_TRACE, "CSites::~CSites(0x%x)\n",
  80. this));
  81. #if DBG
  82. if (DfsSvcVerbose)
  83. DbgPrint("---CSites::~CSites @0x%x\n", this);
  84. #endif
  85. ASSERT (_cRef == 0);
  86. if (_pwszFileName) {
  87. delete [] _pwszFileName;
  88. }
  89. //
  90. // Delete the linked list of SiteInfo's
  91. //
  92. pListHead = &_SiteTableHead;
  93. while (pListHead->Flink != pListHead) {
  94. pSiteInfo = CONTAINING_RECORD(pListHead->Flink, DFSM_SITE_ENTRY, Link);
  95. RemoveEntryList(pListHead->Flink);
  96. #if DBG
  97. if (DfsSvcVerbose)
  98. DbgPrint("CSites::~CSites: deleting SiteInfo@0x%x\n", pSiteInfo);
  99. #endif
  100. delete [] pSiteInfo;
  101. }
  102. }
  103. //+----------------------------------------------------------------------------
  104. //
  105. // Function: CSites::AddRef
  106. //
  107. // Synopsis: Increases the ref count on the in-memory site table. If the
  108. // refcount is going from 0 to 1, an attempt is made to refresh
  109. // the in-memory site table from storage.
  110. //
  111. // Arguments: None
  112. //
  113. // Returns: Nothing
  114. //
  115. //-----------------------------------------------------------------------------
  116. VOID
  117. CSites::AddRef()
  118. {
  119. DWORD dwErr = 0;
  120. IDfsVolInlineDebOut((DEB_TRACE, "CSites::AddRef()\n"));
  121. _cRef++;
  122. if (_cRef == 1) {
  123. dwErr = _ReadSiteTable();
  124. _fDirty = FALSE;
  125. }
  126. }
  127. //+----------------------------------------------------------------------------
  128. //
  129. // Function: CSites::Release
  130. //
  131. // Synopsis: Decrease the ref count on the in-memory site table. If the
  132. // refcount is going from 1 to 0, then attempt to flush the
  133. // table to storage, if something has changed.
  134. //
  135. // Arguments: None
  136. //
  137. // Returns: Nothing
  138. //
  139. //-----------------------------------------------------------------------------
  140. VOID
  141. CSites::Release()
  142. {
  143. IDfsVolInlineDebOut((DEB_TRACE, "CSites::Release()\n"));
  144. ASSERT (_cRef > 0);
  145. _cRef--;
  146. if (_cRef == 0) {
  147. if (_fDirty == TRUE) {
  148. _WriteSiteTable();
  149. _fDirty = FALSE;
  150. }
  151. }
  152. }
  153. //+----------------------------------------------------------------------------
  154. //
  155. // Function: CSites::AddOrUpdateSiteInfo
  156. //
  157. // Synopsis: Adds or updates an entry in the site table.
  158. //
  159. // Arguments: [pServerName] -- Server name to update
  160. // [SiteCount] -- Number of entries in pSites
  161. // [pSites] -- pointer to array of site information.
  162. //
  163. // Returns: [ERROR_SUCCESS] -- Successfully updated the table
  164. //
  165. //-----------------------------------------------------------------------------
  166. DWORD
  167. CSites::AddOrUpdateSiteInfo(
  168. LPWSTR pServerName,
  169. ULONG SiteCount,
  170. PDFS_SITENAME_INFO pSites)
  171. {
  172. PDFSM_SITE_ENTRY pSiteInfo;
  173. PDFSM_SITE_ENTRY pExistingInfo;
  174. DWORD dwErr;
  175. ULONG i;
  176. IDfsVolInlineDebOut((DEB_TRACE, "CSites::AddOrUpdateSiteInfo(%ws)\n", pServerName));
  177. dwErr = _AllocateSiteInfo(
  178. pServerName,
  179. SiteCount,
  180. pSites,
  181. &pSiteInfo);
  182. if (dwErr == ERROR_SUCCESS) {
  183. //
  184. // Only put the new entry in if it supercedes one there,
  185. // or is a new entry.
  186. //
  187. pExistingInfo = LookupSiteInfo(pServerName);
  188. if (pExistingInfo != NULL) {
  189. if (_CompareEntries(pSiteInfo,pExistingInfo) == TRUE ) {
  190. //
  191. // Same info - no update needed
  192. //
  193. delete [] pSiteInfo;
  194. } else {
  195. //
  196. // Remove the existing entry
  197. //
  198. RemoveEntryList(&pExistingInfo->Link);
  199. delete [] pExistingInfo;
  200. //
  201. // Put the new one in
  202. //
  203. DfsSendUpdate(pServerName,SiteCount,pSites);
  204. InsertHeadList(&_SiteTableHead, &pSiteInfo->Link);
  205. _fDirty = TRUE;
  206. }
  207. } else {
  208. //
  209. // Not in table - put it in
  210. //
  211. DfsSendUpdate(pServerName,SiteCount,pSites);
  212. InsertHeadList(&_SiteTableHead, &pSiteInfo->Link);
  213. _fDirty = TRUE;
  214. }
  215. }
  216. return ERROR_SUCCESS;
  217. }
  218. //+----------------------------------------------------------------------------
  219. //
  220. // Function: CSites::LookupSiteInfo
  221. //
  222. // Synopsis: Finds a site table entry
  223. //
  224. // Arguments: [pServerName] -- Server name to look up
  225. //
  226. // Returns: [NULL] -- No entry found
  227. // [PDFSM_SITE_ENTRY] -- pointer to found entry
  228. //
  229. //-----------------------------------------------------------------------------
  230. PDFSM_SITE_ENTRY
  231. CSites::LookupSiteInfo(
  232. LPWSTR pServerName)
  233. {
  234. PLIST_ENTRY pListHead, pLink;
  235. PDFSM_SITE_ENTRY pSiteInfo;
  236. IDfsVolInlineDebOut((DEB_TRACE, "CSites::LookupSiteInfo(%ws)\n", pServerName));
  237. pListHead = &_SiteTableHead;
  238. if (pListHead->Flink == pListHead) { // list empty
  239. return NULL;
  240. }
  241. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  242. pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
  243. if (_wcsicmp(pSiteInfo->ServerName,pServerName) == 0) {
  244. //
  245. // If this was marked for delete, it isn't any more.
  246. //
  247. pSiteInfo->Flags &= ~DFSM_SITE_ENTRY_DELETE_PENDING;
  248. return pSiteInfo;
  249. }
  250. }
  251. return NULL;
  252. }
  253. //+----------------------------------------------------------------------------
  254. //
  255. // Function: CSites::_AllocateSiteInfo, private
  256. //
  257. // Synopsis: Creates a DFSM_SITE_ENTRY struct, as one contiguous chunk of memory
  258. //
  259. // Arguments: [pServerName] -- Server name
  260. // [SiteCount] -- Number of entries in pSites
  261. // [pSites] -- pointer to array of site information.
  262. // [ppSiteInfo] -- pointer to pointer for the results
  263. //
  264. // Returns: [ERROR_SUCCESS] -- Successfully allocated and filled in the structure
  265. // [ERROR_OUTOFMEMORY] -- Couldn't allocate needed memory
  266. //
  267. //-----------------------------------------------------------------------------
  268. DWORD
  269. CSites::_AllocateSiteInfo(
  270. PWSTR pServerName,
  271. ULONG SiteCount,
  272. PDFS_SITENAME_INFO pSites,
  273. PDFSM_SITE_ENTRY *ppSiteInfo)
  274. {
  275. PDFSM_SITE_ENTRY pSiteInfo;
  276. WCHAR *wCp;
  277. ULONG i;
  278. ULONG Size = 0;
  279. IDfsVolInlineDebOut((DEB_TRACE, "CSites::_AllocateSiteInfo(%ws)\n", pServerName));
  280. //
  281. // Calculate the size chunk of mem we'll need
  282. //
  283. Size = FIELD_OFFSET(DFSM_SITE_ENTRY,Info.Site[SiteCount]);
  284. //
  285. // Add space for server name
  286. //
  287. Size += (wcslen(pServerName) + 1) * sizeof(WCHAR);
  288. //
  289. // And space for all the sitenames
  290. //
  291. for (i = 0; i < SiteCount; i++) {
  292. if (pSites[i].SiteName != NULL) {
  293. Size += (wcslen(pSites[i].SiteName) + 1) * sizeof(WCHAR);
  294. } else {
  295. Size += sizeof(WCHAR);
  296. }
  297. }
  298. pSiteInfo = (PDFSM_SITE_ENTRY) new CHAR [Size];
  299. if (pSiteInfo == NULL) {
  300. *ppSiteInfo = NULL;
  301. return ERROR_OUTOFMEMORY;
  302. }
  303. RtlZeroMemory(pSiteInfo, Size);
  304. //
  305. // Marshal the info into the buffer
  306. //
  307. pSiteInfo->Flags = 0;
  308. pSiteInfo->Info.cSites = SiteCount;
  309. wCp = (WCHAR *) &pSiteInfo->Info.Site[SiteCount];
  310. pSiteInfo->ServerName = wCp;
  311. wcscpy(wCp, pServerName);
  312. wCp += wcslen(pServerName) + 1;
  313. for (i = 0; i < SiteCount; i++) {
  314. pSiteInfo->Info.Site[i].SiteFlags = pSites[i].SiteFlags;
  315. pSiteInfo->Info.Site[i].SiteName = wCp;
  316. if (pSites[i].SiteName != NULL) {
  317. wcscpy(wCp, pSites[i].SiteName);
  318. wCp += wcslen(pSites[i].SiteName) + 1;
  319. } else {
  320. *wCp++ = UNICODE_NULL;
  321. }
  322. }
  323. *ppSiteInfo = pSiteInfo;
  324. return ERROR_SUCCESS;
  325. }
  326. //+----------------------------------------------------------------------------
  327. //
  328. // Function: CSites::_ReadSiteTable,private
  329. //
  330. // Synopsis: Loads the site table from storage
  331. //
  332. // First we check if the GUID has changed. If it hasn't, we abort the
  333. // load - the existing table is good.
  334. //
  335. // If the table is different (the GUID is different), we merge the new
  336. // data in with the old. This allows us to track which entries need to
  337. // be updated, which need to be deleted, and which haven't changed. The
  338. // process is done in three steps:
  339. //
  340. // Step 1: Go through the table, marking all the entries DELETE_PENDING
  341. // Step 2: Load the new entries. As they are loaded, the updated entries'
  342. // DELETE_PENDING bit(s) are turned off.
  343. // Step 3: Go though the table again, removing any entries that still
  344. // have the DELETE_PENDING bit on, and issuing an FSCTL to dfs.sys
  345. // to have it remove the entry from its table.
  346. //
  347. // Arguments: None
  348. //
  349. // Returns: [ERROR_SUCCESS] -- Successfully loaded the table
  350. // [ERROR_OUTOFMEMORY] -- Not enough memory
  351. // [other] -- returned from LdapGetData/RegGetData/DfsRtlXXX
  352. //
  353. //-----------------------------------------------------------------------------
  354. DWORD
  355. CSites::_ReadSiteTable()
  356. {
  357. DWORD dwErr;
  358. DWORD cbBuffer;
  359. PBYTE pBuffer = NULL;
  360. PBYTE bp;
  361. ULONG cObjects = 0;
  362. ULONG i;
  363. ULONG j;
  364. PDFSM_SITE_ENTRY pSiteInfo;
  365. MARSHAL_BUFFER marshalBuffer;
  366. GUID TempGuid;
  367. IDfsVolInlineDebOut((DEB_TRACE, "CSites::_ReadSiteTable()\n"));
  368. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  369. dwErr = LdapGetData(
  370. _pwszFileName,
  371. &cbBuffer,
  372. (PCHAR *)&pBuffer);
  373. } else {
  374. dwErr = RegGetData(
  375. _pwszFileName,
  376. SITE_VALUE_NAME,
  377. &cbBuffer,
  378. &pBuffer);
  379. }
  380. if (dwErr == ERROR_SUCCESS && cbBuffer >= sizeof(ULONG) + sizeof(GUID)) {
  381. //
  382. // Unmarshal all the objects (DFS_SITENAME_INFO's) in the buffer
  383. //
  384. //
  385. // We marshal into a temporary buffer, big enough to hold whatever is
  386. // in the buffer.
  387. //
  388. pSiteInfo = (PDFSM_SITE_ENTRY) new BYTE [cbBuffer + sizeof(DFSM_SITE_ENTRY)];
  389. if (pSiteInfo == NULL) {
  390. dwErr = ERROR_OUTOFMEMORY;
  391. }
  392. if (dwErr == ERROR_SUCCESS) {
  393. MarshalBufferInitialize(
  394. &marshalBuffer,
  395. cbBuffer,
  396. pBuffer);
  397. DfsRtlGetGuid(&marshalBuffer, &TempGuid);
  398. //
  399. // If the Guid hasn't changed, we abort the load.
  400. //
  401. if (RtlCompareMemory(&TempGuid, &_SiteTableGuid, sizeof(GUID)) == sizeof(GUID)) {
  402. delete [] pSiteInfo;
  403. delete [] pBuffer;
  404. goto NoLoadNecessary;
  405. }
  406. //
  407. // Ok, we're committed to loading this (supposedly different) version
  408. // of the site table. Mark all the existing entries DFSM_SITE_ENTRY_DELETE_PENDING.
  409. //
  410. MarkEntriesForMerge();
  411. //
  412. // Grab the Guid
  413. //
  414. RtlCopyMemory(&_SiteTableGuid, &TempGuid, sizeof(GUID));
  415. //
  416. // Get number of entries we'll be loading
  417. //
  418. DfsRtlGetUlong(&marshalBuffer, &cObjects);
  419. //
  420. // Now unmarshal each object/entry
  421. //
  422. for (j = 0; dwErr == ERROR_SUCCESS && j < cObjects; j++) {
  423. dwErr = DfsRtlGet(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo);
  424. if (dwErr == ERROR_SUCCESS) {
  425. //
  426. // And put it in the site table
  427. //
  428. AddOrUpdateSiteInfo(
  429. pSiteInfo->ServerName,
  430. pSiteInfo->Info.cSites,
  431. &pSiteInfo->Info.Site[0]);
  432. //
  433. // The unmarshalling routines allocate buffers; we need to
  434. // free them.
  435. //
  436. for (i = 0; i < pSiteInfo->Info.cSites; i++) {
  437. MarshalBufferFree(pSiteInfo->Info.Site[i].SiteName);
  438. }
  439. MarshalBufferFree(pSiteInfo->ServerName);
  440. }
  441. //
  442. // Now sync up the PKT in dfs.sys with this table
  443. //
  444. SyncPktSiteTable();
  445. }
  446. delete [] pSiteInfo;
  447. }
  448. }
  449. if (pBuffer != NULL) {
  450. delete [] pBuffer;
  451. }
  452. NoLoadNecessary:
  453. return dwErr;
  454. }
  455. //+----------------------------------------------------------------------------
  456. //
  457. // Function: CSites::_WriteSiteTable,private
  458. //
  459. // Synopsis: Writes the site table to storage
  460. //
  461. // Arguments: None
  462. //
  463. // Returns: [ERROR_SUCCESS] -- Successfully write the table
  464. // [ERROR_OUTOFMEMORY] -- Not enough memory
  465. // [other] -- returned from LdapGetData/RegGetData/DfsRtlXXX
  466. //
  467. //-----------------------------------------------------------------------------
  468. DWORD
  469. CSites::_WriteSiteTable()
  470. {
  471. DWORD dwErr;
  472. DWORD cbBuffer;
  473. PBYTE pBuffer;
  474. ULONG cObjects;
  475. ULONG i;
  476. PLIST_ENTRY pListHead, pLink;
  477. PDFSM_SITE_ENTRY pSiteInfo;
  478. MARSHAL_BUFFER marshalBuffer;
  479. IDfsVolInlineDebOut((DEB_TRACE, "CSites::_WriteSiteTable()\n"));
  480. //
  481. // Create a new Guid
  482. //
  483. UuidCreate(&_SiteTableGuid);
  484. //
  485. // The cObjects count
  486. //
  487. cbBuffer = sizeof(ULONG) + sizeof(GUID);
  488. //
  489. // Add up the number of entries we need to store, and the total size of all
  490. // of them.
  491. //
  492. cObjects = 0;
  493. pListHead = &_SiteTableHead;
  494. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  495. pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
  496. DfsRtlSize(&MiDfsmSiteEntry, pSiteInfo, &cbBuffer);
  497. cObjects++;
  498. }
  499. //
  500. // Get a buffer big enough
  501. //
  502. pBuffer = new BYTE [cbBuffer];
  503. if (pBuffer == NULL) {
  504. return ERROR_OUTOFMEMORY;
  505. }
  506. //
  507. // Put the guid, then the object count in the beginning of the buffer
  508. //
  509. MarshalBufferInitialize(
  510. &marshalBuffer,
  511. cbBuffer,
  512. pBuffer);
  513. DfsRtlPutGuid(&marshalBuffer, &_SiteTableGuid);
  514. DfsRtlPutUlong(&marshalBuffer, &cObjects);
  515. //
  516. // Walk the linked list of objects, marshalling them into the buffer.
  517. //
  518. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  519. pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
  520. DfsRtlPut(&marshalBuffer,&MiDfsmSiteEntry, pSiteInfo);
  521. }
  522. //
  523. // Push out to storage
  524. //
  525. if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
  526. dwErr = LdapPutData(
  527. _pwszFileName,
  528. cbBuffer,
  529. (PCHAR)pBuffer);
  530. } else {
  531. dwErr = RegPutData(
  532. _pwszFileName,
  533. SITE_VALUE_NAME,
  534. cbBuffer,
  535. pBuffer);
  536. }
  537. //
  538. // ...and free the marshal buffer we created.
  539. //
  540. delete [] pBuffer;
  541. return dwErr;
  542. }
  543. //+----------------------------------------------------------------------------
  544. //
  545. // Function: CSites::_CompareEntries,private
  546. //
  547. // Synopsis: Compare two site table entries - case insensitive, and allows the site
  548. // lists to be in different order.
  549. //
  550. // Arguments: None
  551. //
  552. // Returns: [TRUE] -- The entries are essentially identical
  553. // [FALSE] -- The entries differ in some important way
  554. //
  555. //-----------------------------------------------------------------------------
  556. BOOLEAN
  557. CSites::_CompareEntries(
  558. PDFSM_SITE_ENTRY pDfsmInfo1,
  559. PDFSM_SITE_ENTRY pDfsmInfo2)
  560. {
  561. ULONG i;
  562. ULONG j;
  563. BOOLEAN fFound;
  564. //
  565. // cSites has to be the same
  566. //
  567. if (pDfsmInfo1->Info.cSites != pDfsmInfo2->Info.cSites) {
  568. goto ReturnFalse;
  569. }
  570. //
  571. // Server name has to be identical (why are we calling this
  572. // if they aren't?)
  573. //
  574. if (_wcsicmp(pDfsmInfo1->ServerName,pDfsmInfo2->ServerName) != 0) {
  575. goto ReturnFalse;
  576. }
  577. //
  578. // Check that every Site in pDfsmInfo1 is in pDfsmSiteInfo2
  579. //
  580. for (i = 0; i < pDfsmInfo1->Info.cSites; i++) {
  581. fFound = FALSE;
  582. for (j = 0; fFound == FALSE && j < pDfsmInfo2->Info.cSites; j++) {
  583. if (_wcsicmp(
  584. pDfsmInfo1->Info.Site[i].SiteName,
  585. pDfsmInfo2->Info.Site[j].SiteName) == 0) {
  586. fFound = TRUE;
  587. }
  588. }
  589. if (fFound == FALSE) {
  590. goto ReturnFalse;
  591. }
  592. }
  593. //
  594. // ...and check that every site in pDfsmInfo2 is in pDfsmInfo1
  595. //
  596. for (i = 0; i < pDfsmInfo2->Info.cSites; i++) {
  597. fFound = FALSE;
  598. for (j = 0; fFound == FALSE && j < pDfsmInfo1->Info.cSites; j++) {
  599. if (_wcsicmp(
  600. pDfsmInfo2->Info.Site[i].SiteName,
  601. pDfsmInfo1->Info.Site[j].SiteName) == 0) {
  602. fFound = TRUE;
  603. }
  604. }
  605. if (fFound == FALSE) {
  606. goto ReturnFalse;
  607. }
  608. }
  609. return TRUE;
  610. ReturnFalse:
  611. return FALSE;
  612. }
  613. //+----------------------------------------------------------------------------
  614. //
  615. // Function: CSites::MarkEntriesForMerge
  616. //
  617. // Synopsis: Mark all entries in preparation for a merge.
  618. // (1) Mark all entries with delete_pending on
  619. // (2) Load a new table - duplicate entries remove the delete_pending bit
  620. // (3) Call SyncPktSiteTable(), which will bring the PKT in dfs.sys up to date,
  621. // by deleting delete_pending entries
  622. //
  623. // Arguments: None
  624. //
  625. // Returns: nothing
  626. //
  627. //-----------------------------------------------------------------------------
  628. VOID
  629. CSites::MarkEntriesForMerge()
  630. {
  631. PLIST_ENTRY pListHead, pLink;
  632. PDFSM_SITE_ENTRY pSiteInfo;
  633. ULONG i;
  634. pListHead = &_SiteTableHead;
  635. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  636. pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
  637. pSiteInfo->Flags |= DFSM_SITE_ENTRY_DELETE_PENDING;
  638. }
  639. }
  640. //+----------------------------------------------------------------------------
  641. //
  642. // Function: CSites::SyncPktSiteTable
  643. //
  644. // Synopsis: Step 3 of a table merge. Walk the table, removing any entries
  645. // with the DFSM_SITE_ENTRY_DELETE_PENDING (and telling dfs.sys
  646. // to do so)
  647. //
  648. // Arguments: None
  649. //
  650. // Returns: Nothing
  651. //
  652. //-----------------------------------------------------------------------------
  653. VOID
  654. CSites::SyncPktSiteTable()
  655. {
  656. PLIST_ENTRY pListHead;
  657. PLIST_ENTRY pLink;
  658. PLIST_ENTRY pNext;
  659. PDFSM_SITE_ENTRY pSiteInfo;
  660. IDfsVolInlineDebOut((DEB_TRACE, "CSites::SyncPktSiteTable()\n"));
  661. pListHead = &_SiteTableHead;
  662. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pNext) {
  663. //
  664. // Save next in case we delete this one
  665. //
  666. pNext = pLink->Flink;
  667. pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
  668. if ((pSiteInfo->Flags & DFSM_SITE_ENTRY_DELETE_PENDING) != 0) {
  669. //
  670. // call dfs.sys with the update
  671. //
  672. DfsSendDelete(pSiteInfo->ServerName);
  673. RemoveEntryList(pLink);
  674. delete [] pSiteInfo;
  675. _fDirty = TRUE;
  676. }
  677. }
  678. IDfsVolInlineDebOut((DEB_TRACE, "CSites::SyncPktSiteTable exit\n"));
  679. }
  680. //+----------------------------------------------------------------------------
  681. //
  682. // Function: CSites::_DumpSiteTable
  683. //
  684. // Synopsis: Spill dfs's guts about site table entries.
  685. //
  686. // Arguments: None
  687. //
  688. // Returns: Nothing
  689. //
  690. //-----------------------------------------------------------------------------
  691. VOID
  692. CSites::_DumpSiteTable()
  693. {
  694. PLIST_ENTRY pListHead, pLink;
  695. PDFSM_SITE_ENTRY pSiteInfo;
  696. ULONG i;
  697. pListHead = &_SiteTableHead;
  698. //
  699. // Print them (for debugging)
  700. //
  701. for (pLink = pListHead->Flink; pLink != pListHead; pLink = pLink->Flink) {
  702. pSiteInfo = CONTAINING_RECORD(pLink, DFSM_SITE_ENTRY, Link);
  703. DbgPrint("\tpSiteInfo(%ws)\n", pSiteInfo->ServerName);
  704. for (i = 0; i < pSiteInfo->Info.cSites; i++) {
  705. DbgPrint("\t\t%02d:%ws\n", i, pSiteInfo->Info.Site[i].SiteName);
  706. }
  707. }
  708. }
  709. //+----------------------------------------------------------------------------
  710. //
  711. // Function: DfsSendDelete, private
  712. //
  713. // Synopsis: Send a DFS_DELETE_SITE_ARG down to dfs.sys
  714. //
  715. // Arguments: None
  716. //
  717. // Returns: Nothing
  718. //
  719. //-----------------------------------------------------------------------------
  720. NTSTATUS
  721. DfsSendDelete(
  722. LPWSTR ServerName)
  723. {
  724. ULONG size;
  725. DWORD dwErr;
  726. PDFS_DELETE_SITE_INFO_ARG arg;
  727. size = sizeof(DFS_DELETE_SITE_INFO_ARG) +
  728. wcslen(ServerName) * sizeof(WCHAR);
  729. arg = (PDFS_DELETE_SITE_INFO_ARG) new CHAR [size];
  730. if (arg == NULL) {
  731. return ERROR_OUTOFMEMORY;
  732. }
  733. arg->ServerName.Buffer = (WCHAR *) &arg[1];
  734. arg->ServerName.Length = wcslen(ServerName) * sizeof(WCHAR);
  735. arg->ServerName.MaximumLength = arg->ServerName.Length;
  736. RtlCopyMemory(arg->ServerName.Buffer, ServerName, arg->ServerName.Length);
  737. LPWSTR_TO_OFFSET(arg->ServerName.Buffer,arg);
  738. dwErr = DfsDeleteSiteEntry((PCHAR)arg, size);
  739. delete [] arg;
  740. return dwErr;
  741. }
  742. //+----------------------------------------------------------------------------
  743. //
  744. // Function: DfsSendUpdate, private
  745. //
  746. // Synopsis: Send a DFS_CREATE_SITE_ARG down to dfs.sys
  747. //
  748. // Arguments: None
  749. //
  750. // Returns: Nothing
  751. //
  752. //-----------------------------------------------------------------------------
  753. NTSTATUS
  754. DfsSendUpdate(
  755. LPWSTR ServerName,
  756. ULONG SiteCount,
  757. PDFS_SITENAME_INFO pSites)
  758. {
  759. ULONG size;
  760. DWORD dwErr;
  761. ULONG i;
  762. PDFS_CREATE_SITE_INFO_ARG arg;
  763. WCHAR *wCp;
  764. size = FIELD_OFFSET(DFS_CREATE_SITE_INFO_ARG,SiteName[SiteCount]) +
  765. wcslen(ServerName) * sizeof(WCHAR);
  766. for (i = 0; i < SiteCount; i++) {
  767. size += wcslen(pSites[i].SiteName) * sizeof(WCHAR);
  768. }
  769. arg = (PDFS_CREATE_SITE_INFO_ARG) new CHAR [size];
  770. if (arg == NULL) {
  771. return ERROR_OUTOFMEMORY;
  772. }
  773. wCp = (WCHAR *)(&arg->SiteName[SiteCount]);
  774. arg->ServerName.Buffer = wCp;
  775. wCp += wcslen(ServerName);
  776. arg->ServerName.Length = wcslen(ServerName) * sizeof(WCHAR);
  777. arg->ServerName.MaximumLength = arg->ServerName.Length;
  778. RtlCopyMemory(arg->ServerName.Buffer, ServerName, arg->ServerName.Length);
  779. LPWSTR_TO_OFFSET(arg->ServerName.Buffer,arg);
  780. arg->SiteCount = SiteCount;
  781. for (i = 0; i < SiteCount; i++) {
  782. arg->SiteName[i].Buffer = wCp;
  783. wCp += wcslen(pSites[i].SiteName);
  784. arg->SiteName[i].Length = wcslen(pSites[i].SiteName) * sizeof(WCHAR);
  785. arg->SiteName[i].MaximumLength = arg->SiteName[i].Length;
  786. RtlCopyMemory(arg->SiteName[i].Buffer, pSites[i].SiteName, arg->SiteName[i].Length);
  787. LPWSTR_TO_OFFSET(arg->SiteName[i].Buffer,arg);
  788. }
  789. dwErr = DfsCreateSiteEntry((PCHAR)arg, size);
  790. delete [] arg;
  791. return dwErr;
  792. }