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.

1114 lines
26 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. Share.c
  5. Abstract:
  6. This module contains support for the DFS catagory of APIs for the
  7. NT server service.
  8. Revision History:
  9. --*/
  10. #include "srvsvcp.h"
  11. #include "lmerr.h"
  12. #include <dfsfsctl.h>
  13. #include <dsgetdc.h>
  14. #include <lmapibuf.h> // NetApiBufferFree().
  15. #define CAPTURE_STRING( Name ) \
  16. if( Name != NULL ) { \
  17. ULONG _size = SIZE_WSTR( Name ); \
  18. capture->Name = (LPWSTR)variableData; \
  19. RtlCopyMemory( capture->Name, Name, _size ); \
  20. variableData += _size; \
  21. POINTER_TO_OFFSET( capture->Name, capture ); \
  22. }
  23. #define RELATION_INFO_SIZE( RelInfo ) \
  24. (sizeof( NET_DFS_ENTRY_ID_CONTAINER ) + \
  25. (RelInfo->Count * sizeof(NET_DFS_ENTRY_ID)))
  26. BOOLEAN
  27. ValidateDfsEntryIdContainer(
  28. LPNET_DFS_ENTRY_ID_CONTAINER pRelationInfo);
  29. NET_API_STATUS
  30. DfsFsctl(
  31. IN ULONG FsControlCode,
  32. IN PVOID InputBuffer,
  33. IN ULONG InputBufferLength,
  34. OUT PVOID OutputBuffer,
  35. IN ULONG OutputBufferLength
  36. )
  37. {
  38. NTSTATUS status;
  39. OBJECT_ATTRIBUTES objectAttributes;
  40. IO_STATUS_BLOCK ioStatus;
  41. HANDLE dfsHandle;
  42. UNICODE_STRING deviceName;
  43. deviceName.Buffer = DFS_SERVER_NAME;
  44. deviceName.MaximumLength = sizeof( DFS_SERVER_NAME );
  45. deviceName.Length = deviceName.MaximumLength - sizeof(UNICODE_NULL);
  46. InitializeObjectAttributes(
  47. &objectAttributes,
  48. &deviceName,
  49. OBJ_CASE_INSENSITIVE,
  50. NULL,
  51. NULL
  52. );
  53. if( SsData.SsInitialized &&
  54. (status = RpcImpersonateClient(NULL)) != NO_ERROR ) {
  55. return (NET_API_STATUS) status;
  56. }
  57. status = NtCreateFile(
  58. &dfsHandle,
  59. SYNCHRONIZE | FILE_WRITE_DATA,
  60. &objectAttributes,
  61. &ioStatus,
  62. NULL,
  63. FILE_ATTRIBUTE_NORMAL,
  64. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  65. FILE_OPEN_IF,
  66. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  67. NULL,
  68. 0);
  69. if ( SsData.SsInitialized ) {
  70. (VOID)RpcRevertToSelf( );
  71. }
  72. if ( NT_SUCCESS(status) ) {
  73. status = ioStatus.Status;
  74. }
  75. if( !NT_SUCCESS( status ) ) {
  76. return (NET_API_STATUS)status;
  77. }
  78. status = NtFsControlFile(
  79. dfsHandle,
  80. NULL, // Event,
  81. NULL, // ApcRoutine,
  82. NULL, // ApcContext,
  83. &ioStatus,
  84. FsControlCode,
  85. InputBuffer,
  86. InputBufferLength,
  87. OutputBuffer,
  88. OutputBufferLength
  89. );
  90. if(NT_SUCCESS(status)) {
  91. status = ioStatus.Status;
  92. }
  93. NtClose( dfsHandle );
  94. return (NET_API_STATUS)status;
  95. }
  96. NET_API_STATUS NET_API_FUNCTION
  97. NetrDfsGetVersion(
  98. IN SRVSVC_HANDLE ServerName,
  99. OUT LPDWORD Version)
  100. {
  101. DFS_GET_VERSION_ARG arg;
  102. NET_API_STATUS error;
  103. RtlZeroMemory( &arg, sizeof(arg) );
  104. error = DfsFsctl( FSCTL_DFS_GET_VERSION, &arg, sizeof( arg ), NULL, 0 );
  105. if (error == NERR_Success) {
  106. *Version = arg.Version;
  107. } else {
  108. error = ERROR_FILE_NOT_FOUND;
  109. }
  110. return( error );
  111. }
  112. NET_API_STATUS NET_API_FUNCTION
  113. NetrDfsCreateLocalPartition (
  114. IN SRVSVC_HANDLE ServerName, // Name of server for this API
  115. IN LPWSTR ShareName, // Name of share to add to the DFS
  116. IN LPGUID EntryUid, // unique id for this partition
  117. IN LPWSTR EntryPrefix, // DFS entry path for this volume
  118. IN LPWSTR ShortName, // 8.3 format of EntryPrefix
  119. IN LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
  120. IN BOOL Force // Force knowledge into consistent state?
  121. )
  122. {
  123. NET_API_STATUS error;
  124. PDFS_CREATE_LOCAL_PARTITION_ARG capture;
  125. ULONG size = sizeof( *capture );
  126. ULONG i;
  127. PCHAR variableData;
  128. PSERVER_REQUEST_PACKET srp;
  129. LPSHARE_INFO_2 shareInfo2 = NULL;
  130. UNICODE_STRING ntSharePath;
  131. if( ShareName == NULL || EntryUid == NULL ||
  132. EntryPrefix == NULL || RelationInfo == NULL ||
  133. ValidateDfsEntryIdContainer(RelationInfo) == FALSE) {
  134. return ERROR_INVALID_PARAMETER;
  135. }
  136. //
  137. // Make a call to the SMB server to find the pathname for the share.
  138. //
  139. srp = SsAllocateSrp();
  140. if( srp == NULL ) {
  141. return ERROR_NOT_ENOUGH_MEMORY;
  142. };
  143. srp->Level = 2;
  144. srp->Flags = SRP_RETURN_SINGLE_ENTRY;
  145. srp->Parameters.Get.ResumeHandle = 0;
  146. RtlInitUnicodeString( &srp->Name1, ShareName );
  147. error = SsServerFsControlGetInfo(
  148. FSCTL_SRV_NET_SHARE_ENUM,
  149. srp,
  150. &shareInfo2,
  151. 10000
  152. );
  153. if( error != NO_ERROR ) {
  154. SsFreeSrp( srp );
  155. return error;
  156. }
  157. if( srp->Parameters.Get.EntriesRead == 0 ||
  158. shareInfo2 == NULL ||
  159. shareInfo2->shi2_path == NULL ) {
  160. SsFreeSrp( srp );
  161. if( shareInfo2 != NULL ) {
  162. MIDL_user_free( shareInfo2 );
  163. }
  164. return ERROR_BAD_NET_NAME;
  165. }
  166. if( (shareInfo2->shi2_type & ~STYPE_SPECIAL) != STYPE_DISKTREE ) {
  167. SsFreeSrp( srp );
  168. MIDL_user_free( shareInfo2 );
  169. return ERROR_BAD_DEV_TYPE;
  170. }
  171. //
  172. // Now we need to convert the share's Win32 style pathname to an
  173. // NT pathname
  174. //
  175. ntSharePath.Buffer = NULL;
  176. if( !RtlDosPathNameToNtPathName_U(
  177. shareInfo2->shi2_path,
  178. &ntSharePath,
  179. NULL,
  180. NULL ) ) {
  181. SsFreeSrp( srp );
  182. MIDL_user_free( shareInfo2 );
  183. return ERROR_INVALID_PARAMETER;
  184. }
  185. MIDL_user_free( shareInfo2 );
  186. //
  187. // Pack the data into an fsctl that can be sent to the local Dfs driver:
  188. //
  189. // First find the size...
  190. //
  191. size += SIZE_WSTR( ShareName );
  192. size += ntSharePath.Length + sizeof( WCHAR );
  193. size += SIZE_WSTR( EntryPrefix );
  194. size += SIZE_WSTR( ShortName );
  195. if( ARGUMENT_PRESENT( RelationInfo ) ) {
  196. size += RELATION_INFO_SIZE(RelationInfo);
  197. for( i = 0; i < RelationInfo->Count; i++ ) {
  198. size += SIZE_WSTR( RelationInfo->Buffer[i].Prefix );
  199. }
  200. }
  201. //
  202. // Now allocate the memory
  203. //
  204. capture = MIDL_user_allocate( size );
  205. if( capture == NULL ) {
  206. SsFreeSrp( srp );
  207. RtlFreeUnicodeString( &ntSharePath );
  208. return ERROR_NOT_ENOUGH_MEMORY;
  209. }
  210. RtlZeroMemory( capture, size );
  211. //
  212. // Put the fixed parameters in the capture buffer
  213. //
  214. capture->EntryUid = *EntryUid;
  215. capture->Force = (Force != FALSE);
  216. //
  217. // Put the variable data in the capture buffer.
  218. //
  219. variableData = (PCHAR)(capture + 1);
  220. if( ARGUMENT_PRESENT( RelationInfo ) ) {
  221. capture->RelationInfo = (LPNET_DFS_ENTRY_ID_CONTAINER)variableData;
  222. capture->RelationInfo->Buffer = (LPNET_DFS_ENTRY_ID)
  223. (capture->RelationInfo + 1);
  224. variableData += RELATION_INFO_SIZE( RelationInfo );
  225. for( i=0; i < RelationInfo->Count; i++ ) {
  226. CAPTURE_STRING( RelationInfo->Buffer[i].Prefix );
  227. capture->RelationInfo->Buffer[i].Uid = RelationInfo->Buffer[i].Uid;
  228. }
  229. POINTER_TO_OFFSET( capture->RelationInfo->Buffer, capture );
  230. POINTER_TO_OFFSET( capture->RelationInfo, capture );
  231. }
  232. CAPTURE_STRING( ShareName );
  233. CAPTURE_STRING( EntryPrefix );
  234. CAPTURE_STRING( ShortName );
  235. //
  236. // Capture the nt version of the share path
  237. //
  238. capture->SharePath = (LPWSTR)variableData;
  239. RtlCopyMemory( capture->SharePath, ntSharePath.Buffer, ntSharePath.Length );
  240. variableData += ntSharePath.Length;
  241. POINTER_TO_OFFSET( capture->SharePath, capture );
  242. *((WCHAR *)variableData) = 0; // Null terminate the name
  243. variableData += sizeof( WCHAR );
  244. RtlFreeUnicodeString( &ntSharePath );
  245. //
  246. // First, tell the server to mark this share as being in Dfs. Note that
  247. // the share name is already in srp->Name1. If we later run into an
  248. // error, we'll undo the state change.
  249. //
  250. srp->Flags = SRP_SET_SHARE_IN_DFS;
  251. error = SsServerFsControl(
  252. FSCTL_SRV_SHARE_STATE_CHANGE,
  253. srp,
  254. NULL,
  255. 0
  256. );
  257. if( error != NO_ERROR ) {
  258. SsFreeSrp( srp );
  259. MIDL_user_free( capture );
  260. return error;
  261. }
  262. //
  263. // Tell the Dfs driver!
  264. //
  265. error = DfsFsctl(
  266. FSCTL_DFS_CREATE_LOCAL_PARTITION,
  267. capture,
  268. size,
  269. NULL,
  270. 0
  271. );
  272. MIDL_user_free( capture );
  273. if (error != NO_ERROR) {
  274. //
  275. // An error occured changing the Dfs state. So, try to undo the
  276. // server share state change.
  277. //
  278. NET_API_STATUS error2;
  279. srp->Flags = SRP_CLEAR_SHARE_IN_DFS;
  280. error2 = SsServerFsControl(
  281. FSCTL_SRV_SHARE_STATE_CHANGE,
  282. srp,
  283. NULL,
  284. 0);
  285. }
  286. SsFreeSrp( srp );
  287. return error;
  288. }
  289. NET_API_STATUS NET_API_FUNCTION
  290. NetrDfsDeleteLocalPartition (
  291. IN SRVSVC_HANDLE ServerName,
  292. IN LPGUID Uid,
  293. IN LPWSTR Prefix
  294. )
  295. {
  296. NET_API_STATUS error;
  297. PDFS_DELETE_LOCAL_PARTITION_ARG capture;
  298. ULONG size = sizeof( *capture );
  299. PCHAR variableData;
  300. //
  301. // Pack the args into a single buffer that can be sent to
  302. // the dfs driver:
  303. //
  304. //
  305. // First find the size...
  306. //
  307. size += SIZE_WSTR( Prefix );
  308. //
  309. // Now allocate the memory
  310. //
  311. capture = MIDL_user_allocate( size );
  312. if( capture == NULL ) {
  313. return ERROR_NOT_ENOUGH_MEMORY;
  314. }
  315. RtlZeroMemory( capture, size );
  316. //
  317. // Put the fixed parameters into the capture buffer
  318. //
  319. capture->Uid = *Uid;
  320. //
  321. // Put the variable data in the capture buffer
  322. //
  323. variableData = (PCHAR)(capture + 1 );
  324. CAPTURE_STRING( Prefix );
  325. //
  326. // Tell the driver!
  327. //
  328. error = DfsFsctl(
  329. FSCTL_DFS_DELETE_LOCAL_PARTITION,
  330. capture,
  331. size,
  332. NULL,
  333. 0
  334. );
  335. MIDL_user_free( capture );
  336. //
  337. // If there was no error, tell the server that this share
  338. // is no longer in the Dfs
  339. //
  340. return error;
  341. }
  342. NET_API_STATUS NET_API_FUNCTION
  343. NetrDfsSetLocalVolumeState (
  344. IN SRVSVC_HANDLE ServerName,
  345. IN LPGUID Uid,
  346. IN LPWSTR Prefix,
  347. IN ULONG State
  348. )
  349. {
  350. NET_API_STATUS error;
  351. PDFS_SET_LOCAL_VOLUME_STATE_ARG capture;
  352. ULONG size = sizeof( *capture );
  353. PCHAR variableData;
  354. //
  355. // Pack the args into a single buffer that can be sent to
  356. // the dfs driver:
  357. //
  358. //
  359. // First find the size...
  360. //
  361. size += SIZE_WSTR( Prefix );
  362. //
  363. // Now allocate the memory
  364. //
  365. capture = MIDL_user_allocate( size );
  366. if( capture == NULL ) {
  367. return ERROR_NOT_ENOUGH_MEMORY;
  368. }
  369. RtlZeroMemory( capture, size );
  370. //
  371. // Put the fixed parameters into the capture buffer
  372. //
  373. capture->Uid = *Uid;
  374. capture->State = State;
  375. //
  376. // Put the variable data in the capture buffer
  377. //
  378. variableData = (PCHAR)(capture + 1 );
  379. CAPTURE_STRING( Prefix );
  380. //
  381. // Tell the driver!
  382. //
  383. error = DfsFsctl(
  384. FSCTL_DFS_SET_LOCAL_VOLUME_STATE,
  385. capture,
  386. size,
  387. NULL,
  388. 0
  389. );
  390. MIDL_user_free( capture );
  391. return error;
  392. }
  393. NET_API_STATUS NET_API_FUNCTION
  394. NetrDfsSetServerInfo (
  395. IN SRVSVC_HANDLE ServerName,
  396. IN LPGUID Uid,
  397. IN LPWSTR Prefix
  398. )
  399. {
  400. NET_API_STATUS error;
  401. PDFS_SET_SERVER_INFO_ARG capture;
  402. ULONG size = sizeof( *capture );
  403. PCHAR variableData;
  404. //
  405. // Pack the args into a single buffer that can be sent to
  406. // the dfs driver:
  407. //
  408. //
  409. // First find the size...
  410. //
  411. size += SIZE_WSTR( Prefix );
  412. //
  413. // Now allocate the memory
  414. //
  415. capture = MIDL_user_allocate( size );
  416. if( capture == NULL ) {
  417. return ERROR_NOT_ENOUGH_MEMORY;
  418. }
  419. RtlZeroMemory( capture, size );
  420. //
  421. // Put the fixed parameters into the capture buffer
  422. //
  423. capture->Uid = *Uid;
  424. //
  425. // Put the variable data in the capture buffer
  426. //
  427. variableData = (PCHAR)(capture + 1 );
  428. CAPTURE_STRING( Prefix );
  429. //
  430. // Tell the driver!
  431. //
  432. error = DfsFsctl(
  433. FSCTL_DFS_SET_SERVER_INFO,
  434. capture,
  435. size,
  436. NULL,
  437. 0
  438. );
  439. MIDL_user_free( capture );
  440. return error;
  441. }
  442. NET_API_STATUS NET_API_FUNCTION
  443. NetrDfsCreateExitPoint (
  444. IN SRVSVC_HANDLE ServerName,
  445. IN LPGUID Uid,
  446. IN LPWSTR Prefix,
  447. IN ULONG Type,
  448. IN ULONG ShortPrefixLen,
  449. OUT LPWSTR ShortPrefix
  450. )
  451. {
  452. NET_API_STATUS error;
  453. PDFS_CREATE_EXIT_POINT_ARG capture;
  454. ULONG size = sizeof( *capture );
  455. PCHAR variableData;
  456. //
  457. // Pack the args into a single buffer that can be sent to
  458. // the dfs driver:
  459. //
  460. //
  461. // First find the size...
  462. //
  463. size += SIZE_WSTR( Prefix );
  464. //
  465. // Now allocate the memory
  466. //
  467. capture = MIDL_user_allocate( size );
  468. if( capture == NULL ) {
  469. return ERROR_NOT_ENOUGH_MEMORY;
  470. }
  471. RtlZeroMemory( capture, size );
  472. //
  473. // Put the fixed parameters into the capture buffer
  474. //
  475. capture->Uid = *Uid;
  476. capture->Type = Type;
  477. //
  478. // Put the variable data in the capture buffer
  479. //
  480. variableData = (PCHAR)(capture + 1 );
  481. CAPTURE_STRING( Prefix );
  482. //
  483. // Tell the driver!
  484. //
  485. error = DfsFsctl(
  486. FSCTL_DFS_CREATE_EXIT_POINT,
  487. capture,
  488. size,
  489. ShortPrefix,
  490. ShortPrefixLen * sizeof(WCHAR)
  491. );
  492. MIDL_user_free( capture );
  493. return error;
  494. }
  495. NET_API_STATUS NET_API_FUNCTION
  496. NetrDfsDeleteExitPoint (
  497. IN SRVSVC_HANDLE ServerName,
  498. IN LPGUID Uid,
  499. IN LPWSTR Prefix,
  500. IN ULONG Type
  501. )
  502. {
  503. NET_API_STATUS error;
  504. PDFS_DELETE_EXIT_POINT_ARG capture;
  505. ULONG size = sizeof( *capture );
  506. PCHAR variableData;
  507. //
  508. // Pack the args into a single buffer that can be sent to
  509. // the dfs driver:
  510. //
  511. //
  512. // First find the size...
  513. //
  514. size += SIZE_WSTR( Prefix );
  515. //
  516. // Now allocate the memory
  517. //
  518. capture = MIDL_user_allocate( size );
  519. if( capture == NULL ) {
  520. return ERROR_NOT_ENOUGH_MEMORY;
  521. }
  522. RtlZeroMemory( capture, size );
  523. //
  524. // Put the fixed parameters into the capture buffer
  525. //
  526. capture->Uid = *Uid;
  527. capture->Type = Type;
  528. //
  529. // Put the variable data in the capture buffer
  530. //
  531. variableData = (PCHAR)(capture + 1 );
  532. CAPTURE_STRING( Prefix );
  533. //
  534. // Tell the driver!
  535. //
  536. error = DfsFsctl(
  537. FSCTL_DFS_DELETE_EXIT_POINT,
  538. capture,
  539. size,
  540. NULL,
  541. 0
  542. );
  543. MIDL_user_free( capture );
  544. return error;
  545. }
  546. NET_API_STATUS NET_API_FUNCTION
  547. NetrDfsModifyPrefix (
  548. IN SRVSVC_HANDLE ServerName,
  549. IN LPGUID Uid,
  550. IN LPWSTR Prefix
  551. )
  552. {
  553. NET_API_STATUS error;
  554. PDFS_DELETE_LOCAL_PARTITION_ARG capture;
  555. ULONG size = sizeof( *capture );
  556. PCHAR variableData;
  557. //
  558. // Pack the args into a single buffer that can be sent to
  559. // the dfs driver:
  560. //
  561. //
  562. // First find the size...
  563. //
  564. size += SIZE_WSTR( Prefix );
  565. //
  566. // Now allocate the memory
  567. //
  568. capture = MIDL_user_allocate( size );
  569. if( capture == NULL ) {
  570. return ERROR_NOT_ENOUGH_MEMORY;
  571. }
  572. RtlZeroMemory( capture, size );
  573. //
  574. // Put the fixed parameters into the capture buffer
  575. //
  576. capture->Uid = *Uid;
  577. //
  578. // Put the variable data in the capture buffer
  579. //
  580. variableData = (PCHAR)(capture + 1 );
  581. CAPTURE_STRING( Prefix );
  582. //
  583. // Tell the driver!
  584. //
  585. error = DfsFsctl(
  586. FSCTL_DFS_MODIFY_PREFIX,
  587. capture,
  588. size,
  589. NULL,
  590. 0
  591. );
  592. MIDL_user_free( capture );
  593. return error;
  594. }
  595. NET_API_STATUS NET_API_FUNCTION
  596. NetrDfsFixLocalVolume (
  597. IN SRVSVC_HANDLE ServerName,
  598. IN LPWSTR VolumeName,
  599. IN ULONG EntryType,
  600. IN ULONG ServiceType,
  601. IN LPWSTR StgId,
  602. IN LPGUID EntryUid, // unique id for this partition
  603. IN LPWSTR EntryPrefix, // path prefix for this partition
  604. IN LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
  605. IN ULONG CreateDisposition
  606. )
  607. {
  608. NET_API_STATUS error;
  609. PDFS_FIX_LOCAL_VOLUME_ARG capture;
  610. ULONG size = sizeof( *capture );
  611. ULONG i;
  612. PCHAR variableData;
  613. if (ARGUMENT_PRESENT(RelationInfo) && ValidateDfsEntryIdContainer(RelationInfo) == FALSE)
  614. return ERROR_INVALID_PARAMETER;
  615. //
  616. // Pack the args into a single buffer that can be sent to the
  617. // dfs driver:
  618. //
  619. //
  620. // First find the size...
  621. //
  622. size += SIZE_WSTR( VolumeName );
  623. size += SIZE_WSTR( StgId );
  624. size += SIZE_WSTR( EntryPrefix );
  625. if( ARGUMENT_PRESENT( RelationInfo ) ) {
  626. size += RELATION_INFO_SIZE( RelationInfo );
  627. for( i = 0; i < RelationInfo->Count; i++ ) {
  628. size += SIZE_WSTR( RelationInfo->Buffer[i].Prefix );
  629. }
  630. }
  631. //
  632. // Now allocate the memory
  633. //
  634. capture = MIDL_user_allocate( size );
  635. if( capture == NULL ) {
  636. return ERROR_NOT_ENOUGH_MEMORY;
  637. }
  638. RtlZeroMemory( capture, size );
  639. //
  640. // Put the fixed parameters in the capture buffer
  641. //
  642. capture->EntryType = EntryType;
  643. capture->ServiceType = ServiceType;
  644. capture->EntryUid = *EntryUid;
  645. capture->CreateDisposition = CreateDisposition;
  646. //
  647. // Put the variable data in the capture buffer.
  648. //
  649. variableData = (PCHAR)(capture + 1);
  650. if( ARGUMENT_PRESENT( RelationInfo ) ) {
  651. capture->RelationInfo = (LPNET_DFS_ENTRY_ID_CONTAINER)variableData;
  652. capture->RelationInfo->Buffer = (LPNET_DFS_ENTRY_ID)
  653. (capture->RelationInfo + 1);
  654. variableData += RELATION_INFO_SIZE( RelationInfo );
  655. for( i=0; i < RelationInfo->Count; i++ ) {
  656. CAPTURE_STRING( RelationInfo->Buffer[i].Prefix );
  657. capture->RelationInfo->Buffer[i].Uid = RelationInfo->Buffer[i].Uid;
  658. }
  659. POINTER_TO_OFFSET( capture->RelationInfo->Buffer, capture );
  660. POINTER_TO_OFFSET( capture->RelationInfo, capture );
  661. }
  662. CAPTURE_STRING( VolumeName );
  663. CAPTURE_STRING( StgId );
  664. CAPTURE_STRING( EntryPrefix );
  665. //
  666. // Tell the driver!
  667. //
  668. error = DfsFsctl(
  669. FSCTL_DFS_FIX_LOCAL_VOLUME,
  670. capture,
  671. size,
  672. NULL,
  673. 0
  674. );
  675. MIDL_user_free( capture );
  676. return error;
  677. }
  678. //+----------------------------------------------------------------------------
  679. //
  680. // NetrDfsManagerReportSiteInfo
  681. //
  682. // Sends back the site(s) this server covers.
  683. //
  684. // For debugging and other purposes, we first check a registry value with
  685. // the servername passed in. If we get a match, we use the list of sites
  686. // in that value, and don't put our site in the list. Otherwise we always
  687. // return our site (if available) and the sites in the default list.
  688. //
  689. //+----------------------------------------------------------------------------
  690. NET_API_STATUS NET_API_FUNCTION
  691. NetrDfsManagerReportSiteInfo (
  692. IN SRVSVC_HANDLE ServerName,
  693. OUT LPDFS_SITELIST_INFO *ppSiteInfo
  694. )
  695. {
  696. DWORD status;
  697. LPWSTR ThisSite = NULL;
  698. LPWSTR CoveredSites = NULL;
  699. LPDFS_SITELIST_INFO pSiteInfo = NULL;
  700. ULONG Size;
  701. ULONG cSites;
  702. LPWSTR pSiteName;
  703. LPWSTR pNames;
  704. ULONG iSite;
  705. ULONG j;
  706. DWORD dwType;
  707. DWORD dwUnused;
  708. ULONG cbBuffer;
  709. HKEY hkey;
  710. BOOLEAN fUsingDefault = TRUE;
  711. if (ppSiteInfo == NULL || ServerName == NULL) {
  712. return ERROR_INVALID_PARAMETER;
  713. }
  714. status = RegOpenKeyEx(
  715. HKEY_LOCAL_MACHINE,
  716. REG_KEY_COVERED_SITES,
  717. 0,
  718. KEY_QUERY_VALUE,
  719. &hkey);
  720. if( status == ERROR_SUCCESS ) {
  721. status = RegQueryInfoKey(
  722. hkey, // Key
  723. NULL, // Class string
  724. NULL, // Size of class string
  725. NULL, // Reserved
  726. &dwUnused, // # of subkeys
  727. &dwUnused, // max size of subkey name
  728. &dwUnused, // max size of class name
  729. &dwUnused, // # of values
  730. &dwUnused, // max size of value name
  731. &cbBuffer, // max size of value data,
  732. NULL, // security descriptor
  733. NULL); // Last write time
  734. //
  735. // Check if there's a value the same name as the servername passed in,
  736. // if so, use it. Else default to value REG_VALUE_COVERED_SITES.
  737. //
  738. if (status == ERROR_SUCCESS) {
  739. CoveredSites = MIDL_user_allocate(cbBuffer);
  740. if (CoveredSites != NULL) {
  741. status = RegQueryValueEx(
  742. hkey,
  743. ServerName,
  744. NULL,
  745. &dwType,
  746. (PCHAR)CoveredSites,
  747. &cbBuffer);
  748. if (status == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
  749. fUsingDefault = FALSE;
  750. } else {
  751. status = RegQueryValueEx(
  752. hkey,
  753. REG_VALUE_COVERED_SITES,
  754. NULL,
  755. &dwType,
  756. (PCHAR)CoveredSites,
  757. &cbBuffer);
  758. if ( status != ERROR_SUCCESS || dwType != REG_MULTI_SZ) {
  759. MIDL_user_free(CoveredSites);
  760. CoveredSites = NULL;
  761. }
  762. }
  763. }
  764. }
  765. RegCloseKey( hkey );
  766. }
  767. //
  768. // Size the return buffer
  769. //
  770. Size = 0;
  771. for (cSites = 0, pNames = CoveredSites; pNames && *pNames; cSites++) {
  772. Size += (wcslen(pNames) + 1) * sizeof(WCHAR);
  773. pNames += wcslen(pNames) + 1;
  774. }
  775. //
  776. // Get site we belong to, if we're using the defaults
  777. //
  778. ThisSite = NULL;
  779. if (fUsingDefault == TRUE) {
  780. status = DsGetSiteName(NULL, &ThisSite);
  781. if (status == NO_ERROR && ThisSite != NULL) {
  782. Size += (wcslen(ThisSite) + 1) * sizeof(WCHAR);
  783. cSites++;
  784. }
  785. }
  786. //
  787. // If no sites are configured, and we couldn't determine our site,
  788. // then we fail.
  789. //
  790. if (cSites == 0) {
  791. status = ERROR_NO_SITENAME;
  792. goto ErrorReturn;
  793. }
  794. Size += FIELD_OFFSET(DFS_SITELIST_INFO,Site[cSites]);
  795. pSiteInfo = MIDL_user_allocate(Size);
  796. if (pSiteInfo == NULL) {
  797. status = ERROR_NOT_ENOUGH_MEMORY;
  798. goto ErrorReturn;
  799. }
  800. RtlZeroMemory(pSiteInfo, Size);
  801. pSiteInfo->cSites = cSites;
  802. pSiteName = (LPWSTR) ((PCHAR)pSiteInfo +
  803. sizeof(DFS_SITELIST_INFO) +
  804. sizeof(DFS_SITENAME_INFO) * (cSites - 1));
  805. //
  806. // Marshall the site strings into the buffer
  807. //
  808. iSite = 0;
  809. if (ThisSite != NULL) {
  810. wcscpy(pSiteName, ThisSite);
  811. pSiteInfo->Site[iSite].SiteFlags = DFS_SITE_PRIMARY;
  812. pSiteInfo->Site[iSite++].SiteName = pSiteName;
  813. pSiteName += wcslen(ThisSite) + 1;
  814. }
  815. for (pNames = CoveredSites; pNames && *pNames; pNames += wcslen(pNames) + 1) {
  816. wcscpy(pSiteName, pNames);
  817. pSiteInfo->Site[iSite++].SiteName = pSiteName;
  818. pSiteName += wcslen(pSiteName) + 1;
  819. }
  820. *ppSiteInfo = pSiteInfo;
  821. if (CoveredSites != NULL) {
  822. MIDL_user_free(CoveredSites);
  823. }
  824. if (ThisSite != NULL) {
  825. NetApiBufferFree(ThisSite);
  826. }
  827. return status;
  828. ErrorReturn:
  829. if (pSiteInfo != NULL) {
  830. MIDL_user_free(pSiteInfo);
  831. }
  832. if (CoveredSites != NULL) {
  833. MIDL_user_free(CoveredSites);
  834. }
  835. if (ThisSite != NULL) {
  836. NetApiBufferFree(ThisSite);
  837. }
  838. return status;
  839. }
  840. //
  841. // This routine returns TRUE if this machine is the root of a DFS, FALSE otherwise
  842. //
  843. VOID
  844. SsSetDfsRoot()
  845. {
  846. NET_API_STATUS error;
  847. error = DfsFsctl( FSCTL_DFS_IS_ROOT, NULL, 0, NULL, 0 );
  848. SsData.IsDfsRoot = (error == NO_ERROR);
  849. }
  850. //
  851. // This routine checks the LPNET_DFS_ENTRY_ID_CONTAINER container
  852. // for correctness.
  853. //
  854. BOOLEAN
  855. ValidateDfsEntryIdContainer(
  856. LPNET_DFS_ENTRY_ID_CONTAINER pRelationInfo)
  857. {
  858. ULONG iCount;
  859. if (pRelationInfo->Count > 0 && pRelationInfo->Buffer == NULL)
  860. return FALSE;
  861. for (iCount = 0; iCount < pRelationInfo->Count; iCount++) {
  862. if (pRelationInfo->Buffer[iCount].Prefix == NULL)
  863. return FALSE;
  864. }
  865. return TRUE;
  866. }