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.

1628 lines
45 KiB

  1. //+----------------------------------------------------------------------------//+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992-1995, Microsoft Corporation
  4. //
  5. // File: service.cxx
  6. //
  7. // Contents: A Class for abstracting the concept of a Service/Replica on
  8. // each volume in the namespace.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 26-Jan-93 SudK Created
  15. // 12-May-93 SudK Modified
  16. // 28-Mar-95 Milans Updated to handle server
  17. // knowledge inconsistencies
  18. // 27-Dec-95 Milans Updated for NT/SUR
  19. //
  20. //--------------------------------------------------------------------------
  21. //#include <ntos.h>
  22. //#include <ntrtl.h>
  23. //#include <nturtl.h>
  24. //#include <dfsfsctl.h>
  25. //#include <windows.h>
  26. #include "headers.hxx"
  27. #pragma hdrstop
  28. extern "C" {
  29. #include <dfserr.h>
  30. #include <dfspriv.h> // For I_NetDfsXXX calls
  31. #include "dfsmsrv.h"
  32. }
  33. #include "service.hxx"
  34. #include "cdfsvol.hxx"
  35. #include "jnpt.hxx"
  36. #include "dfsmwml.h"
  37. INIT_DFS_REPLICA_INFO_MARSHAL_INFO()
  38. DWORD
  39. RelationInfoToNetInfo(
  40. PDFS_PKT_RELATION_INFO RelationInfo,
  41. LPNET_DFS_ENTRY_ID_CONTAINER pNetInfo);
  42. NTSTATUS
  43. DfspCreateExitPoint (
  44. IN HANDLE DriverHandle,
  45. IN LPGUID Uid,
  46. IN LPWSTR Prefix,
  47. IN ULONG Type,
  48. IN ULONG ShortPrefixLen,
  49. OUT LPWSTR ShortPrefix);
  50. NTSTATUS
  51. DfspDeleteExitPoint (
  52. IN HANDLE DriverHandle,
  53. IN LPGUID Uid,
  54. IN LPWSTR Prefix,
  55. IN ULONG Type);
  56. //+------------------------------------------------------------------------
  57. //
  58. // Member: CDfsService::CDfsService, private
  59. //
  60. // Synopsis: This is private constructor with no arguments.
  61. //
  62. // Arguments: None.
  63. //
  64. // Returns: Nothing.
  65. //
  66. // Notes: This constructor should be followed up by some kind of
  67. // deserialization to setup the instance appropriately.
  68. //
  69. //-------------------------------------------------------------------------
  70. CDfsService::CDfsService( void )
  71. {
  72. IDfsVolInlineDebOut((
  73. DEB_TRACE, "CDfsService::+CDfsService(1)(0x%x)\n",
  74. this));
  75. //
  76. // Initialise all the private section appropriately.
  77. //
  78. memset(&_DfsReplicaInfo, 0, sizeof(DFS_REPLICA_INFO));
  79. memset(&_DfsPktService, 0, sizeof(DFS_SERVICE));
  80. memset(&_ftModification, 0, sizeof(FILETIME));
  81. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::CDfsService(1)() exit\n"));
  82. }
  83. //+------------------------------------------------------------------------
  84. //
  85. // Member: CDfsService::CDfsService
  86. //
  87. // Synopsis: This is the primary way of constructing a CDfsService instance
  88. // using a DFS_REPLICA_INFO structure. The DFS_REPLICA_INFO struct
  89. // passed in has to be freed by the caller. This constructor does
  90. // not eat up that memory.
  91. //
  92. // Arguments: [pReplicaInfo] -- The ReplicaInfo struct that defines this Svc.
  93. // [bCreatePktSvc] -- Whether to create PKT Service struct in
  94. // private section.
  95. // [pdwErr] -- On return, indicates result of construction.
  96. //
  97. // Returns: *pdwErr will be set to ERROR_OUTOFMEMORY if memory allocation fails.
  98. //
  99. // Notes: This constructor allocates required memory and then copies.
  100. //
  101. //-------------------------------------------------------------------------
  102. CDfsService::CDfsService(
  103. PDFS_REPLICA_INFO pReplicaInfo,
  104. BOOLEAN bCreatePktSvc,
  105. DWORD *pdwErr
  106. )
  107. {
  108. DWORD dwErr = ERROR_SUCCESS;
  109. ULONG size;
  110. LPBYTE buffer;
  111. IDfsVolInlineDebOut((
  112. DEB_TRACE, "CDfsService::+CDfsService(2)(0x%x)\n",
  113. this));
  114. #if DBG
  115. if (DfsSvcVerbose)
  116. DbgPrint("CDfsService::CDfsService(%ws,%ws,%ws)\n",
  117. pReplicaInfo->pwszServerName,
  118. pReplicaInfo->pwszShareName,
  119. bCreatePktSvc == TRUE ? L"TRUE" : L"FALSE");
  120. #endif
  121. //
  122. // First initialise the ServiceEntry structure.
  123. //
  124. ZeroMemory(&_DfsReplicaInfo, sizeof(DFS_REPLICA_INFO));
  125. ZeroMemory(&_DfsPktService, sizeof(DFS_SERVICE));
  126. ZeroMemory(&_ftModification, sizeof(FILETIME));
  127. //
  128. // We first need to initialise the ReplicaInfo structure in the private
  129. // section. The simplest way to do this is to serialize what we got and
  130. // then Deserialize the same thing.
  131. //
  132. _DfsReplicaInfo = *pReplicaInfo; // Temporarily
  133. size = GetMarshalSize();
  134. buffer = new BYTE[size];
  135. if (buffer != NULL) {
  136. Serialize(buffer, size);
  137. //
  138. // Now we unmarshall this buffer again to get a new ReplicaInfo
  139. // structure.
  140. //
  141. DeSerialize(buffer, size);
  142. delete [] buffer;
  143. } else {
  144. ZeroMemory( &_DfsReplicaInfo, sizeof(DFS_REPLICA_INFO));
  145. dwErr = ERROR_OUTOFMEMORY;
  146. }
  147. //
  148. // Now that we have initialised the DfsReplicaInfo structure in the
  149. // private section, we need to initialize the DFS_SERVICE structure
  150. // as well.
  151. //
  152. if (dwErr == ERROR_SUCCESS && bCreatePktSvc)
  153. dwErr = InitializePktSvc();
  154. *pdwErr = dwErr;
  155. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::CDfsService(2)() exit\n"));
  156. #if DBG
  157. if (DfsSvcVerbose)
  158. DbgPrint("CDfsService::CDfsService exit %d\n", dwErr);
  159. #endif
  160. }
  161. //+------------------------------------------------------------------------
  162. //
  163. // Member: CDfsService::~CDfsService
  164. //
  165. // Synopsis: The Destructor. Gets rid of all the memory.
  166. //
  167. // Arguments: None
  168. //
  169. // Returns: Nothing.
  170. //
  171. // Notes: This assumes that the constructor used "new" to allocate
  172. // memory for the strings in the private structure.
  173. //
  174. //-------------------------------------------------------------------------
  175. CDfsService::~CDfsService(void)
  176. {
  177. ULONG i;
  178. PDS_MACHINE pMachine;
  179. IDfsVolInlineDebOut((
  180. DEB_TRACE, "CDfsService::~CDfsService(0x%x)\n",
  181. this));
  182. //
  183. // Need to get rid of memory in DFS_SERVICE and DfsReplicaInfo structs.
  184. //
  185. if (_DfsReplicaInfo.pwszServerName != pwszComputerName) {
  186. MarshalBufferFree( _DfsReplicaInfo.pwszServerName );
  187. }
  188. MarshalBufferFree( _DfsReplicaInfo.pwszShareName );
  189. if (_DfsPktService.pMachEntry != NULL) {
  190. pMachine = _DfsPktService.pMachEntry->pMachine;
  191. if (pMachine != NULL)
  192. DfsMachineFree(pMachine); // Free using appropriate mechanism
  193. delete _DfsPktService.pMachEntry;
  194. }
  195. if (_DfsPktService.Name.Buffer != NULL) {
  196. delete [] _DfsPktService.Name.Buffer;
  197. }
  198. if (_DfsPktService.Address.Buffer != NULL) {
  199. delete [] _DfsPktService.Address.Buffer;
  200. }
  201. if (_DfsPktService.StgId.Buffer != NULL) {
  202. delete [] _DfsPktService.StgId.Buffer;
  203. }
  204. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::~CDfsService() exit\n"));
  205. }
  206. //+------------------------------------------------------------------------
  207. //
  208. // Member: CDfsService::InitializePktSvc
  209. //
  210. // Synopsis: This is the method that initialises the DFS_SERVICE structure
  211. // in the private section of Class. The DFS_REPLICA_INFO
  212. // structure should have been setup by the time this routine is
  213. // called.
  214. //
  215. // Arguments: None
  216. //
  217. // Returns: [ERROR_SUCCESS] -- If everything went ok.
  218. //
  219. // [ERROR_OUTOFMEMORY] -- If unable to allocate requisite memory.
  220. //
  221. // History: 26-Jan-1993 Sudk Created.
  222. // 13-May-93 Sudk Modified for new interface.
  223. //
  224. //-------------------------------------------------------------------------
  225. DWORD
  226. CDfsService::InitializePktSvc()
  227. {
  228. DWORD dwErr = ERROR_SUCCESS;
  229. UNICODE_STRING ustr;
  230. //
  231. // We just put in a switch for Each ReplicaType that we will handle.
  232. //
  233. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::InitializePktSvc()\n"));
  234. switch(_DfsReplicaInfo.ulReplicaType) {
  235. case DFS_STORAGE_TYPE_DFS:
  236. _DfsPktService.ProviderId = PROV_ID_DFS_RDR;
  237. _DfsPktService.Capability = PROV_DFS_RDR;
  238. _DfsPktService.Type = DFS_SERVICE_TYPE_MASTER;
  239. _DfsPktService.Cost = (ULONG) ~0L;
  240. break;
  241. case DFS_STORAGE_TYPE_NONDFS:
  242. _DfsPktService.ProviderId = PROV_ID_LM_RDR;
  243. _DfsPktService.Capability = PROV_STRIP_PREFIX;
  244. _DfsPktService.Type = DFS_SERVICE_TYPE_DOWN_LEVEL | DFS_SERVICE_TYPE_MASTER;
  245. _DfsPktService.Cost = (ULONG) ~0L;
  246. break;
  247. default:
  248. ASSERT( FALSE && "Invalid Replica Type");
  249. break;
  250. }
  251. if (_DfsReplicaInfo.ulReplicaState & DFS_STORAGE_STATE_OFFLINE)
  252. _DfsPktService.Type |= DFS_SERVICE_TYPE_OFFLINE;
  253. //
  254. // Now, we construct the DS_MACHINE
  255. //
  256. _DfsPktService.pMachEntry = (PDFS_MACHINE_ENTRY) new DFS_MACHINE_ENTRY;
  257. if (_DfsPktService.pMachEntry == NULL) {
  258. return( ERROR_OUTOFMEMORY );
  259. } else {
  260. ZeroMemory(
  261. (PVOID) _DfsPktService.pMachEntry,
  262. sizeof( DFS_MACHINE_ENTRY ) );
  263. }
  264. dwErr = DfsGetDSMachine(
  265. _DfsReplicaInfo.pwszServerName,
  266. &_DfsPktService.pMachEntry->pMachine);
  267. if (dwErr != ERROR_SUCCESS) {
  268. delete _DfsPktService.pMachEntry;
  269. _DfsPktService.pMachEntry = NULL;
  270. IDfsVolInlineDebOut((DEB_ERROR, "Unable to get to %ws machine \n",
  271. _DfsReplicaInfo.pwszServerName));
  272. return( ERROR_OUTOFMEMORY );
  273. }
  274. ustr.Length = (USHORT)wcslen(_DfsReplicaInfo.pwszServerName);
  275. ustr.Buffer = new WCHAR [ustr.Length + 1];
  276. ustr.Length *= sizeof(WCHAR);
  277. ustr.MaximumLength = ustr.Length + sizeof(WCHAR);
  278. if (ustr.Buffer != NULL) {
  279. wcscpy(ustr.Buffer, _DfsReplicaInfo.pwszServerName);
  280. _DfsPktService.Name = ustr;
  281. } else {
  282. delete _DfsPktService.pMachEntry;
  283. _DfsPktService.pMachEntry = NULL;
  284. return( ERROR_OUTOFMEMORY );
  285. }
  286. ustr.Length = (1 + wcslen(_DfsReplicaInfo.pwszServerName) +
  287. 1 + wcslen(_DfsReplicaInfo.pwszShareName));
  288. ustr.Buffer = new WCHAR [ustr.Length + 1];
  289. ustr.Length *= sizeof(WCHAR);
  290. ustr.MaximumLength = ustr.Length + sizeof(WCHAR);
  291. if (ustr.Buffer != NULL) {
  292. wcscpy(ustr.Buffer, UNICODE_PATH_SEP_STR);
  293. wcscat(ustr.Buffer, _DfsReplicaInfo.pwszServerName);
  294. wcscat(ustr.Buffer, UNICODE_PATH_SEP_STR);
  295. wcscat(ustr.Buffer, _DfsReplicaInfo.pwszShareName);
  296. _DfsPktService.Address = ustr;
  297. } else {
  298. delete [] _DfsPktService.Name.Buffer;
  299. _DfsPktService.Name.Buffer = NULL;
  300. _DfsPktService.Name.Length = _DfsPktService.Name.MaximumLength = 0;
  301. delete _DfsPktService.pMachEntry;
  302. _DfsPktService.pMachEntry = NULL;
  303. return( ERROR_OUTOFMEMORY );
  304. }
  305. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::InitializePktSvc() exit\n"));
  306. return( ERROR_SUCCESS );
  307. }
  308. //+------------------------------------------------------------------------
  309. //
  310. // Member: CDfsService::DeSerialize, private
  311. //
  312. // Synopsis: This function takes a buffer as an argument and deserializes
  313. // its contents into the private DfsReplicaInfo structure.
  314. //
  315. // Arguments: [buffer] -- The buffer which has to be deserialized.
  316. // [size] -- The size of the buffer.
  317. //
  318. // Returns: Nothing.
  319. //
  320. //
  321. //
  322. // History: 13-May-93 SudK Created.
  323. //
  324. //-------------------------------------------------------------------------
  325. DWORD
  326. CDfsService::DeSerialize(BYTE *buffer, ULONG size)
  327. {
  328. ULONG ulReplicaType;
  329. MARSHAL_BUFFER marshalBuffer;
  330. NTSTATUS status;
  331. MarshalBufferInitialize(&marshalBuffer, size, buffer);
  332. status = DfsRtlGet(&marshalBuffer, &MiFileTime, &_ftModification);
  333. if (!NT_SUCCESS(status))
  334. return( ERROR_INVALID_PARAMETER );
  335. //
  336. // Now that we know which Minfo Struct to use and we also have the
  337. // buffer at hand. We can just do a simple Unmarshall to get the stuff
  338. // out of the buffer.
  339. //
  340. status = DfsRtlGet(&marshalBuffer, &MiDfsReplicaInfo, &_DfsReplicaInfo);
  341. if (ulDfsManagerType == DFS_MANAGER_SERVER) {
  342. //
  343. // To handle machine renames, we store the local computer name as a
  344. // L"." Replace this with the current computer name, if necessary.
  345. //
  346. if (NT_SUCCESS(status) && pwszComputerName != NULL) {
  347. if (wcscmp(_DfsReplicaInfo.pwszServerName, L".") == 0) {
  348. MarshalBufferFree(_DfsReplicaInfo.pwszServerName);
  349. _DfsReplicaInfo.pwszServerName = pwszComputerName;
  350. }
  351. }
  352. }
  353. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  354. return( ERROR_OUTOFMEMORY );
  355. } else if (!NT_SUCCESS(status)) {
  356. return( ERROR_INVALID_PARAMETER );
  357. }
  358. //
  359. // Now that we have deserialized we are done.
  360. //
  361. return ERROR_SUCCESS;
  362. }
  363. //+------------------------------------------------------------------------
  364. //
  365. // Member: CDfsService::DeSerialize, public
  366. //
  367. // Synopsis: This function takes a buffer as an argument and deserializes
  368. // its contents and creates an instance of this class and
  369. // returns a pointer to it.
  370. //
  371. // Arguments: [buffer] -- The buffer which has to be deserialized.
  372. // [size] -- The size of the buffer.
  373. // [ppService] - The new instance is returned here.
  374. //
  375. // Returns: ERROR_SUCCESS -- If all went well.
  376. //
  377. // Notes: This method will not throw any exceptions.
  378. //
  379. // History: 13-May-93 SudK Created.
  380. //
  381. //-------------------------------------------------------------------------
  382. DWORD
  383. CDfsService::DeSerialize(
  384. PBYTE buffer,
  385. ULONG size,
  386. CDfsService **ppService)
  387. {
  388. DWORD dwErr = ERROR_SUCCESS;
  389. *ppService = NULL;
  390. //
  391. // Construct a NULL CDfsService first and then unmarshall the stuff.
  392. //
  393. *ppService = new CDfsService;
  394. if (*ppService == NULL) {
  395. return(ERROR_OUTOFMEMORY);
  396. }
  397. dwErr = (*ppService)->DeSerialize(buffer, size);
  398. //
  399. // Now the ReplicaInfo struct in the private section has been setup
  400. // appropriately. What is left is to setup the DFS_SERVICE struct
  401. // as well and then we have a properly constructed CDfsService.
  402. //
  403. if (dwErr == ERROR_SUCCESS) {
  404. dwErr = (*ppService)->InitializePktSvc();
  405. }
  406. if (dwErr != ERROR_SUCCESS) {
  407. delete *ppService;
  408. *ppService = NULL;
  409. }
  410. return( dwErr );
  411. }
  412. //+------------------------------------------------------------------------
  413. //
  414. // Member: CDfsService::Serialize, public
  415. //
  416. // Synopsis: This function takes a buffer as an argument and serializes
  417. // the private DfsReplicaInfo structure into that buffer.
  418. //
  419. // Arguments: [buffer] -- ReplInfo struct to be serialised into this.
  420. // [size] -- The size of the buffer.
  421. //
  422. // Returns: Nothing.
  423. //
  424. // Notes: Will ASSERT if the buffer is not big enough. The
  425. // size of the buffer should have been calculated using
  426. // the function GetMarshalSize() in this class.
  427. //
  428. // The ServiceInfo MUST BE MARSHALLED FIRST!. This is because
  429. // the Deserialize routine does a _GetUlong to figure out what
  430. // kind of ServiceInfo was marshalled.
  431. //
  432. // History: 13-May-93 SudK Created.
  433. //
  434. //-------------------------------------------------------------------------
  435. VOID
  436. CDfsService::Serialize(PBYTE buffer, ULONG size)
  437. {
  438. MARSHAL_BUFFER marshalBuffer;
  439. NTSTATUS status;
  440. DFS_REPLICA_INFO dfsReplicaInfo;
  441. ASSERT( size >= GetMarshalSize() );
  442. //
  443. // Now that we have a proper buffer lets go marshall the stuff in.
  444. //
  445. MarshalBufferInitialize(&marshalBuffer, size, buffer);
  446. status = DfsRtlPut(&marshalBuffer, &MiFileTime, &_ftModification);
  447. ASSERT(NT_SUCCESS(status));
  448. dfsReplicaInfo = _DfsReplicaInfo;
  449. if (ulDfsManagerType == DFS_MANAGER_SERVER && pwszComputerName != NULL) {
  450. if (_wcsicmp(dfsReplicaInfo.pwszServerName, pwszComputerName) == 0)
  451. dfsReplicaInfo.pwszServerName = L".";
  452. }
  453. status = DfsRtlPut(&marshalBuffer, &MiDfsReplicaInfo, &dfsReplicaInfo);
  454. ASSERT(NT_SUCCESS(status));
  455. }
  456. //+----------------------------------------------------------------------------
  457. //
  458. // Function: CDfsService::GetNetStorageInfo, public
  459. //
  460. // Synopsis: Returns the service info in a DFS_STORAGE_INFO struct.
  461. // Useful for NetDfsXXX APIs.
  462. //
  463. // Arguments: [pInfo] -- Pointer to DFS_STORAGE_INFO to fill. Pointer
  464. // members will be allocated using MIDL_user_allocate.
  465. //
  466. // [pcbInfo] -- On successful return, set to size in bytes of
  467. // returned info. The size does not include the size
  468. // of the DFS_STORAGE_INFO struct itself.
  469. //
  470. // Returns:
  471. //
  472. //-----------------------------------------------------------------------------
  473. DWORD
  474. CDfsService::GetNetStorageInfo(
  475. LPDFS_STORAGE_INFO pInfo,
  476. LPDWORD pcbInfo)
  477. {
  478. DWORD dwErr = ERROR_SUCCESS;
  479. LPWSTR wszShare;
  480. DWORD cbInfo = 0, cbItem;
  481. pInfo->State = _DfsReplicaInfo.ulReplicaState;
  482. cbItem = (wcslen(_DfsReplicaInfo.pwszServerName) + 1) * sizeof(WCHAR);
  483. pInfo->ServerName = (LPWSTR) MIDL_user_allocate(cbItem);
  484. if (pInfo->ServerName != NULL) {
  485. wcscpy(pInfo->ServerName, _DfsReplicaInfo.pwszServerName);
  486. cbInfo += cbItem;
  487. } else {
  488. dwErr = ERROR_OUTOFMEMORY;
  489. }
  490. if (dwErr == ERROR_SUCCESS) {
  491. cbItem = (wcslen(_DfsReplicaInfo.pwszShareName) + 1) * sizeof(WCHAR);
  492. pInfo->ShareName = (LPWSTR) MIDL_user_allocate(cbItem);
  493. if (pInfo->ShareName != NULL) {
  494. wcscpy( pInfo->ShareName, _DfsReplicaInfo.pwszShareName );
  495. cbInfo += cbItem;
  496. } else {
  497. MIDL_user_free( pInfo->ServerName );
  498. pInfo->ServerName = NULL;
  499. dwErr = ERROR_OUTOFMEMORY;
  500. }
  501. }
  502. *pcbInfo = cbInfo;
  503. return( dwErr );
  504. }
  505. //+------------------------------------------------------------------------
  506. //
  507. // Member: CDfsService::IsEqual, public
  508. //
  509. // Synopsis: This function takes a replicaInfo structure and compares it
  510. // for equality with itself. After all a ReplicaInfo structure
  511. // uniquely identifies a service.
  512. //
  513. // Arguments: [pReplicaInfo] -- A replicaInfo struct.
  514. //
  515. // Returns: TRUE if it is equal else FALSE.
  516. //
  517. // Notes: Can throw an exception due to bad structures etc.
  518. //
  519. // History: 13-May-93 SudK Created.
  520. //
  521. //-------------------------------------------------------------------------
  522. BOOLEAN
  523. CDfsService::IsEqual(PDFS_REPLICA_INFO pReplicaInfo)
  524. {
  525. if (_wcsicmp(pReplicaInfo->pwszServerName, _DfsReplicaInfo.pwszServerName)) {
  526. return(FALSE);
  527. }
  528. if (_wcsicmp(pReplicaInfo->pwszShareName, _DfsReplicaInfo.pwszShareName)) {
  529. return(FALSE);
  530. }
  531. return(TRUE);
  532. }
  533. //+------------------------------------------------------------------------
  534. //
  535. // Method: CDfsService::CreateExitPoint, public
  536. //
  537. // Synopsis: This method creates an exit point at the remote machine.
  538. //
  539. // Arguments: [peid] -- The Pkt Entry ID of the exit point.
  540. //
  541. // [Type] -- The type of volume where we are.
  542. //
  543. // Returns: [ERROR_SUCCESS] -- If all went well.
  544. //
  545. // [NERR_DfsServerUpgraded] -- A non-dfs replica has since been
  546. // made Dfs aware.
  547. //
  548. // [NERR_DfsServerNotDfsAware] -- Server is non-dfs or
  549. // replica is unavailable at this time.
  550. //
  551. // History: 01 Feb 93 SudK Created.
  552. //
  553. //-------------------------------------------------------------------------
  554. DWORD
  555. CDfsService::CreateExitPoint(
  556. PDFS_PKT_ENTRY_ID peid,
  557. ULONG Type)
  558. {
  559. DWORD dwErr = ERROR_SUCCESS;
  560. NET_API_STATUS netStatus;
  561. ULONG dwVersion;
  562. BOOL fRetry;
  563. HANDLE pktHandle = NULL;
  564. NTSTATUS status = STATUS_SUCCESS;
  565. //
  566. // If this is marked as a non-dfs aware replica, try and see if the
  567. // replica has been made Dfs aware. If so, we return a distinguished
  568. // error code so the caller can turn around, do a create local partition
  569. // and retry the CreateExitPoint.
  570. //
  571. if (_DfsReplicaInfo.ulReplicaType == DFS_STORAGE_TYPE_NONDFS) {
  572. //
  573. // At the time this server was added as a replica for this volume,
  574. // this server was was either unavailable or not dfs aware. So,
  575. // try and see if the server is now Dfs Aware or not.
  576. //
  577. netStatus = I_NetDfsGetVersion(
  578. _DfsReplicaInfo.pwszServerName,
  579. &dwVersion);
  580. DFSM_TRACE_ERROR_HIGH(netStatus, ALL_ERROR, CDfsServiceCreateExitPoint_Error_I_NetDfsGetVersion,
  581. LOGSTATUS(netStatus));
  582. if (netStatus == NERR_Success) {
  583. return( NERR_DfsServerUpgraded );
  584. } else {
  585. return( NERR_DfsServerNotDfsAware );
  586. }
  587. }
  588. ASSERT (_DfsReplicaInfo.ulReplicaType != DFS_STORAGE_TYPE_NONDFS);
  589. status = PktOpen(&pktHandle, 0, 0, NULL);
  590. if (!NT_SUCCESS(status)) {
  591. dwErr = RtlNtStatusToDosError(status);
  592. return dwErr;
  593. }
  594. fRetry = FALSE;
  595. do {
  596. netStatus = (NET_API_STATUS)DfspCreateExitPoint(
  597. pktHandle,
  598. &peid->Uid,
  599. peid->Prefix.Buffer,
  600. Type,
  601. peid->ShortPrefix.MaximumLength/sizeof(WCHAR),
  602. peid->ShortPrefix.Buffer);
  603. if (netStatus == STATUS_SUCCESS)
  604. peid->ShortPrefix.Length =
  605. wcslen(peid->ShortPrefix.Buffer) * sizeof(WCHAR);
  606. if (fRetry) {
  607. //
  608. // We have already tried once to sync up the server. Time to quit
  609. //
  610. fRetry = FALSE;
  611. } else if (netStatus == DFS_STATUS_NOSUCH_LOCAL_VOLUME ||
  612. netStatus == DFS_STATUS_LOCAL_ENTRY ||
  613. netStatus == DFS_STATUS_BAD_EXIT_POINT) {
  614. fRetry = SyncKnowledge();
  615. }
  616. } while ( fRetry );
  617. if (pktHandle != NULL)
  618. PktClose(pktHandle);
  619. if (netStatus != NERR_Success)
  620. dwErr = RtlNtStatusToDosError(netStatus);
  621. if (dwErr != ERROR_SUCCESS) {
  622. IDfsVolInlineDebOut((
  623. DEB_TRACE, "Failed to do CreateExitPt %ws at %ws. Error: %x\n",
  624. peid->Prefix.Buffer, _DfsReplicaInfo.pwszServerName, dwErr));
  625. }
  626. return( dwErr );
  627. }
  628. //+------------------------------------------------------------------------
  629. //
  630. // Method: CDfsService::DeleteExitPoint()
  631. //
  632. // Synopsis: This method deletes an exit point at the remote machine.
  633. //
  634. // Arguments: [peid] -- ExitPath to be deleted along with GUID in the
  635. // EntryId struct.
  636. // [Type] -- The type of volume where we are.
  637. //
  638. // Returns: [ERROR_SUCCESS] -- If successfully deleted exit point, or exit point
  639. // did not exist to begin with.
  640. //
  641. // Rpc error from I_NetDfsDeleteExitPoint
  642. //
  643. // Notes:
  644. //
  645. // History: 01 Feb 93 SudK Created.
  646. //
  647. //-------------------------------------------------------------------------
  648. DWORD
  649. CDfsService::DeleteExitPoint(
  650. PDFS_PKT_ENTRY_ID peid,
  651. ULONG Type)
  652. {
  653. DWORD dwErr = ERROR_SUCCESS;
  654. NTSTATUS status = STATUS_SUCCESS;
  655. BOOL fRetry;
  656. HANDLE pktHandle = NULL;
  657. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService:DeleteExitPoint()\n"));
  658. // ASSERT (_DfsReplicaInfo.ulReplicaType != DFS_STORAGE_TYPE_NONDFS);
  659. status = PktOpen(&pktHandle, 0, 0, NULL);
  660. fRetry = FALSE;
  661. do {
  662. status = DfspDeleteExitPoint(
  663. pktHandle,
  664. &peid->Uid,
  665. peid->Prefix.Buffer,
  666. Type);
  667. if (fRetry) {
  668. //
  669. // We have already tried once to sync up the server. Time to quit
  670. //
  671. fRetry = FALSE;
  672. } else if (status == DFS_STATUS_BAD_EXIT_POINT ||
  673. status == DFS_STATUS_NOSUCH_LOCAL_VOLUME) {
  674. //
  675. // The server is out of sync with the DC. Lets try to force it
  676. // into a valid state
  677. //
  678. fRetry = SyncKnowledge();
  679. }
  680. } while ( fRetry );
  681. if (pktHandle != NULL)
  682. PktClose(pktHandle);
  683. if (!NT_SUCCESS(status))
  684. dwErr = RtlNtStatusToDosError(status);
  685. if (dwErr != ERROR_SUCCESS) {
  686. IDfsVolInlineDebOut((
  687. DEB_TRACE, "Failed to do DeleteExitPt %ws at %ws. Error: %x\n",
  688. peid->Prefix.Buffer, _DfsReplicaInfo.pwszServerName, status ));
  689. }
  690. if (status == DFS_E_BAD_EXIT_POINT)
  691. dwErr = ERROR_SUCCESS;
  692. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService:DeleteExitPoint() exit\n"));
  693. return( dwErr );
  694. }
  695. //+------------------------------------------------------------------------
  696. //
  697. // Method: CDfsService::CreateLocalVolume()
  698. //
  699. // Synopsis: This method creates knowledge regarding a new volume at the
  700. // remote server.
  701. //
  702. // Arguments: [peid] -- The EntryId. This class does not know this.
  703. // [EntryType] -- Type of Entry. This class doesn't know this.
  704. //
  705. // Returns: [ERROR_SUCCESS] -- Successfully created local volume knowledge on
  706. // server.
  707. //
  708. // History: 01 Feb 93 SudK Created.
  709. //
  710. //-------------------------------------------------------------------------
  711. DWORD
  712. CDfsService::CreateLocalVolume(
  713. PDFS_PKT_ENTRY_ID peid,
  714. ULONG EntryType)
  715. {
  716. DFS_PKT_RELATION_INFO RelationInfo;
  717. NET_DFS_ENTRY_ID_CONTAINER NetRelationInfo;
  718. DWORD dwErr = ERROR_SUCCESS;
  719. NTSTATUS status;
  720. //
  721. // First to check whether this is necessary since this could be a down
  722. // level scenario.
  723. //
  724. if (_DfsReplicaInfo.ulReplicaType == DFS_STORAGE_TYPE_NONDFS) {
  725. return(ERROR_SUCCESS);
  726. }
  727. //
  728. // Now we need to create a config info structure. We will have to go to
  729. // the PKT for this since this is not available in the Private section
  730. // above.
  731. //
  732. dwErr = GetPktCacheRelationInfo(peid, &RelationInfo);
  733. if (dwErr != ERROR_SUCCESS) {
  734. IDfsVolInlineDebOut((
  735. DEB_ERROR,"Failed to do GetPktCacheRelationInfo on %ws %08lx\n",
  736. peid->Prefix.Buffer, dwErr));
  737. return( dwErr );
  738. }
  739. //
  740. // Convert the ConfigInfo into an LPNET_DFS_ENTRY_ID_CONTAINER suitable
  741. // for calling I_NetDfsCreateLocalPartition.
  742. //
  743. dwErr = RelationInfoToNetInfo( &RelationInfo, &NetRelationInfo );
  744. if (dwErr != ERROR_SUCCESS) {
  745. IDfsVolInlineDebOut((
  746. DEB_ERROR,
  747. "Failed to allocate memory for NET_ENTRY_ID_CONTAINER"));
  748. return( dwErr );
  749. }
  750. BOOL fRetry;
  751. fRetry = FALSE;
  752. //
  753. // Note that I_NetDfsCreateLocalPartition returns an NT_STATUS cast to a
  754. // NET_API_STATUS
  755. //
  756. do {
  757. status = I_NetDfsCreateLocalPartition(
  758. _DfsReplicaInfo.pwszServerName,
  759. _DfsReplicaInfo.pwszShareName,
  760. &peid->Uid,
  761. peid->Prefix.Buffer,
  762. peid->ShortPrefix.Buffer,
  763. &NetRelationInfo,
  764. FALSE);
  765. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, CDfsServiceCreateLocalVolume_I_NetDfsCreateLocalPartition,
  766. LOGSTATUS(status));
  767. //
  768. // If this operation fails, it could reflect a knowledge inconsistency at
  769. // the server. So, handle it now.
  770. //
  771. IDfsVolInlineDebOut((
  772. DEB_TRACE, "I_NetDfsCreateLocalPartition returned %08lx\n",
  773. status));
  774. if (fRetry) {
  775. //
  776. // We have already tried once to sync up the server. Time to quit
  777. //
  778. fRetry = FALSE;
  779. } else if (status == DFS_STATUS_LOCAL_ENTRY) {
  780. //
  781. // The server thinks that the volume we are trying to create
  782. // already exists. This is bogus, so lets try to bring the server
  783. // up to sync with us.
  784. //
  785. fRetry = SyncKnowledge();
  786. }
  787. } while ( fRetry );
  788. if (!NT_SUCCESS(status)) {
  789. dwErr = RtlNtStatusToDosError(status);
  790. }
  791. DeallocateCacheRelationInfo(RelationInfo);
  792. delete [] NetRelationInfo.Buffer;
  793. if (dwErr != ERROR_SUCCESS) {
  794. IDfsVolInlineDebOut((
  795. DEB_TRACE,
  796. "Failed to CreateLocalVol at %ws for %ws. Error: %x\n",
  797. _DfsReplicaInfo.pwszServerName, peid->Prefix.Buffer, dwErr));
  798. }
  799. return( dwErr );
  800. }
  801. //+------------------------------------------------------------------------
  802. //
  803. // Method: CDfsService::DeleteLocalVolume()
  804. //
  805. // Synopsis: This method deletes knowledge regarding a volume at remote
  806. // machine.
  807. //
  808. // Arguments: [peid] -- EntryId information.
  809. //
  810. // Returns: [ERROR_SUCCESS] -- If successfully deleted the knowledge at the remote
  811. // server, or the server didn't know about the volume
  812. // to begin with.
  813. //
  814. // History: 01 Feb 93 SudK Created.
  815. //
  816. //-------------------------------------------------------------------------
  817. DWORD
  818. CDfsService::DeleteLocalVolume(
  819. PDFS_PKT_ENTRY_ID peid)
  820. {
  821. NTSTATUS status;
  822. DWORD dwErr = ERROR_SUCCESS;
  823. BOOL fRetry;
  824. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::DeleteLocalVolume()\n"));
  825. //
  826. // First to check whether this is necessary since this could be a down
  827. // level scenario.
  828. //
  829. if (_DfsReplicaInfo.ulReplicaType == DFS_STORAGE_TYPE_NONDFS) {
  830. return(ERROR_SUCCESS);
  831. }
  832. fRetry = FALSE;
  833. //
  834. // Note that I_NetDfsCreateLocalPartition returns an NT_STATUS cast to a
  835. // NET_API_STATUS
  836. //
  837. do {
  838. status = I_NetDfsDeleteLocalPartition(
  839. _DfsReplicaInfo.pwszServerName,
  840. &peid->Uid,
  841. peid->Prefix.Buffer);
  842. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, CDfsServiceDeleteLocalVolume_Error_I_NetDfsDeleteLocalPartition,
  843. LOGSTATUS(status));
  844. IDfsVolInlineDebOut((
  845. DEB_TRACE, "NT Status %08lx from DfsDeleteLocalPartition\n",
  846. status));
  847. if (fRetry) {
  848. //
  849. // We have already tried once to sync up the server. Time to quit
  850. //
  851. fRetry = FALSE;
  852. } else if (status == DFS_STATUS_NOSUCH_LOCAL_VOLUME) {
  853. //
  854. // This could happen because the server's knowledge is
  855. // inconsistent with that of this DC. Try to bring it in sync.
  856. //
  857. fRetry = SyncKnowledge();
  858. }
  859. } while ( fRetry );
  860. if (!NT_SUCCESS(status)) {
  861. IDfsVolInlineDebOut((
  862. DEB_TRACE,
  863. "Failed to Delete Local Volume at %ws for %ws Error: %x\n",
  864. _DfsReplicaInfo.pwszServerName, peid->Prefix.Buffer, status));
  865. }
  866. if (status == DFS_STATUS_NOSUCH_LOCAL_VOLUME)
  867. dwErr = ERROR_SUCCESS;
  868. else if (!NT_SUCCESS(status))
  869. dwErr = RtlNtStatusToDosError(status);
  870. else
  871. dwErr = ERROR_SUCCESS;
  872. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::DeleteLocalVolume() exit\n"));
  873. return( dwErr );
  874. }
  875. //+----------------------------------------------------------------------------
  876. //
  877. // Function: CDfsService::SetVolumeState
  878. //
  879. // Synopsis: This method sets the Online/Offline state of the volume at
  880. // the remote machine.
  881. //
  882. // Arguments: [peid] -- The entry id of the volume.
  883. //
  884. // [fState] -- The state to set it at.
  885. //
  886. // [fRemoteOpMustSucceed] -- If TRUE, then the whole operation
  887. // fails if the remote server cannot be forced offline.
  888. // If FALSE, then the operation succeeds as long as the
  889. // local DC's PKT is updated.
  890. //
  891. // Returns: ERROR_SUCCESS -- The state of the volume was set as specified.
  892. //
  893. // Converted NTSTATUS from call to remote dfs.
  894. //
  895. //-----------------------------------------------------------------------------
  896. DWORD
  897. CDfsService::SetVolumeState(
  898. const PDFS_PKT_ENTRY_ID peid,
  899. const ULONG fState,
  900. const BOOL fRemoteOpMustSucceed)
  901. {
  902. NTSTATUS Status;
  903. DWORD dwErr = ERROR_SUCCESS;
  904. SYSTEMTIME st;
  905. //
  906. // We first inform the DC's Dfs driver to set the replica state.
  907. //
  908. Status = DfsSetServiceState( peid, GetServiceName(), fState );
  909. //
  910. // Save the changed state
  911. //
  912. if (NT_SUCCESS(Status)) {
  913. GetSystemTime( &st );
  914. SystemTimeToFileTime( &st, &_ftModification );
  915. if (fState == DFS_SERVICE_TYPE_OFFLINE) {
  916. _DfsReplicaInfo.ulReplicaState = DFS_STORAGE_STATE_OFFLINE;
  917. } else {
  918. _DfsReplicaInfo.ulReplicaState = DFS_STORAGE_STATE_ONLINE;
  919. }
  920. }
  921. //
  922. // Only in the case that this succeeded and the service in question is
  923. // a dfs aware replica do we tell the server to take the volume offline
  924. //
  925. if (NT_SUCCESS(Status)) {
  926. if (_DfsReplicaInfo.ulReplicaType == DFS_STORAGE_TYPE_DFS) {
  927. Status = I_NetDfsSetLocalVolumeState(
  928. _DfsReplicaInfo.pwszServerName,
  929. &peid->Uid,
  930. peid->Prefix.Buffer,
  931. fState);
  932. DFSM_TRACE_ERROR_HIGH(Status, ALL_ERROR, CDfsServiceSetVolumeState_Error_I_NetDfsSetLocalVolumeState,
  933. LOGSTATUS(Status));
  934. if (!fRemoteOpMustSucceed) {
  935. Status = STATUS_SUCCESS;
  936. }
  937. if (!NT_SUCCESS(Status)) {
  938. //
  939. // Try to undo the DC's PKT change
  940. //
  941. NTSTATUS statusRecover;
  942. statusRecover = DfsSetServiceState(
  943. peid,
  944. GetServiceName(),
  945. (_DfsReplicaInfo.ulReplicaState ==
  946. DFS_STORAGE_STATE_OFFLINE) ?
  947. DFS_STORAGE_STATE_ONLINE : 0);
  948. dwErr = RtlNtStatusToDosError(Status);
  949. }
  950. } else {
  951. //
  952. // Replica is not dfs-aware
  953. //
  954. NOTHING;
  955. }
  956. } else {
  957. dwErr = RtlNtStatusToDosError(Status);
  958. }
  959. return( dwErr );
  960. }
  961. //+------------------------------------------------------------------------
  962. //
  963. // Method: CDfsService::FixLocalVolume()
  964. //
  965. // Synopsis: This method creates knowledge regarding a new volume at remote
  966. // machine. This method merely packages the info from private
  967. // section of the class into a buffer and makes an FSCTRL to the
  968. // remote service. The rest happens at the remote service. This
  969. // method does not affect the local PKT at all. It updates the
  970. // remote service's PKT and the DFS.CFG file on disk and updates
  971. // the registry at the other end.This is a kind of FORCE operation.
  972. // At the remote server every attempt will be made to create this
  973. // local volume knowledge.
  974. //
  975. // Arguments: [peid] -- The EntryId. This class does not know this.
  976. // [EntryType] -- Type of Entry. This class doesn't know this.
  977. //
  978. // Returns: [ERROR_SUCCESS] -- If operation successfully completed.
  979. //
  980. // History: 18-June-93 SudK Created.
  981. //
  982. //-------------------------------------------------------------------------
  983. DWORD
  984. CDfsService::FixLocalVolume(
  985. PDFS_PKT_ENTRY_ID peid,
  986. ULONG EntryType)
  987. {
  988. DFS_PKT_RELATION_INFO RelationInfo;
  989. NET_DFS_ENTRY_ID_CONTAINER NetRelationInfo;
  990. DWORD dwErr = ERROR_SUCCESS;
  991. NTSTATUS status;
  992. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::FixLocalVolume()\n"));
  993. //
  994. // First to check whether this is necessary since this could be a down
  995. // level scenario.
  996. //
  997. if (_DfsReplicaInfo.ulReplicaType == DFS_STORAGE_TYPE_NONDFS) {
  998. return(ERROR_SUCCESS);
  999. }
  1000. //
  1001. // Now we need to create a relation info structure. We will have to go to
  1002. // the PKT for this since this is not available in the private section
  1003. //
  1004. dwErr = GetPktCacheRelationInfo(peid, &RelationInfo);
  1005. if (dwErr != ERROR_SUCCESS) {
  1006. IDfsVolInlineDebOut((
  1007. DEB_ERROR, "Failed to do GetPktCacheRelationInfo on %ws %08lx\n",
  1008. peid->Prefix.Buffer, dwErr));
  1009. return( dwErr );
  1010. }
  1011. //
  1012. // Now that we have the relationInfo. We know how to construct ConfigInfo.
  1013. //
  1014. RelationInfoToNetInfo( &RelationInfo, &NetRelationInfo );
  1015. if (dwErr != ERROR_SUCCESS) {
  1016. IDfsVolInlineDebOut((
  1017. DEB_ERROR,
  1018. "Failed to allocate memory for NET_ENTRY_ID_CONTAINER"));
  1019. return( dwErr );
  1020. }
  1021. //
  1022. // Now we are all setup to make the FSCTRL.
  1023. //
  1024. status = I_NetDfsFixLocalVolume(
  1025. _DfsReplicaInfo.pwszServerName,
  1026. _DfsReplicaInfo.pwszShareName,
  1027. EntryType,
  1028. _DfsPktService.Type,
  1029. NULL,
  1030. &peid->Uid,
  1031. peid->Prefix.Buffer,
  1032. &NetRelationInfo,
  1033. PKT_ENTRY_SUPERSEDE);
  1034. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, CDfsServiceFixLocalVolume_Error_I_NetDfsFixLocalVolume,
  1035. LOGSTATUS(status));
  1036. if (!NT_SUCCESS(status))
  1037. dwErr = RtlNtStatusToDosError(status);
  1038. DeallocateCacheRelationInfo(RelationInfo);
  1039. delete [] NetRelationInfo.Buffer;
  1040. if (dwErr != ERROR_SUCCESS) {
  1041. IDfsVolInlineDebOut((
  1042. DEB_TRACE, "Failed to FixLocalVolume at %ws for %ws. Error: %x\n",
  1043. _DfsReplicaInfo.pwszServerName, peid->Prefix.Buffer, dwErr));
  1044. }
  1045. IDfsVolInlineDebOut((DEB_TRACE, "CDfsService::FixLocalVolume() exit\n"));
  1046. return( dwErr );
  1047. }
  1048. //+------------------------------------------------------------------------
  1049. //
  1050. // Method: CDfsService::ModifyPrefix()
  1051. //
  1052. // Synopsis: This method takes the PKT_ENTRY_ID that it gets and advises
  1053. // the remote server of the new prefix for the volume ID.
  1054. //
  1055. // Arguments: [peid] -- NewEntry ID for this service.
  1056. //
  1057. // Returns: [ERROR_SUCCESS] -- If operation completed successfully.
  1058. //
  1059. // History: 31 April 93 SudK Created.
  1060. //
  1061. //-------------------------------------------------------------------------
  1062. DWORD
  1063. CDfsService::ModifyPrefix(
  1064. PDFS_PKT_ENTRY_ID peid)
  1065. {
  1066. DWORD dwErr = ERROR_SUCCESS;
  1067. NTSTATUS status;
  1068. BOOL fRetry;
  1069. //
  1070. // First to check whether this is necessary since this could be a down
  1071. // level scenario.
  1072. //
  1073. if (_DfsReplicaInfo.ulReplicaType == DFS_STORAGE_TYPE_NONDFS) {
  1074. return(ERROR_SUCCESS);
  1075. }
  1076. fRetry = FALSE;
  1077. do {
  1078. status = I_NetDfsModifyPrefix(
  1079. _DfsReplicaInfo.pwszServerName,
  1080. &peid->Uid,
  1081. peid->Prefix.Buffer);
  1082. DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, CDfsServiceModifyPrefix_Error_I_NetDfsModifyPrefix,
  1083. LOGSTATUS(status));
  1084. if (fRetry) {
  1085. //
  1086. // We have already tried once to sync up the server. Time to quit
  1087. //
  1088. fRetry = FALSE;
  1089. } else if (status == DFS_STATUS_NOSUCH_LOCAL_VOLUME ||
  1090. status == DFS_STATUS_BAD_EXIT_POINT) {
  1091. //
  1092. // The server seems to be out of sync with this DC. Try to
  1093. // force it to sync up
  1094. //
  1095. fRetry = SyncKnowledge();
  1096. }
  1097. } while ( fRetry );
  1098. if (!NT_SUCCESS(status))
  1099. dwErr = RtlNtStatusToDosError(status);
  1100. if (dwErr != ERROR_SUCCESS) {
  1101. IDfsVolInlineDebOut((
  1102. DEB_TRACE,
  1103. "Failed to do ModifyPrefix at [%ws] to [%ws]. Error: %x\n",
  1104. _DfsReplicaInfo.pwszServerName, peid->Prefix.Buffer, dwErr));
  1105. }
  1106. return( dwErr );
  1107. }
  1108. //+----------------------------------------------------------------------------
  1109. //
  1110. // Function: CDfsService::SyncKnowledge()
  1111. //
  1112. // Synopsis: Tries to force the server's knowledge to correspond with that
  1113. // on this DC.
  1114. //
  1115. // Arguments: None.
  1116. //
  1117. // Returns: TRUE if the server had to change any knowledge and was able
  1118. // to do so. FALSE if either nothing changed or the server was
  1119. // unable to comply.
  1120. //
  1121. //-----------------------------------------------------------------------------
  1122. BOOL CDfsService::SyncKnowledge()
  1123. {
  1124. NTSTATUS Status = STATUS_SUCCESS;
  1125. DFS_PKT_ENTRY_ID EntryId;
  1126. EntryId.Uid = _DfsPktService.pMachEntry->pMachine->guidMachine;
  1127. RtlInitUnicodeString(
  1128. &EntryId.Prefix,
  1129. _DfsReplicaInfo.pwszServerName );
  1130. // Status = DfsSetServerInfo( &EntryId, NULL );
  1131. if (!NT_SUCCESS(Status)) {
  1132. LogMessage(
  1133. DEB_ERROR, &EntryId.Prefix.Buffer, 1, DFS_CANT_SYNC_SERVER_MSG );
  1134. }
  1135. return( (BOOL) (Status == STATUS_REGISTRY_RECOVERED) );
  1136. }
  1137. //+----------------------------------------------------------------------------
  1138. //
  1139. // Function: CDfsService::VerifyStgIdInUse
  1140. //
  1141. // Synopsis: Given a storage id, verifies using knowledge on the DC whether
  1142. // that storage id or some parent/child thereof is already shared.
  1143. // This routine simply fsctls to the driver, which does the
  1144. // verification.
  1145. //
  1146. // Arguments: [pustrStgId] -- The storage id to check.
  1147. //
  1148. // Returns: TRUE if this storage id or some parent/child thereof is already
  1149. // shared, FALSE otherwise.
  1150. //
  1151. //-----------------------------------------------------------------------------
  1152. BOOL CDfsService::VerifyStgIdInUse(
  1153. PUNICODE_STRING pustrStgId)
  1154. {
  1155. NTSTATUS Status = STATUS_SUCCESS;
  1156. DFS_PKT_ENTRY_ID EntryId;
  1157. BOOL fStgIdInUse;
  1158. //
  1159. // Marshal the machine's Guid and the storage id into a DFS_PKT_ENTRY_ID
  1160. // structure, and fsctl to the driver to verify the storage id.
  1161. //
  1162. memcpy(
  1163. (PVOID) &EntryId.Uid,
  1164. (PVOID) &_DfsPktService.pMachEntry->pMachine->guidMachine,
  1165. sizeof(GUID) );
  1166. EntryId.Prefix = *pustrStgId;
  1167. // Status = DfsCheckStgIdInUse( &EntryId );
  1168. fStgIdInUse = (Status == STATUS_DEVICE_BUSY);
  1169. if (Status != STATUS_DEVICE_BUSY && Status != STATUS_SUCCESS) {
  1170. LogMessage( DEB_TRACE,
  1171. &pustrStgId->Buffer,
  1172. 1,
  1173. DFS_CANT_VERIFY_SERVER_KNOWLEDGE_MSG );
  1174. }
  1175. return( fStgIdInUse );
  1176. }
  1177. //+----------------------------------------------------------------------------
  1178. //
  1179. // Function: CDfsService::SetCreateTime, public
  1180. //
  1181. // Synopsis: Initializes the Modification Time of this service to the
  1182. // current time.
  1183. //
  1184. // Arguments: None
  1185. //
  1186. // Returns: Nothing
  1187. //
  1188. //-----------------------------------------------------------------------------
  1189. VOID CDfsService::SetCreateTime()
  1190. {
  1191. SYSTEMTIME st;
  1192. FILETIME ft;
  1193. GetSystemTime( &st );
  1194. SystemTimeToFileTime( &st, &_ftModification );
  1195. }
  1196. //+----------------------------------------------------------------------------
  1197. //
  1198. // Function: RelationInfoToNetInfo, private
  1199. //
  1200. // Synopsis: Converts a DFS_PKT_RELATION_INFO struct into a
  1201. // NET_DFS_ENTRY_ID_CONTAINER struct for use with I_NetDfs calls.
  1202. //
  1203. // Arguments: [RelationInfo] -- Reference to source DFS_PKT_RELATION_INFO
  1204. //
  1205. // [pNetInfo] -- On successful return, contains a valid
  1206. // NET_DFS_ENTRY_ID_CONTAINER. pNetInfo->Buffer is
  1207. // allocated using new - caller responsible for freeing
  1208. // it using delete.
  1209. //
  1210. // Returns: [ERROR_SUCCESS] -- Successfully created *ppNetInfo.
  1211. //
  1212. // [ERROR_OUTOFMEMORY] -- Unable to allocate room for the info.
  1213. //
  1214. //-----------------------------------------------------------------------------
  1215. DWORD
  1216. RelationInfoToNetInfo(
  1217. PDFS_PKT_RELATION_INFO RelationInfo,
  1218. LPNET_DFS_ENTRY_ID_CONTAINER pNetInfo)
  1219. {
  1220. DWORD dwErr;
  1221. ULONG i;
  1222. //
  1223. // The +1 is so we don't try to do a 0 length allocation. This simplifies
  1224. // cleanup in the caller's code.
  1225. //
  1226. pNetInfo->Buffer = new NET_DFS_ENTRY_ID
  1227. [RelationInfo->SubordinateIdCount + 1];
  1228. if (pNetInfo->Buffer != NULL) {
  1229. pNetInfo->Count = RelationInfo->SubordinateIdCount;
  1230. for (i = 0; i < pNetInfo->Count; i++) {
  1231. pNetInfo->Buffer[i].Uid = RelationInfo->SubordinateIdList[i].Uid;
  1232. pNetInfo->Buffer[i].Prefix =
  1233. RelationInfo->SubordinateIdList[i].Prefix.Buffer;
  1234. }
  1235. dwErr = ERROR_SUCCESS;
  1236. } else {
  1237. pNetInfo->Count = 0;
  1238. dwErr = ERROR_OUTOFMEMORY;
  1239. }
  1240. return( dwErr );
  1241. }