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.

655 lines
16 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1995, Microsoft Corporation
  4. //
  5. // File: cdfsvol.cxx
  6. //
  7. // Contents: Class to abstract a Dfs Volume object and all the
  8. // administration operations that can be performed on a
  9. // volume object.
  10. //
  11. // Classes: CDfsVolume
  12. //
  13. // Functions:
  14. //
  15. // History: 05/10/93 Sudk Created.
  16. // 12/19/95 Milans Ported to NT.
  17. //
  18. //-----------------------------------------------------------------------------
  19. #include "headers.hxx"
  20. #pragma hdrstop
  21. #include <cguid.h>
  22. #include "cdfsvol.hxx"
  23. #include "cldap.hxx"
  24. extern "C" {
  25. #include <winldap.h>
  26. #include <dsgetdc.h>
  27. }
  28. #include "setup.hxx"
  29. const GUID CLSID_CDfsVolume = {
  30. 0xd9918520, 0xb074, 0x11cd, { 0x47, 0x94, 0x26, 0x8a, 0x82, 0x6b, 0x00, 0x00 }
  31. };
  32. extern "C"
  33. DWORD
  34. DfsGetFtServersFromDs(
  35. PLDAP pLDAP,
  36. LPWSTR wszDomainName,
  37. LPWSTR wszDfsName,
  38. LPWSTR **List);
  39. extern CLdap *pDfsmLdap;
  40. //---------------------------------------------------------------------------
  41. //
  42. // Class CDfsVolume Member Function Implementations
  43. //
  44. //---------------------------------------------------------------------------
  45. //+-------------------------------------------------------------------------
  46. //
  47. // Function: CDfsVolume::CDfsVolume
  48. //
  49. // Synopsis: Constructor
  50. //
  51. //--------------------------------------------------------------------------
  52. CDfsVolume::CDfsVolume()
  53. {
  54. IDfsVolInlineDebOut((
  55. DEB_TRACE, "CDfsVolume::+CDfsVolume(0x%x)\n",
  56. this));
  57. _pStorage = NULL;
  58. _pwzFileName = _FileNameBuffer;
  59. _pwszParentName = _ParentNameBuffer;
  60. _dwRotRegistration = NULL;
  61. memset(&_peid, 0, sizeof(DFS_PKT_ENTRY_ID));
  62. _peid.Prefix.Buffer = _EntryPathBuffer;
  63. _peid.ShortPrefix.Buffer = _ShortPathBuffer;
  64. _pRecoverySvc = NULL;
  65. _Deleted = TRUE;
  66. _State = DFS_VOLUME_STATE_OK;
  67. _Timeout = GTimeout;
  68. _pwszComment = NULL;
  69. memset( &_ftEntryPath, 0, sizeof(FILETIME));
  70. memset( &_ftState, 0, sizeof(FILETIME));
  71. memset( &_ftComment, 0, sizeof(FILETIME));
  72. }
  73. //+-------------------------------------------------------------------------
  74. //
  75. // Function: CDfsVolume::~CDfsVolume
  76. //
  77. // Synopsis: Destructor
  78. //
  79. //--------------------------------------------------------------------------
  80. CDfsVolume::~CDfsVolume()
  81. {
  82. IDfsVolInlineDebOut((
  83. DEB_TRACE, "CDfsVolume::~CDfsVolume(0x%x)\n",
  84. this));
  85. #if DBG
  86. if (DfsSvcVerbose & 0x80000000) {
  87. DbgPrint("CDfsVolume::~CDfsVolume @0x%x\n", this);
  88. DbgPrint(" _DfsSvcList@0x%x\n", &_DfsSvcList);
  89. }
  90. #endif
  91. if (_pStorage != NULL)
  92. _pStorage->Release();
  93. if (_pwzFileName != NULL && _pwzFileName != _FileNameBuffer)
  94. delete [] _pwzFileName;
  95. if (_pwszParentName != NULL && _pwszParentName != _ParentNameBuffer)
  96. delete [] _pwszParentName;
  97. if (_peid.Prefix.Buffer != NULL && _peid.Prefix.Buffer != _EntryPathBuffer)
  98. delete [] _peid.Prefix.Buffer;
  99. if (_peid.ShortPrefix.Buffer != NULL && _peid.ShortPrefix.Buffer != _ShortPathBuffer) {
  100. delete [] _peid.ShortPrefix.Buffer;
  101. }
  102. if (_pwszComment != NULL)
  103. delete [] _pwszComment;
  104. if (_pRecoverySvc != NULL)
  105. delete _pRecoverySvc;
  106. }
  107. //+-------------------------------------------------------------------------
  108. // IPersist Methods
  109. //--------------------------------------------------------------------------
  110. //+-------------------------------------------------------------------------
  111. //
  112. // Function: CDfsVolume::GetClassID
  113. //
  114. // Synopsis: Return classid - This is the implementation for both the
  115. // IPersistStorage and IPersistFile Interfaces.
  116. //
  117. //--------------------------------------------------------------------------
  118. DWORD
  119. CDfsVolume::GetClassID(LPCLSID lpClassID)
  120. {
  121. *lpClassID = CLSID_CDfsVolume;
  122. return(ERROR_SUCCESS);
  123. }
  124. //+-------------------------------------------------------------------------
  125. // IPersistStorage Methods
  126. //--------------------------------------------------------------------------
  127. //+----------------------------------------------------------------------------
  128. //
  129. // Function: GetNameFromStorage
  130. //
  131. // Synopsis: Given an IStorage, this routine computes the name of the
  132. // object.
  133. //
  134. // Arguments: [pstg] -- The storage whose name is to be computed
  135. // [ppwszName] -- Points to a buffer containing the name
  136. // [wszBuffer] -- The buffer to use if name is <= MAX_PATH
  137. //
  138. // Returns: ERROR_SUCCESS if successful
  139. // ERROR_OUTOFMEMORY if out of memory
  140. // NERR_DfsInternalError if any other error
  141. //
  142. //-----------------------------------------------------------------------------
  143. DWORD
  144. GetNameFromStorage(
  145. CStorage *pstg,
  146. LPWSTR *ppwszName,
  147. WCHAR wszBuffer[])
  148. {
  149. DWORD dwErr;
  150. ULONG cLen;
  151. LPWSTR pwszName = NULL;
  152. DFSMSTATSTG statstg;
  153. ZeroMemory( &statstg, sizeof(statstg) );
  154. dwErr = pstg->Stat( &statstg, STATFLAG_DEFAULT );
  155. if (dwErr == ERROR_SUCCESS) {
  156. cLen = 2 + wcslen( statstg.pwcsName ) + 1;
  157. if (cLen > MAX_PATH) {
  158. pwszName = new WCHAR[ cLen ];
  159. if (pwszName == NULL) {
  160. IDfsVolInlineDebOut((
  161. DEB_ERROR, "Unable to allocate %d bytes\n",
  162. cLen * sizeof(WCHAR)));
  163. dwErr = ERROR_OUTOFMEMORY;
  164. } else {
  165. wcscpy( pwszName, statstg.pwcsName );
  166. *ppwszName = pwszName;
  167. }
  168. } else { // Use given buffer
  169. pwszName = wszBuffer;
  170. wcscpy( pwszName, statstg.pwcsName );
  171. *ppwszName = pwszName;
  172. }
  173. delete [] statstg.pwcsName;
  174. } else {
  175. IDfsVolInlineDebOut((
  176. DEB_ERROR, "Error %08lx getting storage stats\n", dwErr ));
  177. dwErr = NERR_DfsInternalError;
  178. }
  179. return( dwErr );
  180. }
  181. //+-------------------------------------------------------------------------
  182. //
  183. // Function: CDfsVolume::InitNew
  184. //
  185. // Synopsis: InitNew is only called by the reconciler when a new
  186. // volume object is created as a result of a reconciliation.
  187. // We simply create all the appropriate property sets so that
  188. // the volume object reconciler can reconcile the property sets
  189. //
  190. //--------------------------------------------------------------------------
  191. DWORD
  192. CDfsVolume::InitNew(CStorage *pStg)
  193. {
  194. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::InitNew()\n"));
  195. DWORD dwErr;
  196. ASSERT( _pStorage == NULL );
  197. //
  198. // Save and AddRef the storage so it wont go away from us.
  199. //
  200. _pStorage = pStg;
  201. _pStorage->AddRef();
  202. //
  203. // First thing we do now is to setup the Class ID.
  204. //
  205. dwErr = _pStorage->SetClass(CLSID_CDfsVolume);
  206. //
  207. // Next, we Initialize the property sets.
  208. //
  209. if (dwErr == ERROR_SUCCESS)
  210. dwErr = SetVersion( TRUE );
  211. if (dwErr == ERROR_SUCCESS) {
  212. _Recover.Initialize(_pStorage);
  213. _Recover.SetDefaultProps();
  214. }
  215. if (dwErr == ERROR_SUCCESS)
  216. dwErr = _DfsSvcList.SetNullSvcList( _pStorage );
  217. //
  218. // Need to initialize our _pwzFileName member
  219. //
  220. if (dwErr == ERROR_SUCCESS) {
  221. ASSERT( _pwzFileName == _FileNameBuffer );
  222. dwErr = GetNameFromStorage(
  223. _pStorage,
  224. &_pwzFileName,
  225. _FileNameBuffer );
  226. }
  227. if (dwErr == ERROR_SUCCESS) {
  228. _Deleted = FALSE;
  229. IDfsVolInlineDebOut((
  230. DEB_TRACE, "Volume Object [%ws] successfully inited\n",
  231. _pwzFileName));
  232. }
  233. return( dwErr );
  234. }
  235. //+-------------------------------------------------------------------------
  236. //
  237. // Function: CDfsVolume::Save
  238. //
  239. // Synopsis: Saves the persistent state of the object. We really don't need
  240. // to support this. It really makes no sense to support this?
  241. //
  242. //--------------------------------------------------------------------------
  243. DWORD
  244. CDfsVolume::Save(
  245. CStorage *pStgSave,
  246. BOOL fSameAsLoad)
  247. {
  248. return(ERROR_SUCCESS);
  249. }
  250. //+-------------------------------------------------------------------------
  251. //
  252. // Function: CDfsVolume::Load
  253. //
  254. // Synopsis: Loads a DfsVolume and the components it contains from
  255. // storage.
  256. //
  257. //--------------------------------------------------------------------------
  258. DWORD
  259. CDfsVolume::Load(
  260. CStorage *pStg)
  261. {
  262. DWORD dwErr = ERROR_SUCCESS;
  263. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::Load()\n"));
  264. ASSERT(_pStorage == NULL);
  265. _pStorage = pStg;
  266. _pStorage->AddRef();
  267. if (dwErr == ERROR_SUCCESS)
  268. dwErr = GetVersion( &_Version );
  269. //
  270. // Out here we are passing in the _pPSStorage. The called people will
  271. // Addref and release this _pStorage on their own.
  272. //
  273. if (dwErr == ERROR_SUCCESS) {
  274. _Recover.Initialize(_pStorage);
  275. dwErr = _DfsSvcList.InitializeServiceList(_pStorage);
  276. }
  277. if (dwErr == ERROR_SUCCESS) {
  278. dwErr = GetIdProps( &_EntryType,
  279. &_peid.Prefix.Buffer,
  280. &_peid.ShortPrefix.Buffer,
  281. &_pwszComment,
  282. &_peid.Uid,
  283. &_State,
  284. &_Timeout,
  285. &_ftEntryPath,
  286. &_ftState,
  287. &_ftComment);
  288. }
  289. if (dwErr == ERROR_SUCCESS) {
  290. _peid.Prefix.Length = wcslen(_peid.Prefix.Buffer) * sizeof(WCHAR);
  291. _peid.Prefix.MaximumLength = _peid.Prefix.Length + sizeof(WCHAR);
  292. _peid.ShortPrefix.Length = wcslen(_peid.ShortPrefix.Buffer) * sizeof(WCHAR);
  293. _peid.ShortPrefix.MaximumLength = _peid.ShortPrefix.Length + sizeof(WCHAR);
  294. dwErr = _Recover.GetRecoveryProps(&_RecoveryState, &_pRecoverySvc);
  295. if (dwErr != ERROR_SUCCESS) {
  296. IDfsVolInlineDebOut((DEB_ERROR,
  297. "CouldNot read RecoveryProps off Stg %08lx\n",
  298. dwErr));
  299. _RecoveryState = DFS_RECOVERY_STATE_NONE;
  300. _pRecoverySvc = NULL;
  301. dwErr = ERROR_SUCCESS;
  302. }
  303. }
  304. if (dwErr == ERROR_SUCCESS) {
  305. _Deleted = FALSE;
  306. }
  307. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::Load() exit\n"));
  308. return( dwErr );
  309. };
  310. //+-------------------------------------------------------------------------
  311. // IPersistFile Methods
  312. //--------------------------------------------------------------------------
  313. DWORD
  314. CDfsVolume::Load(LPCWSTR pwszFileName, DWORD grfMode)
  315. {
  316. DWORD dwErr;
  317. dwErr = LoadNoRegister( pwszFileName, grfMode );
  318. return( dwErr );
  319. }
  320. //+-------------------------------------------------------------------------
  321. //
  322. // Function: CDfsVolume::LoadNoRegister
  323. //
  324. // Synopsis: Load the DfsVolume from a volume object. This is where all the
  325. // initialization takes place.
  326. //
  327. //--------------------------------------------------------------------------
  328. DWORD
  329. CDfsVolume::LoadNoRegister(
  330. LPCWSTR pwszFileName,
  331. DWORD grfMode)
  332. {
  333. DWORD dwErr = ERROR_SUCCESS;
  334. IDfsVolInlineDebOut((
  335. DEB_TRACE, "CDfsVolume::LoadNoRegister(%ws)\n", pwszFileName));
  336. dwErr = DfsmOpenStorage(
  337. pwszFileName,
  338. (CStorage FAR* FAR*)&_pStorage);
  339. if (dwErr == ERROR_SUCCESS) {
  340. ULONG uLen = wcslen(pwszFileName);
  341. if (uLen > MAX_PATH)
  342. _pwzFileName = new WCHAR[(uLen+1)];
  343. else
  344. _pwzFileName = _FileNameBuffer;
  345. if (_pwzFileName == NULL)
  346. dwErr = ERROR_OUTOFMEMORY;
  347. else
  348. wcscpy(_pwzFileName, pwszFileName);
  349. } else {
  350. IDfsVolInlineDebOut((
  351. DEB_TRACE, "Unable to open %ws, %08lx\n", pwszFileName, dwErr));
  352. }
  353. //
  354. // Before we do anything, lets see if the volume object is current.
  355. //
  356. if (dwErr == ERROR_SUCCESS)
  357. dwErr = UpgradeObject();
  358. if (dwErr == ERROR_SUCCESS)
  359. dwErr = GetVersion( &_Version );
  360. if (dwErr == ERROR_SUCCESS) {
  361. //
  362. // Out here we are passing in the _pPSStorage. The called people
  363. // will Addref and release this _pStorage on their own.
  364. //
  365. _Recover.Initialize(_pStorage);
  366. dwErr = _DfsSvcList.InitializeServiceList(_pStorage);
  367. }
  368. if (dwErr == ERROR_SUCCESS) {
  369. dwErr = GetIdProps( &_EntryType,
  370. &(_peid.Prefix.Buffer),
  371. &(_peid.ShortPrefix.Buffer),
  372. &_pwszComment,
  373. &(_peid.Uid),
  374. &_State,
  375. &_Timeout,
  376. &_ftEntryPath,
  377. &_ftState,
  378. &_ftComment);
  379. }
  380. if (dwErr == ERROR_SUCCESS) {
  381. _peid.Prefix.Length = wcslen(_peid.Prefix.Buffer) * sizeof(WCHAR);
  382. _peid.Prefix.MaximumLength = _peid.Prefix.Length + sizeof(WCHAR);
  383. _peid.ShortPrefix.Length = wcslen(_peid.ShortPrefix.Buffer) * sizeof(WCHAR);
  384. _peid.ShortPrefix.MaximumLength = _peid.ShortPrefix.Length + sizeof(WCHAR);
  385. dwErr = _Recover.GetRecoveryProps(&_RecoveryState, &_pRecoverySvc);
  386. if (dwErr != ERROR_SUCCESS) {
  387. IDfsVolInlineDebOut((DEB_ERROR,
  388. "CouldNot read RecoveryProps off %ws\n",
  389. _pwzFileName));
  390. IDfsVolInlineDebOut((DEB_ERROR,"\tError = %08lx\n",dwErr));
  391. _RecoveryState = DFS_RECOVERY_STATE_NONE;
  392. _pRecoverySvc = NULL;
  393. dwErr = ERROR_SUCCESS;
  394. }
  395. }
  396. if (dwErr == ERROR_SUCCESS) {
  397. _Deleted = FALSE;
  398. }
  399. IDfsVolInlineDebOut((
  400. DEB_TRACE, "CDfsVolume::LoadNoRegister() exit\n"));
  401. return( dwErr );
  402. }
  403. //+-------------------------------------------------------------------------
  404. //
  405. // Function: CDfsVolume::Save
  406. //
  407. // Synopsis: Not Implemented
  408. //
  409. //--------------------------------------------------------------------------
  410. DWORD
  411. CDfsVolume::Save(LPCWSTR pwzFileName, BOOL fRemember)
  412. {
  413. DWORD dwErr = ERROR_SUCCESS;
  414. return( dwErr );
  415. }
  416. DWORD
  417. CDfsVolume::SyncWithRemoteServerNameInDs(void)
  418. {
  419. DWORD InfoSize = 0;
  420. DWORD dwError = NO_ERROR;
  421. DFS_INFO_3 DfsInfo;
  422. BOOLEAN Found = FALSE;;
  423. PDFSM_ROOT_LIST pRootList = NULL;
  424. DFS_REPLICA_INFO *pReplicaInfo = NULL;
  425. WCHAR* ServerShare = NULL;
  426. DWORD Length = 0;
  427. WCHAR* DcName = NULL;
  428. DWORD i,j;
  429. PDOMAIN_CONTROLLER_INFO pDomainControllerInfo = NULL;
  430. LPWSTR *pList = NULL;
  431. WCHAR wszFtDfsName[MAX_PATH+1];
  432. ULONG start = 0;
  433. ULONG end = 0;
  434. CDfsService *pService;
  435. LPWSTR DfsName = NULL;
  436. RtlZeroMemory(wszFtDfsName, sizeof(wszFtDfsName));
  437. RtlCopyMemory(wszFtDfsName, _peid.Prefix.Buffer, _peid.Prefix.Length);
  438. //
  439. // Extract the ftdfs name from the DfsInfo.EntryPath
  440. //
  441. for (DfsName = &wszFtDfsName[1];
  442. *DfsName != UNICODE_PATH_SEP && *DfsName != UNICODE_NULL;
  443. DfsName++) {
  444. NOTHING;
  445. }
  446. if (*DfsName == UNICODE_PATH_SEP)
  447. DfsName++;
  448. if(dwError == ERROR_SUCCESS) {
  449. dwError = DfsGetFtServersFromDs(
  450. NULL,
  451. NULL,
  452. DfsName,
  453. &pList
  454. );
  455. }
  456. if(dwError == ERROR_SUCCESS) {
  457. pService=_DfsSvcList.GetFirstService();
  458. while(pService) {
  459. Found = FALSE;
  460. for(j=0;pList[j]!=NULL;j++) {
  461. Length = sizeof(WCHAR) * 2; // whackwhack
  462. Length += sizeof(WCHAR) * wcslen(pService->GetServiceName()); // server
  463. Length += sizeof(WCHAR); // whack
  464. Length += sizeof(WCHAR) * wcslen(pService->GetShareName()); // share
  465. Length += sizeof(WCHAR); // terminating null
  466. ServerShare = (WCHAR *)malloc(Length);
  467. if(ServerShare == NULL) {
  468. dwError = ERROR_NOT_ENOUGH_MEMORY;
  469. goto exit;
  470. }
  471. wcscpy(ServerShare, L"\\\\");
  472. wcscat(ServerShare, pService->GetServiceName());
  473. wcscat(ServerShare, L"\\");
  474. wcscat(ServerShare, pService->GetShareName());
  475. if(wcscmp(ServerShare, pList[j]) == 0) {
  476. Found = TRUE;
  477. break;
  478. }
  479. free(ServerShare);
  480. ServerShare = NULL;
  481. }
  482. if(!Found) {
  483. // after we delete the service we can no longer get the next in the list,
  484. // so we grab it first.
  485. CDfsService *NextService = _DfsSvcList.GetNextService(pService);
  486. dwError = _DfsSvcList.DeleteService(pService, FALSE);
  487. if(dwError != ERROR_SUCCESS) {
  488. break;
  489. }
  490. pService = NextService;
  491. } else {
  492. pService=_DfsSvcList.GetNextService(pService);
  493. }
  494. }
  495. }
  496. exit:
  497. if(pList) {
  498. NetApiBufferFree(pList);
  499. }
  500. return dwError;
  501. }