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.

1872 lines
49 KiB

  1. //-------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (CC) Microsoft Corporation 1992, 1992
  6. //
  7. // File: idfsvsup.cxx
  8. //
  9. // Contents: This contains support methods for the IDfsVol interface
  10. // implementation.
  11. //
  12. //-------------------------------------------------------------
  13. //#include <ntos.h>
  14. //#include <ntrtl.h>
  15. //#include <nturtl.h>
  16. //#include <dfsfsctl.h>
  17. //#include <windows.h>
  18. #include <headers.hxx>
  19. #pragma hdrstop
  20. #include <dfserr.h>
  21. #include "cdfsvol.hxx"
  22. #include "dfsmwml.h"
  23. NTSTATUS
  24. DfspCreateExitPoint (
  25. IN HANDLE DriverHandle,
  26. IN LPGUID Uid,
  27. IN LPWSTR Prefix,
  28. IN ULONG Type,
  29. IN ULONG ShortPrefixLen,
  30. OUT LPWSTR ShortPrefix);
  31. NTSTATUS
  32. DfspDeleteExitPoint (
  33. IN HANDLE DriverHandle,
  34. IN LPGUID Uid,
  35. IN LPWSTR Prefix,
  36. IN ULONG Type);
  37. //+-------------------------------------------------------------------------
  38. //
  39. // Member: CDfsVolume::CreateObject, public
  40. //
  41. // Synopsis: This method merely creates a volume object. This has no
  42. // distributed operations associated with this operation.
  43. //
  44. // Arguments: [pwzVolObjName] -- VOlume object Name
  45. // [EntryPath] -- The EntryPath
  46. // [VolType] -- VolumeType
  47. // [pReplicaInfo] -- ReplicaInfo. This is optional.
  48. //
  49. // Returns:
  50. //
  51. // Notes: Raid: 455299 This function could potentially fail and leave an
  52. // object hanging around??
  53. //
  54. // History: 17-May-1993 SudK Created.
  55. //
  56. //--------------------------------------------------------------------------
  57. DWORD
  58. CDfsVolume::CreateObject(
  59. PWSTR pwszVolObjName,
  60. LPWSTR pwszPrefix,
  61. ULONG ulVolType,
  62. PDFS_REPLICA_INFO pReplicaInfo,
  63. PWCHAR pwszComment,
  64. GUID *pUid
  65. )
  66. {
  67. DWORD dwErr = ERROR_SUCCESS;
  68. CDfsService *pService;
  69. SYSTEMTIME st;
  70. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateVolObject(%ws,%ws,0x%x,%ws)\n",
  71. pwszVolObjName, pwszPrefix, ulVolType, pwszComment));
  72. //
  73. // First put this name in the private section.
  74. //
  75. ULONG volLen = wcslen(pwszVolObjName);
  76. if (volLen > MAX_PATH) {
  77. _pwzFileName = new WCHAR[volLen + 1];
  78. } else {
  79. _pwzFileName = _FileNameBuffer;
  80. }
  81. if (_pwzFileName == NULL)
  82. return( ERROR_OUTOFMEMORY );
  83. wcscpy(_pwzFileName, pwszVolObjName);
  84. IDfsVolInlineDebOut((DEB_TRACE, "Creating Object%ws\n", pwszVolObjName));
  85. //
  86. // Create the storage object.
  87. //
  88. dwErr = DfsmCreateStorage(
  89. pwszVolObjName,
  90. &_pStorage);
  91. if (dwErr != ERROR_SUCCESS) {
  92. IDfsVolInlineDebOut((DEB_ERROR,
  93. "Unable to create directory storage object %08lx %ws\n",
  94. dwErr, pwszVolObjName));
  95. return(dwErr);
  96. }
  97. //
  98. // First thing we do now is to setup the Class.
  99. //
  100. dwErr = _pStorage->SetClass(CLSID_CDfsVolume);
  101. if (dwErr != ERROR_SUCCESS) {
  102. IDfsVolInlineDebOut((DEB_ERROR,
  103. "Unable to set Class on this %ws\n", pwszVolObjName));
  104. return(dwErr);
  105. }
  106. //
  107. // This is where we need to init and create the dummy property sets
  108. // so that next time around we can set them and dont need to create them.
  109. //
  110. dwErr = SetVersion( TRUE );
  111. if (dwErr != ERROR_SUCCESS) {
  112. IDfsVolInlineDebOut((DEB_ERROR,
  113. "Unable to create version propset for %ws Error: %08lx\n",
  114. pwszVolObjName, dwErr));
  115. return(dwErr);
  116. }
  117. GUID Uid;
  118. if (pUid == NULL) {
  119. dwErr = UuidCreate(&Uid);
  120. _peid.Uid = Uid;
  121. } else {
  122. _peid.Uid = *pUid;
  123. }
  124. _EntryType = ulVolType;
  125. ULONG epLen = wcslen(pwszPrefix);
  126. if (epLen > MAX_PATH) {
  127. _peid.Prefix.Buffer = new WCHAR[epLen + 1];
  128. _peid.Prefix.MaximumLength = (USHORT) ((epLen + 1)*sizeof(WCHAR));
  129. } else {
  130. _peid.Prefix.MaximumLength = sizeof(_EntryPathBuffer);
  131. _peid.Prefix.Buffer = _EntryPathBuffer;
  132. }
  133. if (_peid.Prefix.Buffer == NULL)
  134. return( ERROR_OUTOFMEMORY );
  135. _peid.Prefix.Length = (USHORT) epLen*sizeof(WCHAR);
  136. wcscpy(_peid.Prefix.Buffer, pwszPrefix);
  137. //
  138. // We don't yet know the short name of this volume, so simply allocate
  139. // enough room and fill it with the full prefix. When an exit point
  140. // corresponding to this volume is created, the short prefix might be
  141. // modified.
  142. //
  143. // Note that it is tempting to think that the short prefix is <= the full
  144. // prefix in size. This, however, is not a valid assumption, because
  145. // names like A.BCDE qualify as LFNs, and their 8.3 equivalents look like
  146. // A12345~1.BCD!
  147. //
  148. ULONG i, sepLen;
  149. for (i = 0, sepLen = 0; i < epLen; i++) {
  150. if (pwszPrefix[i] == UNICODE_PATH_SEP)
  151. sepLen ++;
  152. }
  153. sepLen *= (1+8+1+3); // For \8.3
  154. if (sepLen < epLen)
  155. sepLen = epLen;
  156. if (sepLen > MAX_PATH) {
  157. _peid.ShortPrefix.Buffer = new WCHAR[sepLen + 1];
  158. _peid.ShortPrefix.MaximumLength = (USHORT) ((sepLen + 1)*sizeof(WCHAR));
  159. } else {
  160. _peid.ShortPrefix.Buffer = _ShortPathBuffer;
  161. _peid.ShortPrefix.MaximumLength = sizeof(_ShortPathBuffer);
  162. }
  163. if (_peid.ShortPrefix.Buffer == NULL)
  164. return( ERROR_OUTOFMEMORY );
  165. _peid.ShortPrefix.Length = (USHORT) epLen*sizeof(WCHAR);
  166. wcscpy(_peid.ShortPrefix.Buffer, pwszPrefix);
  167. //
  168. // We need to deal with a NULL comment as well.
  169. //
  170. if (pwszComment != NULL) {
  171. _pwszComment = new WCHAR[wcslen(pwszComment) + 1];
  172. if (_pwszComment != NULL) {
  173. wcscpy(_pwszComment, pwszComment);
  174. }
  175. } else {
  176. _pwszComment = new WCHAR[1];
  177. if (_pwszComment != NULL) {
  178. *_pwszComment = UNICODE_NULL;
  179. }
  180. }
  181. if (_pwszComment == NULL) {
  182. return( ERROR_OUTOFMEMORY );
  183. }
  184. GetSystemTime( &st );
  185. SystemTimeToFileTime( &st, &_ftEntryPath );
  186. _ftComment = _ftState = _ftEntryPath;
  187. dwErr = SetIdProps(
  188. ulVolType,
  189. _State,
  190. pwszPrefix,
  191. pwszPrefix,
  192. _peid.Uid,
  193. _pwszComment,
  194. _Timeout,
  195. _ftEntryPath,
  196. _ftState,
  197. _ftComment,
  198. TRUE);
  199. if (dwErr != ERROR_SUCCESS)
  200. return(dwErr);
  201. _Recover.Initialize(_pStorage);
  202. _Recover.SetDefaultProps();
  203. //
  204. // Now let us set a NULL service List property. This method will create
  205. // the stream as well. We dont need to bother.
  206. //
  207. dwErr = _DfsSvcList.SetNullSvcList(_pStorage);
  208. if (dwErr != ERROR_SUCCESS)
  209. return(dwErr);
  210. _Deleted = FALSE;
  211. //
  212. // Everything is setup now. We can set the appropriate service etc.
  213. //
  214. if (pReplicaInfo != NULL) {
  215. pService = new CDfsService(pReplicaInfo, FALSE, &dwErr);
  216. if (pService == NULL) {
  217. dwErr = ERROR_OUTOFMEMORY;
  218. }
  219. if (dwErr == ERROR_SUCCESS) {
  220. dwErr = _DfsSvcList.SetNewService(pService);
  221. if (dwErr != ERROR_SUCCESS) {
  222. delete pService;
  223. }
  224. }
  225. }
  226. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateVolObject() exit\n"));
  227. return(dwErr);
  228. }
  229. //+-------------------------------------------------------------------------
  230. //
  231. // Member: CDfsVolume::GetDfsVolumeFromStg, private
  232. //
  233. // Synopsis: This method takes a STATDIR structure and returns a CDfsVol
  234. // pointer to the object corresponding to that.
  235. //
  236. // Arguments: [rgelt] -- Pointer to the DFSMSTATDIR structure.
  237. // [ppDfsVol] -- This is where the DfsVol is returned.
  238. //
  239. // Returns: [ERROR_SUCCESS] -- If successfully set the parent's path.
  240. //
  241. // [ERROR_OUTOFMEMORY] -- If unable to allocate memory for parent's
  242. // path.
  243. //
  244. // Error from loading the volume object
  245. //
  246. //--------------------------------------------------------------------------
  247. DWORD
  248. CDfsVolume::GetDfsVolumeFromStg(
  249. DFSMSTATDIR *rgelt,
  250. CDfsVolume **ppDfsVol)
  251. {
  252. DWORD dwErr = ERROR_SUCCESS;
  253. PWCHAR pwszFullName;
  254. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetDfsVolumeFromStg()\n"));
  255. //
  256. // Allocate a new CDfsVolume and initialize with appropriate name.
  257. //
  258. *ppDfsVol = new CDfsVolume();
  259. if (*ppDfsVol == NULL)
  260. return( ERROR_OUTOFMEMORY );
  261. pwszFullName = new WCHAR[wcslen(_pwzFileName) + wcslen(rgelt->pwcsName) + 2];
  262. if (pwszFullName != NULL) {
  263. wcscpy(pwszFullName, _pwzFileName);
  264. wcscat(pwszFullName, L"\\");
  265. wcscat(pwszFullName, rgelt->pwcsName);
  266. dwErr = (*ppDfsVol)->LoadNoRegister(pwszFullName, 0);
  267. delete [] pwszFullName;
  268. } else {
  269. dwErr = ERROR_OUTOFMEMORY;
  270. }
  271. if (dwErr != ERROR_SUCCESS) {
  272. (*ppDfsVol)->Release();
  273. *ppDfsVol = NULL;
  274. }
  275. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetDfsVolumeFromStg() exit\n"));
  276. return(dwErr);
  277. }
  278. //+-------------------------------------------------------------------------
  279. //
  280. // Member: CDfsVolume::SetParentPath, private
  281. //
  282. // Synopsis: This method figures out the name of the parent object and
  283. // sets it up in the private section of this instance.
  284. //
  285. // Arguments: None
  286. //
  287. // Returns: [ERROR_SUCCESS] -- If successfully set the parent's path.
  288. //
  289. // [ERROR_OUTOFMEMORY] -- If unable to allocate memory for parent's
  290. // path.
  291. //
  292. //--------------------------------------------------------------------------
  293. DWORD
  294. CDfsVolume::SetParentPath(void)
  295. {
  296. PWCHAR pwszLastComponent;
  297. ULONG parentLen;
  298. pwszLastComponent = wcsrchr(_pwzFileName, L'\\');
  299. if(pwszLastComponent == NULL) {
  300. return ERROR_INVALID_DATA;
  301. }
  302. ASSERT(*(pwszLastComponent + 1) != UNICODE_NULL);
  303. //
  304. // Let us now figure out the length of the parent Name and copy over
  305. // appropriate number of characters.
  306. //
  307. if (_pwszParentName != _ParentNameBuffer)
  308. delete [] _pwszParentName;
  309. parentLen = wcslen(_pwzFileName) - wcslen(pwszLastComponent);
  310. if (parentLen > MAX_PATH) {
  311. _pwszParentName = new WCHAR[parentLen + 1];
  312. if (_pwszParentName == NULL)
  313. return( ERROR_OUTOFMEMORY );
  314. } else {
  315. _pwszParentName = _ParentNameBuffer;
  316. }
  317. wcsncpy(_pwszParentName, _pwzFileName, parentLen);
  318. _pwszParentName[parentLen] = UNICODE_NULL;
  319. return(ERROR_SUCCESS);
  320. }
  321. //+-------------------------------------------------------------------------
  322. //
  323. // Member: CDfsVolume::GetParent, private
  324. //
  325. // Synopsis: This function returns a pointer to IDfsVolume to the parent
  326. // of the present object. The release function on this
  327. // should be called by the caller of this function. We use
  328. // Ths IStorage interface to get to the parent.
  329. //
  330. // Arguments: [pIDfsParent] -- This is where the IDfsVolume for parent is
  331. // returned.
  332. //
  333. // Returns: [ERROR_SUCCESS] -- If everything went well.
  334. //
  335. // [ERROR_OUTOFMEMORY] -- Unable to create parent instance.
  336. //
  337. // History: 14-Sep-92 SudK Created
  338. //
  339. //--------------------------------------------------------------------------
  340. DWORD
  341. CDfsVolume::GetParent(
  342. CDfsVolume **parent)
  343. {
  344. DWORD dwErr = ERROR_SUCCESS;
  345. CDfsVolume *pDfsVol;
  346. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetParent()\n"));
  347. //
  348. // First we get the parent's pathname and then we can do the appropriate.
  349. //
  350. dwErr = SetParentPath();
  351. if (dwErr != ERROR_SUCCESS) {
  352. IDfsVolInlineDebOut((
  353. DEB_ERROR, "Unable to get parentPath %ws %08lx\n",
  354. _pwzFileName, dwErr));
  355. return(dwErr);
  356. }
  357. //
  358. // Now we instantiate a CDfsVolume structure and then initialise it.
  359. //
  360. pDfsVol = new CDfsVolume();
  361. if (pDfsVol == NULL)
  362. return( ERROR_OUTOFMEMORY );
  363. dwErr = pDfsVol->LoadNoRegister(_pwszParentName, 0);
  364. if (dwErr != ERROR_SUCCESS) {
  365. pDfsVol->Release();
  366. *parent = NULL;
  367. return(dwErr);
  368. }
  369. *parent = pDfsVol;
  370. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetParent() exit\n"));
  371. return(dwErr);
  372. }
  373. //+-------------------------------------------------------------------------
  374. //
  375. // Method: CDfsVolume::DeleteObject, private
  376. //
  377. // Synopsis: Support method to merely delete a volume object from
  378. // persistent store.
  379. //
  380. // Arguments: None
  381. //
  382. // Returns: [ERROR_SUCCESS] -- If successfully deleted object.
  383. //
  384. // [ERROR_OUTOFMEMORY] -- Unable to get parent instance.
  385. //
  386. // History: 16-Sep-1992 SudK Created
  387. //
  388. //--------------------------------------------------------------------------
  389. DWORD
  390. CDfsVolume::DeleteObject()
  391. {
  392. DWORD dwErr = ERROR_SUCCESS;
  393. CStorage *parentStg;
  394. PWCHAR pwszLastComponent;
  395. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::DeleteObject()\n"));
  396. //
  397. // We are going to delete this object so let us release all our pointers.
  398. //
  399. ASSERT ((_pStorage != NULL));
  400. _pStorage->Release();
  401. _pStorage = NULL;
  402. //
  403. // Let us now release all the IStorage's which are with CRecover & SvcList
  404. //
  405. if (_Recover._pPSStg != NULL) {
  406. _Recover._pPSStg->Release();
  407. _Recover._pPSStg = NULL;
  408. }
  409. if (_DfsSvcList._pPSStg != NULL) {
  410. _DfsSvcList._pPSStg->Release();
  411. _DfsSvcList._pPSStg = NULL;
  412. }
  413. //
  414. // First we get the parent's pathname and then we can do the appropriate.
  415. //
  416. dwErr = SetParentPath();
  417. if (dwErr != ERROR_SUCCESS) {
  418. IDfsVolInlineDebOut((
  419. DEB_ERROR, "Failed to get parent path for %ws\n", _pwzFileName));
  420. return( dwErr );
  421. }
  422. dwErr = DfsmOpenStorage( _pwszParentName, &parentStg);
  423. if (dwErr != ERROR_SUCCESS) {
  424. IDfsVolInlineDebOut((
  425. DEB_ERROR, "Unable to open [%ws] %08lx\n", _pwszParentName, dwErr));
  426. return( dwErr );
  427. }
  428. //
  429. // Now we have to delete ourselves using our parent's IStorage.
  430. // So we extract the last component name from the file name.
  431. //
  432. pwszLastComponent = _pwzFileName + wcslen(_pwszParentName) + 1;
  433. dwErr = parentStg->DestroyElement(pwszLastComponent);
  434. parentStg->Release();
  435. if (dwErr != ERROR_SUCCESS) {
  436. IDfsVolInlineDebOut((
  437. DEB_ERROR, "Unable to delete [%ws] %08lx\n", _pwzFileName, dwErr));
  438. return( dwErr );
  439. } else {
  440. //
  441. // The storage object has really been deleted, so delete the mapping
  442. // of this prefix from the storage directory.
  443. //
  444. dwErr = pDfsmStorageDirectory->_Delete( _peid.Prefix.Buffer );
  445. ASSERT( dwErr == ERROR_SUCCESS );
  446. }
  447. _Deleted = TRUE;
  448. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::DeleteObject() exit\n"));
  449. return( ERROR_SUCCESS );
  450. }
  451. //+----------------------------------------------------------------------------
  452. //
  453. // Function: CDfsVolume::GetVersion, private
  454. //
  455. // Synopsis: Retrieves the version of the volume object from the property
  456. // stamped on it.
  457. //
  458. // Arguments: [pVersion] -- The version is returned here.
  459. //
  460. // Returns: Result of reading the version property.
  461. //
  462. //-----------------------------------------------------------------------------
  463. DWORD
  464. CDfsVolume::GetVersion(
  465. ULONG * pVersion)
  466. {
  467. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetVersion()\n"));
  468. DWORD dwErr = ERROR_SUCCESS;
  469. dwErr = _pStorage->GetVersionProps(pVersion);
  470. if (dwErr != ERROR_SUCCESS) {
  471. IDfsVolInlineDebOut((DEB_ERROR,
  472. "Unable to read Version Properties %08lx\n",
  473. dwErr));
  474. return(dwErr);
  475. }
  476. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetVersion() exit\n"));
  477. return( dwErr );
  478. }
  479. //+----------------------------------------------------------------------------
  480. //
  481. // Function: SetVersion
  482. //
  483. // Synopsis: Sets the version property on the volume object to
  484. // VOL_OBJ_VERSION_NUMBER
  485. //
  486. // Arguments: [bCreate] -- TRUE if the property set should be created,
  487. // FALSE if the property set should be assumed to
  488. // exist
  489. //
  490. // Returns: Result of setting the property
  491. //
  492. //-----------------------------------------------------------------------------
  493. DWORD
  494. CDfsVolume::SetVersion(
  495. BOOL bCreate)
  496. {
  497. DWORD dwErr;
  498. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetVersion()\n"));
  499. dwErr = _pStorage->SetVersionProps( VOL_OBJ_VERSION_NUMBER );
  500. if (dwErr != ERROR_SUCCESS) {
  501. IDfsVolInlineDebOut(( DEB_ERROR,
  502. "Unable to set Version Properties %08lx\n",
  503. dwErr));
  504. return(dwErr);
  505. }
  506. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetVersion() exit\n"));
  507. return( dwErr );
  508. }
  509. //+-------------------------------------------------------------------------
  510. //
  511. // Method: CDfsVolume::GetIdProps, private
  512. //
  513. // Synopsis: Gets the ID Properties from a volume object.
  514. // Memory for the string values is allocated using new. The
  515. // caller is responsible for freeing it.
  516. //
  517. // Arguments: [pdwType] -- The Volume Type property is returned here.
  518. // [ppwszEntryPath] -- EntryPath is returned here.
  519. // [ppwszShortPath] -- The 8.3 form of EntryPath is returned here
  520. // [ppwszComment] -- Comment is returned here.
  521. // [pGuid] -- The Guid (VolumeID) is returned here.
  522. // [pdwVolumeState] -- The volume state is returned here.
  523. // [pftPathTime] -- Time that EntryPath was last modified.
  524. // [pftStateTime] -- Time that Volume State was last modified.
  525. // [pftCommentTime] -- Time that Comment was last modified.
  526. //
  527. // Returns:
  528. //
  529. // History: 16-Sep-1992 SudK Imported from PART.CXX
  530. // 01-Jan-1996 Milans Ported to NT/SUR
  531. //
  532. //--------------------------------------------------------------------------
  533. DWORD
  534. CDfsVolume::GetIdProps(
  535. ULONG *pdwType,
  536. PWCHAR *ppwszEntryPath,
  537. PWCHAR *ppwszShortPath,
  538. PWCHAR *ppwszComment,
  539. GUID *pGuid,
  540. ULONG *pdwVolumeState,
  541. ULONG *pdwTimeout,
  542. FILETIME *pftPathTime,
  543. FILETIME *pftStateTime,
  544. FILETIME *pftCommentTime
  545. )
  546. {
  547. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetIdProps()\n"));
  548. DWORD dwErr = ERROR_SUCCESS;
  549. dwErr = _pStorage->GetIdProps(
  550. pdwType,
  551. pdwVolumeState,
  552. ppwszEntryPath,
  553. ppwszShortPath,
  554. pGuid,
  555. ppwszComment,
  556. pdwTimeout,
  557. pftPathTime,
  558. pftStateTime,
  559. pftCommentTime);
  560. if (dwErr != ERROR_SUCCESS) {
  561. IDfsVolInlineDebOut((
  562. DEB_ERROR, "Unable to read Id Props %08lx\n", dwErr));
  563. }
  564. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::GetIdProps() exit\n"));
  565. return( dwErr );
  566. }
  567. //+-------------------------------------------------------------------------
  568. //
  569. // Method: CDfsVolume::SetIdProps, private
  570. //
  571. // Synopsis: Exact opposite of GetIdProps function. A wrapper around the
  572. // property interface to set the appropriate properties that
  573. // identify a volume.
  574. //
  575. // Arguments:
  576. //
  577. // Returns:
  578. //
  579. // History: 16-Sep-1992 SudK Imported from PART.CXX
  580. //
  581. //--------------------------------------------------------------------------
  582. DWORD
  583. CDfsVolume::SetIdProps(
  584. ULONG Type,
  585. ULONG State,
  586. PWCHAR pwszPrefix,
  587. PWCHAR pwszShortPath,
  588. GUID & Guid,
  589. PWSTR pwszComment,
  590. ULONG Timeout,
  591. FILETIME ftPrefix,
  592. FILETIME ftState,
  593. FILETIME ftComment,
  594. BOOLEAN bCreate
  595. )
  596. {
  597. DWORD dwErr;
  598. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetIdProps()\n"));
  599. dwErr = _pStorage->SetIdProps(
  600. Type,
  601. State,
  602. pwszPrefix,
  603. pwszShortPath,
  604. Guid,
  605. pwszComment,
  606. Timeout,
  607. ftPrefix,
  608. ftState,
  609. ftComment);
  610. if (dwErr != ERROR_SUCCESS) {
  611. IDfsVolInlineDebOut(( DEB_ERROR,
  612. "Unable to Set IDProperties %08lx\n",
  613. dwErr));
  614. return(dwErr);
  615. }
  616. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetIdProps() exit\n"));
  617. return( dwErr );
  618. }
  619. //+----------------------------------------------------------------------------
  620. //
  621. // Function: CDfsVolume::SaveShortName
  622. //
  623. // Synopsis: Updates the short name for the volume entry path and saves it
  624. // to the registry.
  625. //
  626. // Arguments: None - the short name is picked up from the _peid private
  627. // member.
  628. //
  629. // Returns:
  630. //
  631. //-----------------------------------------------------------------------------
  632. DWORD
  633. CDfsVolume::SaveShortName()
  634. {
  635. DWORD dwErr;
  636. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetShortName()\n"));
  637. dwErr = SetIdProps(
  638. _EntryType,
  639. _State,
  640. _peid.Prefix.Buffer,
  641. _peid.ShortPrefix.Buffer,
  642. _peid.Uid,
  643. _pwszComment,
  644. _Timeout,
  645. _ftEntryPath,
  646. _ftState,
  647. _ftComment,
  648. FALSE);
  649. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::SetShortName() exit\n"));
  650. return( dwErr );
  651. }
  652. //+-------------------------------------------------------------------------
  653. //
  654. // Method: CDfsVolume::DeletePktEntry, private
  655. //
  656. // Synopsis: This method deletes an entry from the PKT. Given an ID to
  657. // identify the entry this method deletes the entry.
  658. //
  659. // Arguments: victim - The entryID that identifies the PKT entry to go.
  660. //
  661. // Returns:
  662. //
  663. // History: 24-Nov-1992 SudK Created.
  664. //
  665. //--------------------------------------------------------------------------
  666. DWORD
  667. CDfsVolume :: DeletePktEntry(
  668. PDFS_PKT_ENTRY_ID victim
  669. )
  670. {
  671. DWORD dwErr = ERROR_SUCCESS;
  672. NTSTATUS status = STATUS_SUCCESS;
  673. HANDLE pktHandle = NULL;
  674. IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::DeletePktEntry()\n"));
  675. //
  676. // Open the local PKT...
  677. //
  678. status = PktOpen(&pktHandle, 0, 0, NULL);
  679. if(NT_SUCCESS(status)) {
  680. status = PktDestroyEntry(
  681. pktHandle,
  682. *victim
  683. );
  684. PktClose(pktHandle);
  685. if (status == DFS_STATUS_NO_SUCH_ENTRY) {
  686. dwErr = ERROR_SUCCESS;
  687. } else if (!NT_SUCCESS(status)) {
  688. dwErr = RtlNtStatusToDosError(status);
  689. }
  690. } else {
  691. dwErr = RtlNtStatusToDosError(status);
  692. }
  693. IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::DeletePktEntry() exit\n"));
  694. return( dwErr );
  695. }
  696. //+-------------------------------------------------------------------------
  697. //
  698. // Method: CDfsVolume::CreateSubordinatePktEntry, private
  699. //
  700. // Synopsis: This method is basically an interface into the driver to be
  701. // able to manipulate the PKT. This creates an entry for the
  702. // current volume object and at the same time links it with its
  703. // superior volume object's PKT entry. This method makes one
  704. // assumption that no services are associated with the service.
  705. // It adds a NULL serviceList infact if the Boolean bWithService
  706. // is FALSE else it puts in the servicelist also.
  707. //
  708. // Arguments: [pSuperior] -- The Superior's EntryID info is passed here to
  709. // identify the superior in the PKT.
  710. // [bWithService] -- Whether to include the serviceinfo in EINFO.
  711. //
  712. // Returns:
  713. //
  714. // History: 22-Nov-1992 SudK Created
  715. //
  716. //--------------------------------------------------------------------------
  717. DWORD
  718. CDfsVolume::CreateSubordinatePktEntry(
  719. HANDLE pktHandle,
  720. PDFS_PKT_ENTRY_ID pSuperior,
  721. BOOLEAN bWithService)
  722. {
  723. ULONG etype = 0;
  724. DFS_PKT_ENTRY_INFO einfo;
  725. DWORD dwErr = ERROR_SUCCESS;
  726. NTSTATUS status = STATUS_SUCCESS;
  727. CDfsService *pDfsSvc = NULL;
  728. DFS_SERVICE *pService;
  729. ULONG count = 0;
  730. UNICODE_STRING ustrShortName;
  731. WCHAR ShortPrefix[MAX_PATH+1];
  732. BOOLEAN CloseHandle = FALSE;
  733. IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::CreateSubordinatePktEntry()\n"));
  734. //
  735. // We setup the servicelist based on the CreateDisposition.
  736. //
  737. if (!bWithService) {
  738. memset(&einfo, 0, sizeof(DFS_PKT_ENTRY_INFO));
  739. einfo.ServiceList = NULL;
  740. einfo.Timeout = _Timeout;
  741. } else {
  742. einfo.Timeout = _Timeout;
  743. count = _DfsSvcList.GetServiceCount();
  744. einfo.ServiceCount = count;
  745. einfo.ServiceList = new DFS_SERVICE[count];
  746. //447491, dont use null pointer.
  747. if (einfo.ServiceList == NULL) {
  748. dwErr = ERROR_OUTOFMEMORY;
  749. return dwErr;
  750. }
  751. memset(einfo.ServiceList, 0, sizeof(DFS_SERVICE)*count);
  752. pDfsSvc = _DfsSvcList.GetFirstService();
  753. pService = einfo.ServiceList;
  754. for (ULONG i=0; i<count; i++) {
  755. *pService = *(pDfsSvc->GetDfsService());
  756. pService++;
  757. pDfsmSites->LookupSiteInfo((pDfsSvc->GetReplicaInfo())->pwszServerName);
  758. pDfsSvc = _DfsSvcList.GetNextService(pDfsSvc);
  759. }
  760. }
  761. //
  762. // Note: We depend upon the correspondence of certain bits between the DFS
  763. // volume types and PKT entry types here.
  764. //
  765. #if (DFS_VOL_TYPE_ALL & (PKT_ENTRY_TYPE_LOCAL|PKT_ENTRY_TYPE_PERMANENT|PKT_ENTRY_TYPE_INUSE|PKT_ENTRY_TYPE_REFERRAL_SVC|PKT_ENTRY_TYPE_LOCAL_XPOINT))
  766. #error (DFS_VOL_TYPE_ALL & (PKT_ENTRY_TYPE_LOCAL|PKT_ENTRY_TYPE_PERMANENT|PKT_ENTRY_TYPE_INUSE|PKT_ENTRY_TYPE_REFERRAL_SVC|PKT_ENTRY_TYPE_LOCAL_XPOINT))
  767. #endif
  768. etype = _EntryType | PKT_ENTRY_TYPE_PERMANENT;
  769. //
  770. // If the handle supplied is NULL, open the local pkt
  771. //
  772. if (pktHandle == NULL) {
  773. status = PktOpen(&pktHandle, 0, 0, NULL);
  774. if (NT_SUCCESS(status))
  775. CloseHandle = TRUE;
  776. }
  777. if(NT_SUCCESS(status)) {
  778. #if DBG
  779. if (DfsSvcVerbose & 0x80000000) {
  780. WCHAR wszGuid[sizeof(GUID)*2+1];
  781. GuidToString(&_peid.Uid, wszGuid);
  782. DbgPrint("CDfsVolume::CreateSubordinatePktEntry:\n"
  783. "\tSupName=%ws\n"
  784. "\tPrefix=%ws\n"
  785. "\tShortPrefix=%ws\n"
  786. "\tType=0x%x\n"
  787. "\tCount=%d\n"
  788. "\tGUID=%ws\n",
  789. pSuperior->Prefix.Buffer,
  790. _peid.Prefix.Buffer,
  791. _peid.ShortPrefix.Buffer,
  792. _EntryType,
  793. einfo.ServiceCount,
  794. wszGuid);
  795. }
  796. #endif
  797. DfspCreateExitPoint(
  798. pktHandle,
  799. &_peid.Uid,
  800. _peid.Prefix.Buffer,
  801. _EntryType,
  802. sizeof(ShortPrefix),
  803. ShortPrefix);
  804. status = PktCreateSubordinateEntry(
  805. pktHandle,
  806. pSuperior,
  807. etype,
  808. &_peid,
  809. &einfo,
  810. PKT_ENTRY_SUPERSEDE);
  811. //
  812. // If we opened the handle, close it
  813. //
  814. if (CloseHandle == TRUE) {
  815. PktClose(pktHandle);
  816. pktHandle = NULL;
  817. }
  818. }
  819. if (!NT_SUCCESS(status)) {
  820. dwErr = RtlNtStatusToDosError(status);
  821. }
  822. //
  823. // Now before we leave we may have to delete the service list if we
  824. // allocated it.
  825. //
  826. delete [] einfo.ServiceList;
  827. IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::CreateSubordinatePktEntry() exit\n"));
  828. return( dwErr );
  829. }
  830. //+------------------------------------------------------------------------
  831. //
  832. // Method: CDfsVolume::UpdatePktEntry, public
  833. //
  834. // Synopsis: This method updates the PKT with all the info regarding this
  835. // volume. It however, does not bother about any kind of
  836. // Relational Info at all.
  837. //
  838. // Arguments: None
  839. //
  840. // Returns: ERROR_SUCCESS -- If all went well.
  841. //
  842. // Notes:
  843. //
  844. // History: 03-Feb-93 SudK Created.
  845. //
  846. //-------------------------------------------------------------------------
  847. DWORD
  848. CDfsVolume::UpdatePktEntry(
  849. HANDLE pktHandle)
  850. {
  851. DFS_PKT_ENTRY_INFO einfo;
  852. PDFS_SERVICE pService;
  853. CDfsService *pDfsSvc;
  854. DWORD dwErr = ERROR_SUCCESS;
  855. NTSTATUS status = STATUS_SUCCESS;
  856. ULONG EntryType, count;
  857. UNICODE_STRING ustrShortName;
  858. BOOLEAN CloseHandle = FALSE;
  859. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::UpdatePktEntry()\n"));
  860. #if DBG
  861. if (DfsSvcVerbose)
  862. DbgPrint("CDfsVolume::UpdatePktEntry()\n");
  863. #endif
  864. memset(&einfo, 0, sizeof(DFS_PKT_ENTRY_INFO));
  865. EntryType = _EntryType | PKT_ENTRY_TYPE_PERMANENT;
  866. //
  867. // Let us collect the service info now. Some memory allocation out here.
  868. //
  869. count = _DfsSvcList.GetServiceCount();
  870. einfo.Timeout = _Timeout;
  871. einfo.ServiceCount = count;
  872. einfo.ServiceList = new DFS_SERVICE[count];
  873. //447492, dont use null pointer.
  874. if (einfo.ServiceList == NULL) {
  875. dwErr = ERROR_OUTOFMEMORY;
  876. return dwErr;
  877. }
  878. memset(einfo.ServiceList, 0, sizeof(DFS_SERVICE)*count);
  879. pService = einfo.ServiceList;
  880. pDfsSvc = _DfsSvcList.GetFirstService();
  881. //
  882. // In this loop we merely do an assignment of all the services. The
  883. // conversion operator returns the DFS_SERVICE struct embedded in class.
  884. //
  885. for (ULONG i=0;i<count;i++) {
  886. *pService = *(pDfsSvc->GetDfsService());
  887. pService++;
  888. pDfsmSites->LookupSiteInfo((pDfsSvc->GetReplicaInfo())->pwszServerName);
  889. pDfsSvc = _DfsSvcList.GetNextService(pDfsSvc);
  890. }
  891. #if DBG
  892. if (DfsSvcVerbose) {
  893. WCHAR wszGuid[sizeof(GUID)*2+1];
  894. GuidToString(&_peid.Uid, wszGuid);
  895. DbgPrint("CDfsVolume::UpdatePktEntry\n"
  896. "\tPrefix=%ws\n"
  897. "\tShortPrefix=%ws\n"
  898. "\tType=0x%x\n"
  899. "\tCount=%d\n"
  900. "\tGUID=%ws\n",
  901. _peid.Prefix.Buffer,
  902. _peid.ShortPrefix.Buffer,
  903. _EntryType,
  904. einfo.ServiceCount,
  905. wszGuid);
  906. }
  907. #endif
  908. //
  909. // If we weren't given a handle, create one
  910. //
  911. if (pktHandle == NULL) {
  912. status = PktOpen(&pktHandle, 0, 0, NULL);
  913. if (NT_SUCCESS(status))
  914. CloseHandle = TRUE;
  915. }
  916. if (NT_SUCCESS(status)) {
  917. status = PktCreateEntry(
  918. pktHandle,
  919. EntryType,
  920. &_peid,
  921. &einfo,
  922. PKT_ENTRY_SUPERSEDE);
  923. if (CloseHandle == TRUE) {
  924. PktClose(pktHandle);
  925. pktHandle = NULL;
  926. }
  927. }
  928. if (!NT_SUCCESS(status)) {
  929. #if DBG
  930. if (DfsSvcVerbose)
  931. DbgPrint("PktCreateEntry returned 0x%x\n", status);
  932. #endif
  933. dwErr = RtlNtStatusToDosError(status);
  934. }
  935. delete [] einfo.ServiceList;
  936. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::UpdatePktEntry() exit %d\n", dwErr));
  937. #if DBG
  938. if (DfsSvcVerbose)
  939. DbgPrint("CDfsVolume::UpdatePktEntry() exit %d\n", dwErr);
  940. #endif
  941. //
  942. // Cant blindly return this error. This needs to be processed.
  943. //
  944. return(dwErr);
  945. }
  946. //+----------------------------------------------------------------------------
  947. //
  948. // Function: GuidToString
  949. //
  950. // Synopsis: Converts a GUID to a 32 char wchar null terminated string.
  951. //
  952. // Arguments: [pGuid] -- Pointer to Guid structure.
  953. // [pwszGuid] -- wchar buffer into which to put the string
  954. // representation of the GUID. Must be atleast
  955. // 2 * sizeof(GUID) + 1 long.
  956. //
  957. // Returns: Nothing
  958. //
  959. //-----------------------------------------------------------------------------
  960. const WCHAR rgwchHexDigits[] = L"0123456789ABCDEF";
  961. VOID GuidToString(
  962. IN GUID *pGuid,
  963. OUT PWSTR pwszGuid)
  964. {
  965. PBYTE pbBuffer = (PBYTE) pGuid;
  966. USHORT i;
  967. for(i = 0; i < sizeof(GUID); i++) {
  968. pwszGuid[2 * i] = rgwchHexDigits[(pbBuffer[i] >> 4) & 0xF];
  969. pwszGuid[2 * i + 1] = rgwchHexDigits[pbBuffer[i] & 0xF];
  970. }
  971. pwszGuid[2 * i] = UNICODE_NULL;
  972. }
  973. //+-------------------------------------------------------------------------
  974. //
  975. // Method: CDfsVolume::CreateChildPartition, private
  976. //
  977. // Synopsis: This is somewhat of a wrapper around the IStorage interface.
  978. // It merely creates a new volume object and associates the
  979. // properties passed in with the Volume Object. We use the
  980. // IStorage interface for this purpose.
  981. // This method generates a GUID and uses that. It also sets
  982. // a NULL service list and Initial State on the volume object.
  983. //
  984. // Arguments: [Name] -- Child Volume Object's name.
  985. // [Type] -- Type of this volume object.
  986. // [EntryPath] -- Dfs prefix of child volume.
  987. // [pwszComment] -- Comment associated with this new volume
  988. // [pUid] -- Optional guid of child volume
  989. // [pReplInfo] -- Info regarding the server\share supporting volume
  990. // [NewIDfsVol] -- On successful return, pointer to new child
  991. // volume object is returned here.
  992. //
  993. // Returns:
  994. //
  995. // Notes: This Method creates a GUID and uses it. It also sets a default
  996. // state on the volume object and associates a NULL serviceList.
  997. //
  998. // History: 16-Sep-1992 SudK Imported from PART.CXX
  999. //
  1000. //--------------------------------------------------------------------------
  1001. DWORD
  1002. CDfsVolume::CreateChildPartition(
  1003. PWCHAR Name,
  1004. ULONG Type,
  1005. PWCHAR EntryPath,
  1006. PWCHAR pwszComment,
  1007. GUID *pUid,
  1008. PDFS_REPLICA_INFO pReplInfo,
  1009. CDfsVolume **NewIDfsVol
  1010. )
  1011. {
  1012. DWORD dwErr = ERROR_SUCCESS;
  1013. CDfsVolume *pDfsVol;
  1014. PWSTR pwszChildName;
  1015. CDfsService *pService;
  1016. WCHAR wszChildElement[sizeof(GUID)*2+1];
  1017. GUID Uid, *pVolId;
  1018. PWCHAR pwszChild;
  1019. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateChildPartition(%ws)\n", Name));
  1020. if (Name == NULL) {
  1021. //
  1022. // Get a guid first.
  1023. //
  1024. dwErr = UuidCreate(&Uid);
  1025. if (dwErr != ERROR_SUCCESS) {
  1026. IDfsVolInlineDebOut((DEB_ERROR, "UuidCreate failed %08lx\n", dwErr));
  1027. return(dwErr);
  1028. }
  1029. //
  1030. // Now figure out the last element of the child name from the GUID.
  1031. //
  1032. GuidToString(&Uid, wszChildElement);
  1033. pwszChild = wszChildElement;
  1034. pVolId = pUid == NULL ? &Uid : pUid;
  1035. } else {
  1036. pwszChild = Name;
  1037. pVolId = pUid;
  1038. }
  1039. //
  1040. // Now compose the full name of the child object.
  1041. //
  1042. pwszChildName = new WCHAR[wcslen(_pwzFileName)+wcslen(pwszChild)+2];
  1043. if (pwszChildName == NULL) {
  1044. *NewIDfsVol = NULL;
  1045. dwErr = ERROR_OUTOFMEMORY;
  1046. return dwErr;
  1047. }
  1048. wcscpy(pwszChildName, _pwzFileName);
  1049. wcscat(pwszChildName, L"\\");
  1050. wcscat(pwszChildName, pwszChild);
  1051. //
  1052. // Let us now instantiate a new instance of CDfsVolume and then we will
  1053. // initialise it with the appropriate Name.
  1054. //
  1055. pDfsVol = new CDfsVolume();
  1056. if (pDfsVol != NULL) {
  1057. dwErr = pDfsVol->CreateObject( pwszChildName,
  1058. EntryPath,
  1059. Type,
  1060. pReplInfo,
  1061. pwszComment,
  1062. pVolId);
  1063. //
  1064. // We set up recovery properties of creation here though this is also used
  1065. // by Move operation. This is OK however.
  1066. //
  1067. if (dwErr == ERROR_SUCCESS) {
  1068. dwErr = pDfsVol->_Recover.SetOperationStart( DFS_RECOVERY_STATE_CREATING, NULL);
  1069. if (dwErr == ERROR_SUCCESS) {
  1070. *NewIDfsVol = pDfsVol;
  1071. //
  1072. // Create object merely creates the object. We now need to call
  1073. // initPktSvc on the service inside the serviceList.
  1074. //
  1075. pService = pDfsVol->_DfsSvcList.GetFirstService();
  1076. ASSERT(((pService==NULL) && (pReplInfo==NULL)) ||
  1077. ((pService!=NULL) && (pReplInfo!=NULL)));
  1078. if (pService != NULL)
  1079. pService->InitializePktSvc();
  1080. }
  1081. else {
  1082. pDfsVol->Release();
  1083. *NewIDfsVol = NULL;
  1084. }
  1085. } else {
  1086. pDfsVol->Release();
  1087. *NewIDfsVol = NULL;
  1088. }
  1089. } else {
  1090. *NewIDfsVol = NULL;
  1091. dwErr = ERROR_OUTOFMEMORY;
  1092. }
  1093. delete [] pwszChildName;
  1094. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::CreateChildPartition() exit\n"));
  1095. return(dwErr);
  1096. }
  1097. //+----------------------------------------------------------------------------
  1098. //
  1099. // Function: CDfsVolume::IsValidChildName,private
  1100. //
  1101. // Synopsis: Determines whether a prefix is a valid child prefix for this
  1102. // volume (ie, is hierarchically subordinate and there is no
  1103. // conflicting child.
  1104. //
  1105. // Arguments: [pwszChildPrefix] -- The prefix to test.
  1106. // [pidChild] -- The volume id of the proposed child volume.
  1107. //
  1108. // Returns: TRUE if the child prefix is legal, FALSE otherwise
  1109. //
  1110. //-----------------------------------------------------------------------------
  1111. BOOL CDfsVolume::IsValidChildName(
  1112. PWCHAR pwszChildPrefix,
  1113. GUID *pidChild)
  1114. {
  1115. NTSTATUS Status;
  1116. Status = PktIsChildnameLegal(
  1117. _peid.Prefix.Buffer,
  1118. pwszChildPrefix,
  1119. pidChild);
  1120. return( (BOOL) (Status == STATUS_SUCCESS) );
  1121. }
  1122. //+-------------------------------------------------------------------------
  1123. //
  1124. // Method: CDfsVolume::NotLeafVolume, private
  1125. //
  1126. // Synopsis: Uses IStorage to find if child exists.
  1127. //
  1128. // Arguments:None
  1129. //
  1130. // Returns: TRUE if NotLeafVolume else FALSE.
  1131. //
  1132. // History: 18-May-1993 SudK Created.
  1133. //
  1134. //--------------------------------------------------------------------------
  1135. BOOL
  1136. CDfsVolume::NotLeafVolume(void)
  1137. {
  1138. ULONG fetched = 0;
  1139. CEnumDirectory *pdir;
  1140. DFSMSTATDIR rgelt;
  1141. DWORD dwErr;
  1142. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::NotLeafVolume()\n"));
  1143. ASSERT(!(VolumeDeleted()));
  1144. memset(&rgelt, 0, sizeof(DFSMSTATDIR));
  1145. //
  1146. // First, we get a hold of the IDirectory interface to our own volume
  1147. // object.
  1148. //
  1149. dwErr = _pStorage->GetEnumDirectory(&pdir);
  1150. if (dwErr != ERROR_SUCCESS) {
  1151. IDfsVolInlineDebOut((DEB_ERROR, "Failed to get IDirectory %08lx\n", dwErr));
  1152. return(FALSE);
  1153. }
  1154. //
  1155. // While there are children still to be handled we continue on.
  1156. //
  1157. while (TRUE) {
  1158. if (rgelt.pwcsName != NULL) {
  1159. delete [] rgelt.pwcsName;
  1160. rgelt.pwcsName = NULL;
  1161. }
  1162. dwErr = pdir->Next(&rgelt, &fetched);
  1163. //
  1164. // Will we get an error if there are no more children.
  1165. //
  1166. if (dwErr != ERROR_SUCCESS) {
  1167. IDfsVolInlineDebOut((DEB_ERROR, "Failed to Enumeraate %08lx\n",dwErr));
  1168. pdir->Release();
  1169. return(FALSE);
  1170. }
  1171. //
  1172. // If we did not get back any children we are done.
  1173. //
  1174. if (fetched == 0) {
  1175. IDfsVolInlineDebOut((DEB_TRACE, "No Children Found\n",0));
  1176. pdir->Release();
  1177. return(FALSE);
  1178. }
  1179. //
  1180. // If the child is . or .. we look for next child.
  1181. //
  1182. ULONG cbLen = wcslen(rgelt.pwcsName);
  1183. if (cbLen < sizeof(L"..")/sizeof(WCHAR))
  1184. continue;
  1185. //
  1186. // If we got here it means that we came across a volume object
  1187. // and we have to return TRUE now.
  1188. //
  1189. IDfsVolInlineDebOut((DEB_ERROR, "Child Found - NotLeafVolume %ws\n",
  1190. rgelt.pwcsName));
  1191. pdir->Release();
  1192. delete [] rgelt.pwcsName;
  1193. return(TRUE);
  1194. }
  1195. IDfsVolInlineDebOut((DEB_TRACE, "CDfsVolume::NotLeafVolume() exit\n"));
  1196. }
  1197. //+----------------------------------------------------------------------------
  1198. //
  1199. // Function: CDfsVolume::IsValidService
  1200. //
  1201. // Synopsis: Given a server name, indicates whether the server is a valid
  1202. // server for this volume.
  1203. //
  1204. // Arguments: [pwszServer] -- Name of server to verify.
  1205. //
  1206. // Returns: TRUE if server is a valid server for this volume, FALSE
  1207. // otherwise
  1208. //
  1209. //-----------------------------------------------------------------------------
  1210. BOOLEAN
  1211. CDfsVolume::IsValidService(
  1212. IN LPWSTR pwszServer)
  1213. {
  1214. DWORD dwErr;
  1215. CDfsService *pSvc;
  1216. dwErr = _DfsSvcList.GetServiceFromPrincipalName( pwszServer, &pSvc );
  1217. return( dwErr == ERROR_SUCCESS );
  1218. }
  1219. //+-------------------------------------------------------------------------
  1220. //
  1221. // Method: DeallocateCacheRelationInfo, private
  1222. //
  1223. // Synopsis: This function is used to deallocate relationInfo structures
  1224. // that were allocated by GetPktCacheRelationInfo.
  1225. //
  1226. // Arguments: RelationInfo - The relationInfo struct to deallocate.
  1227. //
  1228. // Returns:
  1229. //
  1230. // History: 24-Nov-1992 SudK Created.
  1231. //
  1232. //--------------------------------------------------------------------------
  1233. VOID
  1234. DeallocateCacheRelationInfo(
  1235. DFS_PKT_RELATION_INFO & RelationInfo
  1236. )
  1237. {
  1238. PDFS_PKT_ENTRY_ID peid = &RelationInfo.EntryId;
  1239. IDfsVolInlineDebOut((DEB_TRACE, "Dfsm::DeallocateCacheRelationInfo()\n"));
  1240. MarshalBufferFree(peid->Prefix.Buffer);
  1241. peid->Prefix.Buffer = NULL;
  1242. if (peid->ShortPrefix.Buffer) {
  1243. MarshalBufferFree(peid->ShortPrefix.Buffer);
  1244. peid->ShortPrefix.Buffer = NULL;
  1245. }
  1246. if(peid = RelationInfo.SubordinateIdList)
  1247. {
  1248. for(ULONG i = 0; i < RelationInfo.SubordinateIdCount; i++)
  1249. {
  1250. MarshalBufferFree(peid[i].Prefix.Buffer);
  1251. peid[i].Prefix.Buffer = NULL;
  1252. if (peid[i].ShortPrefix.Buffer != NULL) {
  1253. MarshalBufferFree(peid[i].ShortPrefix.Buffer);
  1254. peid[i].ShortPrefix.Buffer = NULL;
  1255. }
  1256. }
  1257. MarshalBufferFree(RelationInfo.SubordinateIdList);
  1258. RelationInfo.SubordinateIdList = NULL;
  1259. }
  1260. IDfsVolInlineDebOut((DEB_TRACE, "Dfsm::DeallocateCacheRelationInfo() exit\n"));
  1261. }
  1262. //+-------------------------------------------------------------------------
  1263. //
  1264. // Method: GetPktCacheRelationInfo, private
  1265. //
  1266. // Synopsis: This method retrieves the relational information regarding
  1267. // a particular volume (identified by the ENTRY_ID props)
  1268. // passed in to it.
  1269. //
  1270. // Arguments: [RelationInfo] -- The relational info is returned here.
  1271. // [peid] -- The EntryID is passed in here.
  1272. //
  1273. // Returns:
  1274. //
  1275. // History: 24-Nov-1992 SudK Created.
  1276. //
  1277. //--------------------------------------------------------------------------
  1278. DWORD
  1279. GetPktCacheRelationInfo(
  1280. PDFS_PKT_ENTRY_ID peid,
  1281. PDFS_PKT_RELATION_INFO RelationInfo
  1282. )
  1283. {
  1284. //
  1285. // Initialize all return values to be NULL...
  1286. //
  1287. HANDLE pktHandle;
  1288. DWORD dwErr = ERROR_SUCCESS;
  1289. NTSTATUS status;
  1290. memset(RelationInfo, 0, sizeof(DFS_PKT_RELATION_INFO));
  1291. IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::GetPktCacheRelationInfo()\n"));
  1292. status = PktOpen(&pktHandle, 0, 0, NULL);
  1293. if (NT_SUCCESS(status))
  1294. {
  1295. //
  1296. // Create/Update the Entry...
  1297. //
  1298. status = PktGetRelationInfo(
  1299. pktHandle,
  1300. peid,
  1301. RelationInfo
  1302. );
  1303. PktClose(pktHandle);
  1304. pktHandle = NULL;
  1305. };
  1306. if (!NT_SUCCESS(status))
  1307. dwErr = RtlNtStatusToDosError(status);
  1308. else
  1309. dwErr = ERROR_SUCCESS;
  1310. if (dwErr != ERROR_SUCCESS) {
  1311. IDfsVolInlineDebOut((DEB_ERROR, "Failed GetRelationInfo %08lx\n",dwErr));
  1312. }
  1313. IDfsVolInlineDebOut((DEB_TRACE, "IDfsVol::GetPktCacheRelationInfo() exit\n"));
  1314. return( dwErr );
  1315. }
  1316. NTSTATUS
  1317. DfspCreateExitPoint (
  1318. IN HANDLE DriverHandle,
  1319. IN LPGUID Uid,
  1320. IN LPWSTR Prefix,
  1321. IN ULONG Type,
  1322. IN ULONG Len,
  1323. OUT LPWSTR ShortPrefix)
  1324. {
  1325. NTSTATUS NtStatus;
  1326. IO_STATUS_BLOCK IoStatusBlock;
  1327. PDFS_CREATE_EXIT_POINT_ARG CreateArg;
  1328. ULONG Size = sizeof(*CreateArg);
  1329. PCHAR pWc;
  1330. if (Uid == NULL || Prefix == NULL) {
  1331. NtStatus = STATUS_INVALID_PARAMETER;
  1332. DFSM_TRACE_HIGH(ERROR, DfspCreateExitPoint_Error1,
  1333. LOGSTATUS(NtStatus)
  1334. LOGWSTR(Prefix));
  1335. goto ExitWithStatus;
  1336. }
  1337. #if DBG
  1338. if (DfsSvcVerbose & 0x80000000) {
  1339. WCHAR wszGuid[sizeof(GUID)*2+1];
  1340. GuidToString(Uid, wszGuid);
  1341. DbgPrint("DfspCreateExitPoint(%ws,%ws,0x%x)\n",
  1342. wszGuid,
  1343. Prefix,
  1344. Type);
  1345. }
  1346. #endif
  1347. //
  1348. // Pack the args into a single buffer that can be sent to
  1349. // the dfs driver:
  1350. //
  1351. //
  1352. // First find the size...
  1353. //
  1354. if (Prefix != NULL) {
  1355. Size += (wcslen(Prefix) + 1) * sizeof(WCHAR);
  1356. }
  1357. //
  1358. // Now allocate the memory
  1359. //
  1360. CreateArg = (PDFS_CREATE_EXIT_POINT_ARG)malloc(Size);
  1361. if (CreateArg == NULL) {
  1362. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1363. DFSM_TRACE_HIGH(ERROR, DfspCreateExitPoint_Error2,
  1364. LOGSTATUS(NtStatus)
  1365. LOGWSTR(Prefix));
  1366. goto ExitWithStatus;
  1367. }
  1368. RtlZeroMemory(CreateArg, Size);
  1369. //
  1370. // Put the fixed parameters into the buffer
  1371. //
  1372. CreateArg->Uid = *Uid;
  1373. CreateArg->Type = Type;
  1374. //
  1375. // Put the variable data in the buffer
  1376. //
  1377. pWc = (PCHAR)(CreateArg + 1);
  1378. CreateArg->Prefix = (LPWSTR)pWc;
  1379. RtlCopyMemory(CreateArg->Prefix, Prefix, wcslen(Prefix)*sizeof(WCHAR));
  1380. LPWSTR_TO_OFFSET(CreateArg->Prefix, CreateArg);
  1381. //
  1382. // Tell the driver!!
  1383. //
  1384. NtStatus = NtFsControlFile(
  1385. DriverHandle,
  1386. NULL, // Event,
  1387. NULL, // ApcRoutine,
  1388. NULL, // ApcContext,
  1389. &IoStatusBlock,
  1390. FSCTL_DFS_CREATE_EXIT_POINT,
  1391. CreateArg,
  1392. Size,
  1393. ShortPrefix,
  1394. Len);
  1395. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfspCreateExitPoint_Error_NtFsControlFile,
  1396. LOGSTATUS(NtStatus)
  1397. LOGWSTR(Prefix));
  1398. free(CreateArg);
  1399. ExitWithStatus:
  1400. #if DBG
  1401. if (DfsSvcVerbose & 0x80000000)
  1402. DbgPrint("DfspCreateExitPoint exit 0x%x\n", NtStatus);
  1403. #endif
  1404. return NtStatus;
  1405. }
  1406. NTSTATUS
  1407. DfspDeleteExitPoint (
  1408. IN HANDLE DriverHandle,
  1409. IN LPGUID Uid,
  1410. IN LPWSTR Prefix,
  1411. IN ULONG Type)
  1412. {
  1413. NTSTATUS NtStatus;
  1414. IO_STATUS_BLOCK IoStatusBlock;
  1415. PDFS_DELETE_EXIT_POINT_ARG DeleteArg;
  1416. ULONG Size = sizeof(*DeleteArg);
  1417. PCHAR pWc;
  1418. if (Uid == NULL || Prefix == NULL) {
  1419. NtStatus = STATUS_INVALID_PARAMETER;
  1420. DFSM_TRACE_HIGH(ERROR, DfspDeleteExitPoint_Error1,
  1421. LOGSTATUS(NtStatus)
  1422. LOGWSTR(Prefix));
  1423. goto ExitWithStatus;
  1424. }
  1425. #if DBG
  1426. if (DfsSvcVerbose & 0x80000000) {
  1427. WCHAR wszGuid[sizeof(GUID)*2+1];
  1428. GuidToString(Uid, wszGuid);
  1429. DbgPrint("DfspDeleteExitPoint(%ws,%ws,0x%x)\n",
  1430. wszGuid,
  1431. Prefix,
  1432. Type);
  1433. }
  1434. #endif
  1435. //
  1436. // Pack the args into a single buffer that can be sent to
  1437. // the dfs driver:
  1438. //
  1439. //
  1440. // First find the size...
  1441. //
  1442. if (Prefix != NULL) {
  1443. Size += (wcslen(Prefix) + 1) * sizeof(WCHAR);
  1444. }
  1445. //
  1446. // Now allocate the memory
  1447. //
  1448. DeleteArg = (PDFS_DELETE_EXIT_POINT_ARG)malloc(Size);
  1449. if (DeleteArg == NULL) {
  1450. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1451. DFSM_TRACE_HIGH(ERROR, DfspDeleteExitPoint_Error2,
  1452. LOGSTATUS(NtStatus)
  1453. LOGWSTR(Prefix));
  1454. goto ExitWithStatus;
  1455. }
  1456. RtlZeroMemory(DeleteArg, Size);
  1457. //
  1458. // Put the fixed parameters into the buffer
  1459. //
  1460. DeleteArg->Uid = *Uid;
  1461. DeleteArg->Type = Type;
  1462. //
  1463. // Put the variable data in the buffer
  1464. //
  1465. pWc = (PCHAR)(DeleteArg + 1);
  1466. DeleteArg->Prefix = (LPWSTR)pWc;
  1467. RtlCopyMemory(DeleteArg->Prefix, Prefix, wcslen(Prefix)*sizeof(WCHAR));
  1468. LPWSTR_TO_OFFSET(DeleteArg->Prefix, DeleteArg);
  1469. //
  1470. // Tell the driver!!
  1471. //
  1472. NtStatus = NtFsControlFile(
  1473. DriverHandle,
  1474. NULL, // Event,
  1475. NULL, // ApcRoutine,
  1476. NULL, // ApcContext,
  1477. &IoStatusBlock,
  1478. FSCTL_DFS_DELETE_EXIT_POINT,
  1479. DeleteArg,
  1480. Size,
  1481. NULL,
  1482. 0);
  1483. DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfspDeleteExitPoint_Error_NtFsControlFile,
  1484. LOGSTATUS(NtStatus)
  1485. LOGWSTR(Prefix));
  1486. free(DeleteArg);
  1487. ExitWithStatus:
  1488. #if DBG
  1489. if (DfsSvcVerbose & 0x80000000)
  1490. DbgPrint("DfspDeleteExitPoint exit 0x%x\n", NtStatus);
  1491. #endif
  1492. return NtStatus;
  1493. }