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.

876 lines
24 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1995, Microsoft Corporation
  4. //
  5. // File: dcfsctl.c
  6. //
  7. // Contents: This file has all the fsctrl routines that typically execute
  8. // on a DC.
  9. //
  10. // Classes:
  11. //
  12. // Functions: DfsFsctrlDCSetVolumeState -
  13. // DfsFsctrlDCSetVolumeState -
  14. // DfsFsctrlSetServiceState -
  15. // DfsFsctrlGetServerInfo -
  16. // DfsFsctrlCheckStgIdInUse -
  17. //
  18. // DfspGetServerConfigInfo -
  19. // IsPathAPrefixOf -
  20. //
  21. //
  22. // History: April 5, 1995 Milans created
  23. //
  24. //-----------------------------------------------------------------------------
  25. #include "dfsprocs.h"
  26. #include <dfserr.h>
  27. #include <netevent.h>
  28. #include "fsctrl.h"
  29. #include "log.h"
  30. NTSTATUS
  31. DfspGetServerConfigInfo(
  32. IN GUID *pMachine,
  33. IN PDFS_PKT pPkt,
  34. IN PDFS_PKT_ENTRY pPktEntry,
  35. OUT PDFS_LOCAL_VOLUME_CONFIG pConfigInfo);
  36. BOOLEAN
  37. IsPathAPrefixOf(
  38. IN PUNICODE_STRING pustrPath1,
  39. IN PUNICODE_STRING pustrPath2);
  40. #pragma alloc_text( PAGE, DfsFsctrlDCSetVolumeState )
  41. #pragma alloc_text( PAGE, DfsFsctrlSetVolumeTimeout )
  42. #pragma alloc_text( PAGE, DfsFsctrlSetServiceState )
  43. #pragma alloc_text( PAGE, DfsFsctrlGetServerInfo )
  44. #pragma alloc_text( PAGE, DfsFsctrlCheckStgIdInUse )
  45. #pragma alloc_text( PAGE, DfspGetServerConfigInfo )
  46. #pragma alloc_text( PAGE, IsPathAPrefixOf )
  47. #define Dbg (DEBUG_TRACE_LOCALVOL)
  48. //+----------------------------------------------------------------------------
  49. //
  50. // Function: DfsFsctrlDCSetVolumeState, public
  51. //
  52. // Synopsis: Marks the specified replica offline for the particular volume
  53. //
  54. // Arguments: [Irp]
  55. //
  56. // [InputBuffer] -- Marshalled DFS_SETSTATE_ARG structure
  57. // that specifies the volume and the state to set it to.
  58. //
  59. // [InputBufferLength] -- Length in bytes of InputBuffer
  60. //
  61. // Returns: [STATUS_SUCCESS] -- The specified replica was set
  62. // online/offline as speficied.
  63. //
  64. // [DFS_STATUS_NO_SUCH_ENTRY] -- The specified volume was not
  65. // found.
  66. //
  67. // [STATUS_DATA_ERROR] -- The InputBuffer could not be
  68. // correctly unmarshalled.
  69. //
  70. // [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory situation.
  71. //
  72. //-----------------------------------------------------------------------------
  73. NTSTATUS
  74. DfsFsctrlDCSetVolumeState(
  75. IN PIRP Irp,
  76. IN PVOID InputBuffer,
  77. IN ULONG InputBufferLength)
  78. {
  79. NTSTATUS status;
  80. MARSHAL_BUFFER marshalBuffer;
  81. DFS_SETSTATE_ARG setStateArg;
  82. PDFS_PKT pkt;
  83. PDFS_PKT_ENTRY pktEntry;
  84. STD_FSCTRL_PROLOGUE(DfsFsctrlDCSetVolumeState, TRUE, FALSE);
  85. MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
  86. status = DfsRtlGet(
  87. &marshalBuffer,
  88. &MiSetStateArg,
  89. &setStateArg);
  90. if (NT_SUCCESS(status)) {
  91. DebugTrace(
  92. 0, Dbg, "Setting volume state for %[wZ]\n",
  93. &setStateArg.Id.Prefix);
  94. pkt = _GetPkt();
  95. PktAcquireShared( pkt, TRUE );
  96. pktEntry = PktLookupEntryById( pkt, &setStateArg.Id );
  97. if (pktEntry != NULL) {
  98. if (setStateArg.Type == PKT_ENTRY_TYPE_OFFLINE) {
  99. pktEntry->Type |= PKT_ENTRY_TYPE_OFFLINE;
  100. } else {
  101. pktEntry->Type &= ~PKT_ENTRY_TYPE_OFFLINE;
  102. }
  103. status = STATUS_SUCCESS;
  104. } else {
  105. DebugTrace(0, Dbg, "Unable to find PKT Entry!\n", 0);
  106. status = DFS_STATUS_NO_SUCH_ENTRY;
  107. }
  108. PktRelease( pkt );
  109. PktEntryIdDestroy(&setStateArg.Id, FALSE);
  110. }
  111. DebugTrace(-1, Dbg, "DfsFsctrlDCSetVolumeState: Exit %08lx\n", ULongToPtr( status ));
  112. DfsCompleteRequest( Irp, status );
  113. return( status );
  114. }
  115. //+----------------------------------------------------------------------------
  116. //
  117. // Function: DfsFsctrlSetServiceState, public
  118. //
  119. // Synopsis: Marks the specified replica offline for the particular volume
  120. //
  121. // Arguments: [Irp]
  122. //
  123. // [InputBuffer] -- Marshalled DFS_DC_SET_REPLICA_STATE structure
  124. // that specifies the volume and the replica to be set
  125. // offline/online.
  126. //
  127. // [InputBufferLength] -- Length in bytes of InputBuffer
  128. //
  129. // Returns: [STATUS_SUCCESS] -- The specified replica was set
  130. // online/offline as speficied.
  131. //
  132. // [DFS_STATUS_NO_SUCH_ENTRY] -- The specified volume was not
  133. // found, or the specified replica is not a server for
  134. // the volume.
  135. //
  136. // [STATUS_DATA_ERROR] -- The InputBuffer could not be
  137. // correctly unmarshalled.
  138. //
  139. // [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory situation.
  140. //
  141. //-----------------------------------------------------------------------------
  142. NTSTATUS
  143. DfsFsctrlSetServiceState(
  144. IN PIRP Irp,
  145. IN PVOID InputBuffer,
  146. IN ULONG InputBufferLength)
  147. {
  148. NTSTATUS status;
  149. MARSHAL_BUFFER marshalBuffer;
  150. DFS_DC_SET_SERVICE_STATE setSvcState;
  151. PDFS_PKT pkt;
  152. PDFS_PKT_ENTRY pktEntry;
  153. STD_FSCTRL_PROLOGUE(DfsFsctrlSetServiceState, TRUE, FALSE);
  154. MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
  155. status = DfsRtlGet(
  156. &marshalBuffer,
  157. &MiDCSetServiceState,
  158. &setSvcState);
  159. if (NT_SUCCESS(status)) {
  160. DebugTrace(
  161. 0, Dbg, "Setting service state for [%wZ]\n",
  162. &setSvcState.Id.Prefix);
  163. DebugTrace(
  164. 0, Dbg, "For Service [%wZ]\n", &setSvcState.ServiceName);
  165. pkt = _GetPkt();
  166. PktAcquireShared( pkt, TRUE );
  167. pktEntry = PktLookupEntryById( pkt, &setSvcState.Id );
  168. if (pktEntry != NULL) {
  169. PDFS_SERVICE pSvc;
  170. ULONG i, cSvc;
  171. status = DFS_STATUS_NO_SUCH_ENTRY;
  172. for (i = 0, cSvc = pktEntry->Info.ServiceCount;
  173. i < cSvc && status != STATUS_SUCCESS;
  174. i++) {
  175. pSvc = &pktEntry->Info.ServiceList[i];
  176. if (RtlEqualUnicodeString(
  177. &setSvcState.ServiceName, &pSvc->Name, TRUE)) {
  178. DebugTrace(0, Dbg, "Found Svc @ %08lx\n", pSvc );
  179. if (setSvcState.State == DFS_SERVICE_TYPE_OFFLINE) {
  180. pSvc->Type |= DFS_SERVICE_TYPE_OFFLINE;
  181. } else {
  182. pSvc->Type &= ~DFS_SERVICE_TYPE_OFFLINE;
  183. }
  184. status = STATUS_SUCCESS;
  185. }
  186. } // For each service
  187. } else {
  188. DebugTrace(0, Dbg, "Unable to find PKT Entry!\n", 0);
  189. status = DFS_STATUS_NO_SUCH_ENTRY;
  190. }
  191. PktRelease( pkt );
  192. //
  193. // Free up the unmarshalled arguments
  194. //
  195. PktEntryIdDestroy(&setSvcState.Id, FALSE);
  196. MarshalBufferFree( setSvcState.ServiceName.Buffer );
  197. }
  198. DebugTrace(-1, Dbg, "DfsFsctrlSetServiceState: Exit %08lx\n", ULongToPtr( status ));
  199. DfsCompleteRequest( Irp, status );
  200. return( status );
  201. }
  202. //+----------------------------------------------------------------------------
  203. //
  204. // Function: DfsFsctrlSetVolumeTimeout, public
  205. //
  206. // Synopsis: Sets the specified volume's referral timeout
  207. //
  208. // Arguments: [Irp]
  209. //
  210. // [InputBuffer] -- Marshalled DFS_SET_VOLUME_TIMEOUT_ARG structure
  211. // that specifies the volume and the timeout to associate
  212. // with the volume.
  213. //
  214. // [InputBufferLength] -- Length in bytes of InputBuffer
  215. //
  216. // Returns: [STATUS_SUCCESS] -- The specified timeout was set.
  217. //
  218. // [DFS_STATUS_NO_SUCH_ENTRY] -- The specified volume was not
  219. // found.
  220. //
  221. // [STATUS_DATA_ERROR] -- The InputBuffer could not be
  222. // correctly unmarshalled.
  223. //
  224. // [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory situation.
  225. //
  226. //-----------------------------------------------------------------------------
  227. NTSTATUS
  228. DfsFsctrlSetVolumeTimeout(
  229. IN PIRP Irp,
  230. IN PVOID InputBuffer,
  231. IN ULONG InputBufferLength)
  232. {
  233. NTSTATUS status;
  234. MARSHAL_BUFFER marshalBuffer;
  235. DFS_SET_VOLUME_TIMEOUT_ARG setVolTimeoutArg;
  236. PDFS_PKT pkt;
  237. PDFS_PKT_ENTRY pktEntry;
  238. STD_FSCTRL_PROLOGUE(DfsFsctrlSetVolumeTimeout, TRUE, FALSE);
  239. MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
  240. status = DfsRtlGet(
  241. &marshalBuffer,
  242. &MiSetVolTimeoutArg,
  243. &setVolTimeoutArg);
  244. if (NT_SUCCESS(status)) {
  245. DebugTrace(
  246. 0, Dbg, "Setting volume timeout for %[wZ]\n",
  247. &setVolTimeoutArg.Id.Prefix);
  248. pkt = _GetPkt();
  249. PktAcquireShared( pkt, TRUE );
  250. pktEntry = PktLookupEntryById( pkt, &setVolTimeoutArg.Id );
  251. if (pktEntry != NULL) {
  252. pktEntry->Info.Timeout = setVolTimeoutArg.Timeout;
  253. status = STATUS_SUCCESS;
  254. } else {
  255. DebugTrace(0, Dbg, "Unable to find PKT Entry!\n", 0);
  256. status = DFS_STATUS_NO_SUCH_ENTRY;
  257. }
  258. PktRelease( pkt );
  259. //
  260. // Free the unmarshalled input arguments
  261. //
  262. PktEntryIdDestroy(&setVolTimeoutArg.Id, FALSE);
  263. }
  264. DebugTrace(-1, Dbg, "DfsFsctrlSetVolumeTimeout: Exit %08lx\n", ULongToPtr( status ));
  265. DfsCompleteRequest( Irp, status );
  266. return( status );
  267. }
  268. //+----------------------------------------------------------------------------
  269. //
  270. // Function: DfsFsctrlGetServerInfo
  271. //
  272. // Synopsis: Given the machine guid of a server, this routine will return
  273. // the entire local volume knowledge that a dfs server should
  274. // have. This routine is intended to be called on the DC only.
  275. //
  276. // Arguments:
  277. //
  278. // Returns: [STATUS_SUCCESS] -- The info is successfully returned.
  279. //
  280. // [STATUS_BUFFER_OVERFLOW] -- The output buffer is too small.
  281. // The needed size is returned in the first 4 bytes of
  282. // this buffer.
  283. //
  284. // [STATUS_DATA_ERROR] -- The input buffer could not be
  285. // unmarshalled
  286. //
  287. // [STATUS_BUFFER_TOO_SMALL] -- The output buffer is < 4 bytes.
  288. //
  289. // [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition
  290. //
  291. //-----------------------------------------------------------------------------
  292. NTSTATUS
  293. DfsFsctrlGetServerInfo(
  294. IN PIRP Irp,
  295. IN PVOID InputBuffer,
  296. IN ULONG InputBufferLength,
  297. IN PVOID OutputBuffer,
  298. IN ULONG OutputBufferLength)
  299. {
  300. NTSTATUS Status, MarshalStatus;
  301. PDFS_PKT pPkt;
  302. PDFS_PKT_ENTRY pPktEntry;
  303. MARSHAL_BUFFER marshalBuffer;
  304. DFS_PKT_ENTRY_ID EntryId;
  305. DFS_LOCAL_VOLUME_CONFIG ConfigInfo;
  306. ULONG i, cInfo, cbBuffer;
  307. STD_FSCTRL_PROLOGUE(DfsFsctrlGetServerInfo, TRUE, FALSE);
  308. pPkt = _GetPkt();
  309. //
  310. // Get the input arguments
  311. //
  312. MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
  313. Status = DfsRtlGet( &marshalBuffer, &MiPktEntryId, &EntryId );
  314. if (NT_SUCCESS(Status)) {
  315. DebugTrace(0, Dbg,
  316. "Getting Server Info for server [%wZ]\n", &EntryId.Prefix);
  317. MarshalBufferInitialize(
  318. &marshalBuffer,
  319. OutputBufferLength,
  320. OutputBuffer );
  321. //
  322. // We'll marshal in a count of 0 at the beginning of the output
  323. // buffer. Later, we'll revisit this and put in the actual count of
  324. // relation info's.
  325. //
  326. cInfo = 0;
  327. MarshalStatus = DfsRtlPutUlong( &marshalBuffer, &cInfo );
  328. cbBuffer = sizeof(ULONG);
  329. //
  330. // For each Pkt entry, create and marshal a relation info if the
  331. // Dfs volume is a local volume for the server.
  332. //
  333. PktAcquireShared( pPkt, TRUE );
  334. pPktEntry =
  335. CONTAINING_RECORD(pPkt->EntryList.Flink, DFS_PKT_ENTRY, Link);
  336. for (i = 0; i < pPkt->EntryCount && NT_SUCCESS(Status); i++) {
  337. Status = DfspGetServerConfigInfo(
  338. &EntryId.Uid,
  339. pPkt,
  340. pPktEntry,
  341. &ConfigInfo);
  342. if (NT_SUCCESS(Status)) {
  343. DebugTrace(0, Dbg, "Found [%wZ]\n", &pPktEntry->Id.Prefix);
  344. Status = DfsRtlSize( &MiLocalVolumeConfig, &ConfigInfo, &cbBuffer);
  345. if (NT_SUCCESS(Status) && NT_SUCCESS(MarshalStatus)) {
  346. MarshalStatus = DfsRtlPut(
  347. &marshalBuffer,
  348. &MiLocalVolumeConfig,
  349. &ConfigInfo);
  350. cInfo++;
  351. }
  352. LocalVolumeConfigInfoDestroy( &ConfigInfo, FALSE );
  353. } else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  354. //
  355. // Means volume is not local to server - go on to the next
  356. // Pkt Entry
  357. //
  358. Status = STATUS_SUCCESS;
  359. } else if (Status == STATUS_OBJECT_TYPE_MISMATCH) {
  360. //
  361. // Means volume is a Machine, Domain, or Orgroot volume -
  362. // we ignore it.
  363. //
  364. Status = STATUS_SUCCESS;
  365. } else {
  366. DebugTrace(0, Dbg,
  367. "Error %08lx constructing relation info!\n", ULongToPtr( Status ));
  368. }
  369. pPktEntry =
  370. CONTAINING_RECORD(pPktEntry->Link.Flink, DFS_PKT_ENTRY, Link);
  371. } // End for each Pkt Entry
  372. PktRelease( pPkt );
  373. //
  374. // Free the unmarshalled input arguments
  375. //
  376. PktEntryIdDestroy(&EntryId, FALSE);
  377. } else {
  378. DebugTrace( 0, Dbg, "Error %08lx unmarshalling input\n", ULongToPtr( Status ));
  379. }
  380. if (NT_SUCCESS(Status)) {
  381. if (NT_SUCCESS(MarshalStatus)) {
  382. //
  383. // Everything went successfully - Marshal in the number of
  384. // relation info's we are returning at the beginning of the
  385. // output buffer
  386. //
  387. MarshalBufferInitialize(
  388. &marshalBuffer,
  389. OutputBufferLength,
  390. OutputBuffer);
  391. Status = DfsRtlPutUlong( &marshalBuffer, &cInfo );
  392. ASSERT( NT_SUCCESS(Status) );
  393. ASSERT( cbBuffer <= OutputBufferLength );
  394. Irp->IoStatus.Information = cbBuffer;
  395. } else {
  396. //
  397. // If we hit a marshalling error along the way, we'll try and
  398. // tell the caller how much buffer we need
  399. //
  400. RETURN_BUFFER_SIZE( cbBuffer, Status );
  401. }
  402. }
  403. DfsCompleteRequest( Irp, Status );
  404. DebugTrace(-1, Dbg, "DfsFsctrlGetServerInfo: returning %08lx\n", ULongToPtr( Status ));
  405. return Status;
  406. }
  407. //+----------------------------------------------------------------------------
  408. //
  409. // Function: DfsFsctrlCheckStgIdInUse
  410. //
  411. // Synopsis: Given a storage id and the machine guid of a server, this
  412. // routine will say whether the storage id can be legally shared
  413. // by the server. This routine is intended to be called on the
  414. // DC only.
  415. //
  416. // Arguments:
  417. //
  418. // Returns: [STATUS_SUCCESS] -- It is legal for the server to share the
  419. // storage id.
  420. //
  421. // [STATUS_DEVICE_BUSY] -- Some parent or child of the
  422. // storage id is already shared in Dfs. The shared
  423. // volume is returned in OutputBuffer.
  424. //
  425. // [STATUS_BUFFER_OVERFLOW] -- OutputBuffer too small to return
  426. // prefix of shared volume - the required size is
  427. // returned in the first 4 bytes of OutputBuffer
  428. //
  429. // [STATUS_BUFFER_TOO_SMALL] -- OutputBuffer is < 4 bytes.
  430. //
  431. // [STATUS_DATA_ERROR] -- Unable to unmarshall the arguments.
  432. //
  433. // [STATUS_INSUFFICIENT_RESOURCES] -- Unable to unmarshall the
  434. // arguments.
  435. //
  436. // Notes: The Input buffer is a marshalled PKT_ENTRY_ID, where the
  437. // GUID is the server's machine id, and the Prefix is the
  438. // storage id to be verified.
  439. //
  440. //-----------------------------------------------------------------------------
  441. NTSTATUS
  442. DfsFsctrlCheckStgIdInUse(
  443. IN PIRP Irp,
  444. IN PVOID InputBuffer,
  445. IN ULONG InputBufferLength,
  446. IN PVOID OutputBuffer,
  447. IN ULONG OutputBufferLength)
  448. {
  449. NTSTATUS Status = STATUS_SUCCESS; // Innocent till proven...
  450. PDFS_PKT pPkt;
  451. PDFS_PKT_ENTRY pPktEntry;
  452. MARSHAL_BUFFER marshalBuffer;
  453. DFS_PKT_ENTRY_ID EntryId;
  454. ULONG i;
  455. STD_FSCTRL_PROLOGUE(DfsFsctrlIsStgIdLegalOnServer, TRUE, FALSE);
  456. MarshalBufferInitialize( &marshalBuffer, InputBufferLength, InputBuffer );
  457. Status = DfsRtlGet( &marshalBuffer, &MiPktEntryId, &EntryId );
  458. if (NT_SUCCESS(Status)) {
  459. DebugTrace(0, Dbg, "Verifying Storage Id [%wZ]\n", &EntryId.Prefix );
  460. pPkt = _GetPkt();
  461. pPktEntry =
  462. CONTAINING_RECORD(pPkt->EntryList.Flink, DFS_PKT_ENTRY, Link);
  463. for (i = 0; i < pPkt->EntryCount && NT_SUCCESS(Status); i++) {
  464. //
  465. // For every pkt entry, we iterate through all the services. If a
  466. // service matches the input service, then we see if the storage
  467. // id is a prefix or child of the service's storage id. If so,
  468. // the storage id is not legal.
  469. //
  470. ULONG j;
  471. for (j = 0;
  472. j < pPktEntry->Info.ServiceCount && NT_SUCCESS(Status);
  473. j++) {
  474. PDFS_SERVICE pService = &pPktEntry->Info.ServiceList[j];
  475. if ( GuidEqual( &pService->pMachEntry->pMachine->guidMachine,
  476. &EntryId.Uid ) ) {
  477. if (IsPathAPrefixOf(
  478. &EntryId.Prefix,
  479. &pService->StgId ) ||
  480. IsPathAPrefixOf(
  481. &pService->StgId,
  482. &EntryId.Prefix )) {
  483. DebugTrace(0, Dbg,
  484. "Stg Id Not legal - Conflicts with [%wZ]\n",
  485. &pPktEntry->Id.Prefix);
  486. DebugTrace(0, Dbg,
  487. "Storage Id for share is [%wZ]\n",
  488. &pService->StgId);
  489. Status = STATUS_DEVICE_BUSY;
  490. }
  491. //
  492. // We found a matching service, no need to look at the
  493. // rest of the services
  494. //
  495. break;
  496. }
  497. }
  498. pPktEntry =
  499. CONTAINING_RECORD(pPktEntry->Link.Flink, DFS_PKT_ENTRY, Link);
  500. }
  501. //
  502. // Free the unmarshalled input arguments
  503. //
  504. PktEntryIdDestroy(&EntryId, FALSE);
  505. } else {
  506. DebugTrace( 0, Dbg, "Unmarshalling Error - %08lx\n", ULongToPtr( Status ));
  507. }
  508. DfsCompleteRequest( Irp, Status );
  509. DebugTrace(-1, Dbg,
  510. "DfsFsctrlIsStgIdLegalOnServer - returning %08lx\n", ULongToPtr( Status ));
  511. return Status;
  512. }
  513. //+----------------------------------------------------------------------------
  514. //
  515. // Function: DfspGetServerConfigInfo
  516. //
  517. // Synopsis: Given a machine guid and a pkt entry, this routine will
  518. // return the relation info for the entry if the machine is a
  519. // server for the entry.
  520. //
  521. // Arguments: [pMachine] -- Pointer to machine guid
  522. // [pPkt] -- The pkt to examine
  523. // [pPktEntry] -- The pkt entry to examine
  524. // [pConfigInfo] -- If the machine is a server for this entry, a
  525. // relation info is returned here.
  526. //
  527. // Returns: [STATUS_SUCCESS] -- Machine is a server, and relation info
  528. // constructed successfully
  529. //
  530. // [STATUS_OBJECT_NAME_NOT_FOUND] -- Machine is not a server for
  531. // the given pkt entry
  532. //
  533. // [STATUS_OBJECT_TYPE_MISMATCH] -- pPktEntry is for a machine,
  534. // domain, or orgroot volume. Can't get config info for
  535. // these volumes.
  536. //
  537. // [STATUS_INSUFFICIENT_RESOURCES] -- Machine is a server, but
  538. // out of memory constructing relation info
  539. //
  540. //-----------------------------------------------------------------------------
  541. NTSTATUS
  542. DfspGetServerConfigInfo(
  543. IN GUID *pMachine,
  544. IN PDFS_PKT pPkt,
  545. IN PDFS_PKT_ENTRY pPktEntry,
  546. OUT PDFS_LOCAL_VOLUME_CONFIG pConfigInfo)
  547. {
  548. ULONG j;
  549. NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
  550. //
  551. // We can't get a config info for a machine volume.
  552. //
  553. if ( ((pPktEntry->Type & PKT_ENTRY_TYPE_MACHINE) != 0) ||
  554. (pPktEntry == pPkt->DomainPktEntry) ||
  555. (pPktEntry->Id.Prefix.Length == sizeof(WCHAR))) {
  556. return( STATUS_OBJECT_TYPE_MISMATCH );
  557. }
  558. for (j = 0; j < pPktEntry->Info.ServiceCount; j++) {
  559. PDFS_SERVICE pService = &pPktEntry->Info.ServiceList[j];
  560. if ( GuidEqual(
  561. &pService->pMachEntry->pMachine->guidMachine,
  562. pMachine ) ) {
  563. Status = PktRelationInfoConstruct(
  564. &pConfigInfo->RelationInfo,
  565. pPkt,
  566. &pPktEntry->Id);
  567. ASSERT( Status != DFS_STATUS_NO_SUCH_ENTRY );
  568. if (NT_SUCCESS(Status)) {
  569. ASSERT( pService->StgId.Length != 0 );
  570. pConfigInfo->StgId.Length = 0;
  571. pConfigInfo->StgId.MaximumLength =
  572. pService->StgId.MaximumLength;
  573. pConfigInfo->StgId.Buffer = ExAllocatePoolWithTag(
  574. PagedPool,
  575. pService->StgId.Length,
  576. ' sfD');
  577. if (pConfigInfo->StgId.Buffer != NULL) {
  578. RtlCopyUnicodeString(
  579. &pConfigInfo->StgId,
  580. &pService->StgId);
  581. } else {
  582. Status = STATUS_INSUFFICIENT_RESOURCES;
  583. }
  584. }
  585. if (NT_SUCCESS(Status)) {
  586. ASSERT( pPktEntry->Type & PKT_ENTRY_TYPE_CAIRO );
  587. //
  588. // Send only the PKT_ENTRY_TYPE_CAIRO bit.
  589. //
  590. pConfigInfo->EntryType = PKT_ENTRY_TYPE_CAIRO;
  591. //
  592. // Send only the service online/offline bit
  593. //
  594. pConfigInfo->ServiceType = pService->Type &
  595. DFS_SERVICE_TYPE_OFFLINE;
  596. }
  597. break;
  598. }
  599. }
  600. return( Status );
  601. }
  602. //+----------------------------------------------------------------------------
  603. //
  604. // Function: IsPathAPrefixOf
  605. //
  606. // Synopsis: Given two paths, this will return TRUE if the first path is
  607. // a prefix of the second.
  608. //
  609. // Arguments: [pustrPath1] -- The two paths
  610. // [pustrPath2]
  611. //
  612. // Returns: TRUE if pustrPath1 is a prefix of pustrPath2, FALSE otherwise
  613. //
  614. //-----------------------------------------------------------------------------
  615. BOOLEAN
  616. IsPathAPrefixOf(
  617. IN PUNICODE_STRING pustrPath1,
  618. IN PUNICODE_STRING pustrPath2)
  619. {
  620. BOOLEAN fResult;
  621. fResult = RtlPrefixUnicodeString( pustrPath1, pustrPath2, FALSE );
  622. if (fResult) {
  623. //
  624. // Path1 is a prefix of Path2. However, this is not a sufficient test.
  625. // We have to catch cases like d:\test1 being a prefix of d:\test10
  626. //
  627. fResult =
  628. (pustrPath2->Length == pustrPath1->Length)
  629. ||
  630. (pustrPath2->Buffer[ pustrPath1->Length / sizeof(WCHAR) ] ==
  631. UNICODE_PATH_SEP);
  632. }
  633. return( fResult );
  634. }