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.

1216 lines
31 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation
  4. //
  5. // File: lvolinfo.c
  6. //
  7. // Contents: Functions to store and retrieve local volume info in the
  8. // registry.
  9. //
  10. // Classes: None
  11. //
  12. // Functions: DfsStoreLvolInfo
  13. // DfsGetLvolInfo
  14. // DfsDeleteLvolInfo
  15. // DfsChangeLvolInfoServiceType
  16. // DfsChangeLvolInfoEntryPath
  17. // DfsCreateExitPointInfo
  18. // DfsDeleteExitPointInfo
  19. //
  20. // DfspAddSubordinateId
  21. // GuidToString
  22. // StringToGuid
  23. //
  24. //
  25. // History: August 16, 1994 Milans created
  26. //
  27. //-----------------------------------------------------------------------------
  28. #include "dfsprocs.h"
  29. #include "regkeys.h"
  30. #include "registry.h"
  31. #define Dbg DEBUG_TRACE_LOCALVOL
  32. NTSTATUS
  33. DfspAddSubordinateId(
  34. IN PWSTR wszLvolKey,
  35. IN PDFS_PKT_ENTRY_ID pId);
  36. NTSTATUS
  37. DfspReadPrefix(
  38. IN PWSTR wszKey,
  39. IN PWSTR wszValue,
  40. OUT PUNICODE_STRING pustrPrefix);
  41. NTSTATUS
  42. DfspSavePrefix(
  43. IN PWSTR wszKey,
  44. IN PWSTR wszValue,
  45. IN PUNICODE_STRING pustrPrefix);
  46. NTSTATUS
  47. DfspUpgradePrefix(
  48. IN PWSTR wszKey,
  49. IN PWSTR wszValue,
  50. IN USHORT cbComputerName,
  51. IN PULONG pcbPrefix,
  52. IN OUT PWSTR *pwszPrefix);
  53. //+----------------------------------------------------------------------------
  54. //
  55. // Function: DfsStoreLvolInfo
  56. //
  57. // Synopsis: Stores the local volume info in the registry.
  58. //
  59. // Arguments: [pRelationInfo] -- Contains the entry id and exit point info
  60. // for the local volume.
  61. //
  62. // Returns: STATUS_SUCCESS
  63. //
  64. //-----------------------------------------------------------------------------
  65. NTSTATUS
  66. DfsStoreLvolInfo(
  67. IN PDFS_LOCAL_VOLUME_CONFIG pConfigInfo,
  68. IN PUNICODE_STRING pustrStorageId)
  69. {
  70. NTSTATUS Status;
  71. WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
  72. ULONG i;
  73. DebugTrace(+1, Dbg, "DfsStoreLvolInfo: Entered\n", 0);
  74. //
  75. // Open the local volume section
  76. //
  77. Status = KRegSetRoot(wszLocalVolumesSection);
  78. if (!NT_SUCCESS(Status)) {
  79. DebugTrace(-1, Dbg, "Unable to open Local volumes section!\n", 0);
  80. return( Status );
  81. }
  82. //
  83. // Now, create a key for the local volume. We use the ascii form of the
  84. // volume guid as the key.
  85. //
  86. GuidToString( &pConfigInfo->RelationInfo.EntryId.Uid, wszLvolKey );
  87. DebugTrace(0, Dbg, "Volume Guid (Key) is [%ws]\n", wszLvolKey);
  88. Status = KRegCreateKey( NULL, wszLvolKey );
  89. if (!NT_SUCCESS(Status)) {
  90. goto Cleanup;
  91. }
  92. //
  93. // Now, put the rest of the stuff in the registry for this local volume.
  94. // Entry Path
  95. // 8.3 Entry Path
  96. // Entry Type
  97. // Storage ID
  98. // Share Name
  99. // A separate key for each exit point.
  100. //
  101. DebugTrace(0, Dbg, "Entry path is %wZ\n", &pConfigInfo->RelationInfo.EntryId.Prefix);
  102. Status = DfspSavePrefix(
  103. wszLvolKey,
  104. wszEntryPath,
  105. &pConfigInfo->RelationInfo.EntryId.Prefix);
  106. if (!NT_SUCCESS(Status)) {
  107. DebugTrace(0, Dbg, "Error setting entry path in registry %08lx!\n", ULongToPtr( Status ));
  108. goto Cleanup;
  109. }
  110. DebugTrace(
  111. 0, Dbg, "Short Entry path is %wZ\n",
  112. &pConfigInfo->RelationInfo.EntryId.ShortPrefix);
  113. Status = DfspSavePrefix(
  114. wszLvolKey,
  115. wszShortEntryPath,
  116. &pConfigInfo->RelationInfo.EntryId.ShortPrefix);
  117. if (!NT_SUCCESS(Status)) {
  118. DebugTrace(0, Dbg, "Error setting short entry path in registry %08lx!\n", ULongToPtr( Status ));
  119. goto Cleanup;
  120. }
  121. DebugTrace(0, Dbg, "Entry type is %08lx\n", ULongToPtr( pConfigInfo->EntryType ));
  122. Status = KRegSetValue(
  123. wszLvolKey,
  124. wszEntryType,
  125. REG_DWORD,
  126. sizeof(ULONG),
  127. (PBYTE) &pConfigInfo->EntryType);
  128. if (!NT_SUCCESS(Status)) {
  129. DebugTrace(0, Dbg, "Error setting entry type in registry %08lx\n", ULongToPtr( Status ));
  130. goto Cleanup;
  131. }
  132. Status = KRegSetValue(
  133. wszLvolKey,
  134. wszServiceType,
  135. REG_DWORD,
  136. sizeof(ULONG),
  137. (PBYTE) &pConfigInfo->ServiceType);
  138. if (!NT_SUCCESS(Status)) {
  139. DebugTrace(0, Dbg, "Error setting service type in registry %08lx\n", ULongToPtr( Status ));
  140. goto Cleanup;
  141. }
  142. DebugTrace(0, Dbg, "Storage ID is %wZ\n", pustrStorageId);
  143. Status = KRegSetValue(
  144. wszLvolKey,
  145. wszStorageId,
  146. REG_SZ,
  147. pustrStorageId->Length,
  148. (PBYTE) pustrStorageId->Buffer);
  149. if (!NT_SUCCESS(Status)) {
  150. DebugTrace(0, Dbg, "Error setting storage id in registry %08lx\n", ULongToPtr( Status ));
  151. goto Cleanup;
  152. }
  153. DebugTrace(0, Dbg, "Share name is %wZ\n", &pConfigInfo->Share);
  154. Status = KRegSetValue(
  155. wszLvolKey,
  156. wszShareName,
  157. REG_SZ,
  158. pConfigInfo->Share.Length,
  159. (PVOID) pConfigInfo->Share.Buffer);
  160. if (!NT_SUCCESS(Status)) {
  161. DebugTrace(0, Dbg, "Error setting share name in registry %08lx\n", ULongToPtr( Status ));
  162. goto Cleanup;
  163. }
  164. for (i = pConfigInfo->RelationInfo.SubordinateIdCount;
  165. i != 0;
  166. i--) {
  167. Status = DfspAddSubordinateId(
  168. wszLvolKey,
  169. &pConfigInfo->RelationInfo.SubordinateIdList[i-1]);
  170. if (!NT_SUCCESS(Status)) {
  171. DebugTrace(0, Dbg, "Error %08lx adding subordinate info!\n", ULongToPtr( Status ));
  172. goto Cleanup;
  173. }
  174. DebugTrace(0, Dbg, "Successfully added subordinate info\n", 0);
  175. }
  176. Cleanup:
  177. if (!NT_SUCCESS(Status)) {
  178. //
  179. // We have to cleanup all the stuff we did if we failed somewhere.
  180. // This is easy - just delete the key we added for the local volume
  181. //
  182. NTSTATUS CleanupStatus;
  183. DebugTrace(0, Dbg, "Error occured, cleaning up...\n", 0);
  184. CleanupStatus = KRegDeleteKey( wszLvolKey );
  185. if (!NT_SUCCESS(CleanupStatus)) {
  186. //
  187. // We are hosed!
  188. //
  189. DebugTrace(0, Dbg, "Unable to cleanup %08lx!\n", ULongToPtr( CleanupStatus ));
  190. }
  191. }
  192. KRegCloseRoot();
  193. DebugTrace(-1, Dbg, "DfsStoreLvolInfo exited %08lx\n", ULongToPtr( Status ));
  194. return( Status );
  195. }
  196. //+----------------------------------------------------------------------------
  197. //
  198. // Function: DfsGetLvolInfo
  199. //
  200. // Synopsis: Retrieves local volume info from the registry given the key
  201. // identifying the local volume.
  202. //
  203. // Arguments: [pwszGuid] -- the string representation of the guid of the
  204. // volume.
  205. // [pRelationInfo] -- Pointer to relation info which will be
  206. // filled in. Note that the SubordinateIdList will
  207. // be allocated here, and must be freed by the
  208. // caller. Additionally, the buffers in the
  209. // individual prefixes are also allocated and must
  210. // be freed.
  211. //
  212. // Returns: NTSTATUS from reading the registry.
  213. //
  214. //-----------------------------------------------------------------------------
  215. NTSTATUS
  216. DfsGetLvolInfo(
  217. IN PWSTR pwszGuid,
  218. OUT PDFS_LOCAL_VOLUME_CONFIG pConfigInfo,
  219. OUT PUNICODE_STRING pustrStorageId)
  220. {
  221. NTSTATUS Status;
  222. PDFS_PKT_ENTRY_ID pid;
  223. PULONG pulEntryType = NULL;
  224. PULONG pulServiceType = NULL;
  225. ULONG i, cbSize;
  226. APWSTR awstrSubs = NULL;
  227. DebugTrace(+1, Dbg, "DfsGetLvolInfo: Entered for %ws\n", pwszGuid);
  228. //
  229. // First, initialize the pConfigInfo and pustrStorageId to NULL to
  230. // facilitate cleanup.
  231. //
  232. RtlZeroMemory((PVOID) pConfigInfo, sizeof(DFS_LOCAL_VOLUME_CONFIG));
  233. RtlZeroMemory((PVOID) pustrStorageId, sizeof(UNICODE_STRING));
  234. Status = KRegSetRoot(wszLocalVolumesSection);
  235. if (!NT_SUCCESS(Status)) {
  236. DebugTrace(-1, Dbg, "DfsGetLvolInfo: Error setting registry root %08lx!\n", ULongToPtr( Status ));
  237. return( Status );
  238. }
  239. //
  240. // Get the Entry ID - convert the wchar GUID to an actual GUID, and get
  241. // the entry path from the registry.
  242. //
  243. pid = &pConfigInfo->RelationInfo.EntryId;
  244. Status = DfspReadPrefix( pwszGuid, wszEntryPath, &pid->Prefix );
  245. DebugTrace(0, Dbg, "EntryPath is %wZ\n", &pid->Prefix);
  246. Status = DfspReadPrefix( pwszGuid, wszShortEntryPath, &pid->ShortPrefix );
  247. if (!NT_SUCCESS(Status)) {
  248. DebugTrace(-1, Dbg, "DfsGetLvolInfo: Error reading entry path %08lx\n", ULongToPtr( Status ));
  249. KRegCloseRoot();
  250. return( Status );
  251. }
  252. DebugTrace(0, Dbg, "8.3 EntryPath is %wZ\n", &pid->Prefix);
  253. StringToGuid( pwszGuid, &pid->Uid );
  254. //
  255. // Now get the Entry and Service Type
  256. //
  257. Status = KRegGetValue( pwszGuid, wszEntryType, (PBYTE *) &pulEntryType );
  258. if (!NT_SUCCESS(Status)) {
  259. DebugTrace(0, Dbg, "Error %08lx getting entry type\n", ULongToPtr( Status ));
  260. goto Cleanup;
  261. }
  262. pConfigInfo->EntryType = *pulEntryType;
  263. Status = KRegGetValue( pwszGuid, wszServiceType, (PBYTE *) &pulServiceType );
  264. if (!NT_SUCCESS(Status)) {
  265. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  266. pConfigInfo->ServiceType = 0;
  267. } else {
  268. DebugTrace(0, Dbg, "Error %08lx getting service type\n", ULongToPtr( Status ));
  269. goto Cleanup;
  270. }
  271. } else {
  272. pConfigInfo->ServiceType = *pulServiceType;
  273. }
  274. //
  275. // Next, get the Storage ID
  276. //
  277. Status = KRegGetValue( pwszGuid, wszStorageId, (PBYTE *) &pustrStorageId->Buffer);
  278. if (!NT_SUCCESS(Status)) {
  279. DebugTrace(0, Dbg, "Error %08lx getting storage id from registry\n", ULongToPtr( Status ));
  280. goto Cleanup;
  281. }
  282. pustrStorageId->Length = wcslen(pustrStorageId->Buffer) * sizeof(WCHAR);
  283. pustrStorageId->MaximumLength = pustrStorageId->Length + sizeof(WCHAR);
  284. DebugTrace(0, Dbg, "Storage id is %wZ\n", pustrStorageId);
  285. //
  286. // Next, get the share name
  287. //
  288. Status = KRegGetValue( pwszGuid, wszShareName, (PBYTE *) &pConfigInfo->Share.Buffer);
  289. if (!NT_SUCCESS(Status)) {
  290. DebugTrace(0, Dbg, "Error %08lx getting share name from registry\n", ULongToPtr( Status ));
  291. goto Cleanup;
  292. }
  293. pConfigInfo->Share.Length = wcslen(pConfigInfo->Share.Buffer) * sizeof(WCHAR);
  294. pustrStorageId->MaximumLength = pConfigInfo->Share.Length + sizeof(WCHAR);
  295. DebugTrace(0, Dbg, "Share Nameis %wZ\n", &pConfigInfo->Share);
  296. //
  297. // We have the volumes PKT_ENTRY_ID. Now, figure out how many
  298. // subordinates there are, and get them.
  299. //
  300. Status = KRegEnumSubKeySet(
  301. pwszGuid,
  302. &pConfigInfo->RelationInfo.SubordinateIdCount,
  303. &awstrSubs);
  304. if (!NT_SUCCESS(Status)) {
  305. DebugTrace(0, Dbg, "DfsGetLvolInfo: Error getting subkeys %08lx\n", ULongToPtr( Status ));
  306. goto Cleanup;
  307. }
  308. DebugTrace(0, Dbg, "Volume has %d subordinates\n", ULongToPtr( pConfigInfo->RelationInfo.SubordinateIdCount ));
  309. if (pConfigInfo->RelationInfo.SubordinateIdCount == 0) {
  310. DebugTrace(-1, Dbg, "DfsGetLvolInfo: No subordinates! Returning success\n", 0);
  311. Status = STATUS_SUCCESS;
  312. goto Cleanup;
  313. }
  314. cbSize = pConfigInfo->RelationInfo.SubordinateIdCount * sizeof(DFS_PKT_ENTRY_ID);
  315. pConfigInfo->RelationInfo.SubordinateIdList = ExAllocatePoolWithTag(
  316. PagedPool,
  317. cbSize,
  318. ' sfD' );
  319. if (pConfigInfo->RelationInfo.SubordinateIdList == NULL) {
  320. DebugTrace(0, Dbg, "DfsGetLvolInfo: Unable to allocate %d bytes!\n", ULongToPtr( cbSize ));
  321. Status = STATUS_INSUFFICIENT_RESOURCES;
  322. goto Cleanup;
  323. }
  324. RtlZeroMemory(pConfigInfo->RelationInfo.SubordinateIdList, cbSize);
  325. //
  326. // Get all the Subordinate information
  327. //
  328. for (i = pConfigInfo->RelationInfo.SubordinateIdCount; i != 0; i--) {
  329. PWSTR pwszSubordinateGuid;
  330. pid = &pConfigInfo->RelationInfo.SubordinateIdList[i-1];
  331. //
  332. // awstrSubs[?] is of the form lvolguid\subordinateguid.
  333. //
  334. pwszSubordinateGuid = &awstrSubs[i-1][2 * sizeof(GUID) + 1];
  335. DebugTrace(0, Dbg, "Subordinate Guid is %ws\n", pwszSubordinateGuid);
  336. StringToGuid( pwszSubordinateGuid, &pid->Uid );
  337. DebugTrace(0, Dbg, "Subkey is %ws\n", awstrSubs[i-1]);
  338. Status = DfspReadPrefix(
  339. awstrSubs[i-1],
  340. wszEntryPath,
  341. &pid->Prefix);
  342. if (!NT_SUCCESS(Status)) {
  343. DebugTrace(0, Dbg, "Error %08lx reading subordinate prefix\n", ULongToPtr( Status ));
  344. goto Cleanup;
  345. }
  346. DebugTrace(0, Dbg, "Retrieved Subordinate Entry %ws\n", awstrSubs[i-1]);
  347. DebugTrace(0, Dbg, "Prefix is %wZ\n", &pid->Prefix);
  348. }
  349. Cleanup:
  350. KRegCloseRoot();
  351. if (pulEntryType) {
  352. ExFreePool( pulEntryType );
  353. }
  354. if (pulServiceType) {
  355. ExFreePool( pulServiceType );
  356. }
  357. if (!NT_SUCCESS(Status)) {
  358. //
  359. // Cleanup whatever relation info we might have built up so far.
  360. //
  361. KRegFreeArray(
  362. pConfigInfo->RelationInfo.SubordinateIdCount,
  363. (APBYTE) awstrSubs);
  364. if (pConfigInfo->RelationInfo.EntryId.Prefix.Buffer != NULL) {
  365. ExFreePool(pConfigInfo->RelationInfo.EntryId.Prefix.Buffer);
  366. }
  367. if (pustrStorageId->Buffer != NULL) {
  368. ExFreePool(pustrStorageId->Buffer);
  369. }
  370. for (i = pConfigInfo->RelationInfo.SubordinateIdCount; i != 0; i--) {
  371. pid = &pConfigInfo->RelationInfo.SubordinateIdList[i-1];
  372. if (pid->Prefix.Buffer != NULL) {
  373. ExFreePool( pid->Prefix.Buffer );
  374. }
  375. }
  376. if (pConfigInfo->RelationInfo.SubordinateIdList != NULL) {
  377. ExFreePool(pConfigInfo->RelationInfo.SubordinateIdList);
  378. }
  379. } else {
  380. KRegFreeArray(
  381. pConfigInfo->RelationInfo.SubordinateIdCount,
  382. (APBYTE) awstrSubs);
  383. }
  384. DebugTrace(-1, Dbg, "DfsGetLvolInfo: Exited - %08lx\n", ULongToPtr( Status ) );
  385. return( Status );
  386. }
  387. //+----------------------------------------------------------------------------
  388. //
  389. // Function: DfsDeleteLvolInfo
  390. //
  391. // Synopsis: Deletes local volume information from the registry.
  392. //
  393. // Arguments: [pguidLvol] -- pointer to guid of local volume to delete.
  394. //
  395. // Returns: NTSTATUS from registry API
  396. //
  397. //-----------------------------------------------------------------------------
  398. NTSTATUS
  399. DfsDeleteLvolInfo(
  400. IN GUID *pguidLvol)
  401. {
  402. NTSTATUS Status;
  403. WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
  404. DebugTrace(+1, Dbg, "DfsDeleteLvolInfo - Entered\n", 0);
  405. GuidToString(pguidLvol, wszLvolKey);
  406. Status = KRegSetRoot( wszLocalVolumesSection );
  407. if (!NT_SUCCESS(Status)) {
  408. DebugTrace(-1, Dbg, "DfsDeleteLvolInfo - Error %08lx opening local volumes section\n", ULongToPtr( Status ));
  409. return(Status);
  410. }
  411. Status = KRegDeleteKey( wszLvolKey );
  412. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  413. Status = STATUS_SUCCESS;
  414. }
  415. KRegCloseRoot();
  416. DebugTrace(-1, Dbg, "DfsDeleteLvolInfo - Exiting %08lx\n", ULongToPtr( Status ));
  417. return( Status );
  418. }
  419. //+----------------------------------------------------------------------------
  420. //
  421. // Function: DfsChangeLvolInfoServiceType
  422. //
  423. // Synopsis: Changes the service type associated with the local volume in
  424. // the registry.
  425. //
  426. // Arguments: [pguidLvol] -- pointer to guid of local volume.
  427. // [ulServiceType] -- new service type.
  428. //
  429. // Returns: NTSTATUS from registry api.
  430. //
  431. //-----------------------------------------------------------------------------
  432. NTSTATUS
  433. DfsChangeLvolInfoServiceType(
  434. IN GUID *pguidLvol,
  435. IN ULONG ulServiceType)
  436. {
  437. NTSTATUS Status;
  438. WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
  439. Status = KRegSetRoot( wszLocalVolumesSection );
  440. if (!NT_SUCCESS(Status)) {
  441. return( Status );
  442. }
  443. GuidToString(pguidLvol, wszLvolKey);
  444. Status = KRegSetValue(
  445. wszLvolKey,
  446. wszServiceType,
  447. REG_DWORD,
  448. sizeof(ULONG),
  449. (PBYTE) &ulServiceType);
  450. KRegCloseRoot();
  451. return( Status );
  452. }
  453. //+----------------------------------------------------------------------------
  454. //
  455. // Function: DfsChangeLvolInfoEntryPath
  456. //
  457. // Synopsis: Changes the entry path associated with the local volume in the
  458. // registry.
  459. //
  460. // Arguments: [pguidLvol] -- pointer to guid of local volume.
  461. // [pustrEntryPath] -- new entry path.
  462. //
  463. // Returns: NTSTATUS from registry api.
  464. //
  465. //-----------------------------------------------------------------------------
  466. NTSTATUS
  467. DfsChangeLvolInfoEntryPath(
  468. IN GUID *pguidLvol,
  469. IN PUNICODE_STRING pustrEntryPath)
  470. {
  471. NTSTATUS Status;
  472. WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
  473. Status = KRegSetRoot( wszLocalVolumesSection );
  474. if (!NT_SUCCESS(Status)) {
  475. return( Status );
  476. }
  477. GuidToString(pguidLvol, wszLvolKey);
  478. Status = DfspSavePrefix(
  479. wszLvolKey,
  480. wszEntryPath,
  481. pustrEntryPath);
  482. KRegCloseRoot();
  483. return( Status );
  484. }
  485. //+----------------------------------------------------------------------------
  486. //
  487. // Function: DfsCreateExitPointInfo
  488. //
  489. // Synopsis: Adds a single exit point to the local volume information in
  490. // the registry.
  491. //
  492. // Arguments: [pguidLvol] -- pointer to guid of local volume.
  493. // [pidExitPoint] -- pointer to PKT_ENTRY_ID of exit point.
  494. //
  495. // Returns: NTSTATUS from registry manipulation.
  496. //
  497. //-----------------------------------------------------------------------------
  498. NTSTATUS
  499. DfsCreateExitPointInfo(
  500. IN GUID *pguidLvol,
  501. IN PDFS_PKT_ENTRY_ID pidExitPoint)
  502. {
  503. NTSTATUS Status = STATUS_SUCCESS;
  504. WCHAR wszLvolKey[ 2 * sizeof(GUID) + 1 ];
  505. DebugTrace(+1, Dbg, "DfsCreateExitPointInfo - Entered\n", 0);
  506. //
  507. // Stop storing exit point information in the SYSTEM part of
  508. // the registry. (380845).
  509. //
  510. #if 0
  511. Status = KRegSetRoot( wszLocalVolumesSection );
  512. if (!NT_SUCCESS(Status)) {
  513. DebugTrace(-1, Dbg, "DfsCreateExitPointInfo - exiting %08lx\n", Status);
  514. return(Status);
  515. }
  516. GuidToString( pguidLvol, wszLvolKey );
  517. Status = DfspAddSubordinateId( wszLvolKey, pidExitPoint );
  518. KRegCloseRoot();
  519. #endif
  520. DebugTrace(-1, Dbg, "DfsCreateExitPointInfo - Exited %08lx\n", ULongToPtr( Status ));
  521. return( Status );
  522. }
  523. //+----------------------------------------------------------------------------
  524. //
  525. // Function: DfsDeleteExitPointInfo
  526. //
  527. // Synopsis: Deletes an exit point info from the registry.
  528. //
  529. // Arguments: [pguidLvol] -- pointer to guid of local volume.
  530. // [pguidExitPoint] -- pointer to guid of exit point.
  531. //
  532. // Returns: NTSTATUS from registry api.
  533. //
  534. //-----------------------------------------------------------------------------
  535. NTSTATUS
  536. DfsDeleteExitPointInfo(
  537. IN GUID *pguidLvol,
  538. IN GUID *pguidExitPoint)
  539. {
  540. NTSTATUS Status = STATUS_SUCCESS;
  541. WCHAR wszExitPointKey[ 2 * sizeof(GUID) + // for Local volume guid
  542. 1 + // for UNICODE_PATH_SEP
  543. 2 * sizeof(GUID) + // for exit point guid
  544. 1 ]; // for UNICODE_NULL
  545. DebugTrace(+1, Dbg, "DfsDeleteExitPointInfo: Entered\n", 0);
  546. //
  547. // Stop storing exit point information in the SYSTEM part of
  548. // the registry. (380845).
  549. //
  550. #if 0
  551. Status = KRegSetRoot( wszLocalVolumesSection );
  552. if (!NT_SUCCESS(Status)) {
  553. DebugTrace(-1, Dbg, "DfsDeleteExitPointInfo: Exiting %08lx\n", Status);
  554. return( Status );
  555. }
  556. GuidToString( pguidLvol, wszExitPointKey );
  557. wszExitPointKey[ 2 * sizeof(GUID) ] = UNICODE_PATH_SEP;
  558. GuidToString( pguidExitPoint, &wszExitPointKey[2*sizeof(GUID) + 1] );
  559. DebugTrace(0, Dbg, "Attempting to delete subkey %ws\n", wszExitPointKey);
  560. Status = KRegDeleteKey( wszExitPointKey );
  561. KRegCloseRoot();
  562. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  563. Status = STATUS_SUCCESS;
  564. }
  565. #endif
  566. DebugTrace(-1, Dbg, "DfsDeleteExitPointInfo: Exiting %08lx\n", ULongToPtr( Status ));
  567. return( Status );
  568. }
  569. //+----------------------------------------------------------------------------
  570. //
  571. // Function: DfspAddSubordinateId
  572. //
  573. // Synopsis: Adds a single exit point info to a local volume entry in the
  574. // registry.
  575. //
  576. // Arguments: [wszLvolKey] -- The local volume key under which to add info.
  577. // [pId] -- The info to add.
  578. //
  579. // Returns: NT Status from adding the info.
  580. //
  581. //-----------------------------------------------------------------------------
  582. NTSTATUS
  583. DfspAddSubordinateId(
  584. IN PWSTR wszLvolKey,
  585. IN PDFS_PKT_ENTRY_ID pId)
  586. {
  587. NTSTATUS Status;
  588. WCHAR wszExitPoint[ 2 * sizeof(GUID) + 1 ];
  589. WCHAR wszExitPointKey[ 2 * sizeof(GUID) +
  590. sizeof(UNICODE_PATH_SEP_STR) +
  591. 2 * sizeof(GUID) +
  592. sizeof(UNICODE_NULL) ];
  593. GuidToString( &pId->Uid, wszExitPoint );
  594. DebugTrace(0, Dbg, "Adding exit point key %ws\n", wszExitPoint);
  595. Status = KRegCreateKey(wszLvolKey, wszExitPoint);
  596. if (!NT_SUCCESS(Status)) {
  597. DebugTrace(0, Dbg, "Error adding exit pt key %08lx\n", ULongToPtr( Status ));
  598. return(Status);
  599. }
  600. //
  601. // Now, add the entry path for the exit point as a value to the
  602. // new key.
  603. //
  604. wcscpy(wszExitPointKey, wszLvolKey);
  605. wcscat(wszExitPointKey, UNICODE_PATH_SEP_STR);
  606. wcscat(wszExitPointKey, wszExitPoint);
  607. DebugTrace(0, Dbg, "Subkey name is %ws\n", wszExitPointKey);
  608. DebugTrace(0, Dbg, "Prefix is %wZ\n", &pId->Prefix);
  609. Status = DfspSavePrefix(
  610. wszExitPointKey,
  611. wszEntryPath,
  612. &pId->Prefix);
  613. if (!NT_SUCCESS(Status)) {
  614. KRegDeleteKey(wszExitPointKey);
  615. }
  616. return(Status);
  617. }
  618. //+----------------------------------------------------------------------------
  619. //
  620. // Function: DfspReadPrefix
  621. //
  622. // Synopsis: Reads a prefix from the registry, given the registry key and
  623. // value name. To handle machine renames, the first component
  624. // of the prefix is matched against the current computer name.
  625. // If the two are different, indicating a computer name change,
  626. // the prefix is updated.
  627. //
  628. // Arguments: [wszKey] -- Name of key (relative to current root)
  629. // [wszValue] -- Name of value to read prefix from
  630. // [pustrPrefix] -- On successful return, the prefix is returned
  631. // here.
  632. //
  633. // Returns: [STATUS_SUCCESS] -- If successfully retrieved prefix.
  634. //
  635. // [STATUS_INSUFFICIENT_RESOURCES] -- Unable to allocate memory
  636. //
  637. // [STATUS_INTERNAL_DB_CORRUPTION] -- The retrieved value did
  638. // not look like a prefix.
  639. //
  640. // Status from reading the registry value
  641. //
  642. //-----------------------------------------------------------------------------
  643. NTSTATUS
  644. DfspReadPrefix(
  645. IN PWSTR wszKey,
  646. IN PWSTR wszValue,
  647. OUT PUNICODE_STRING pustrPrefix)
  648. {
  649. NTSTATUS Status;
  650. PWSTR wszCurrentPrefix = NULL;
  651. ULONG cbPrefix, cwCurrentPrefix, i;
  652. UNICODE_STRING ustrComputerName;
  653. Status = KRegGetValue(
  654. wszKey,
  655. wszValue,
  656. (LPBYTE *)&wszCurrentPrefix );
  657. //
  658. // If successfully read in the prefix, do some elementary syntax checking
  659. //
  660. if (NT_SUCCESS(Status)) {
  661. cwCurrentPrefix = wcslen(wszCurrentPrefix);
  662. cbPrefix = cwCurrentPrefix * sizeof(WCHAR);
  663. //
  664. // Must be atleast \a\b
  665. //
  666. if ((cwCurrentPrefix < 4) ||
  667. (wszCurrentPrefix[0] != UNICODE_PATH_SEP)) {
  668. Status = STATUS_INTERNAL_DB_CORRUPTION;
  669. }
  670. }
  671. //
  672. // Compute the first component of the prefix
  673. //
  674. if (NT_SUCCESS(Status)) {
  675. ustrComputerName.Buffer = &wszCurrentPrefix[1];
  676. for (i = 1;
  677. (i < cwCurrentPrefix) &&
  678. (wszCurrentPrefix[i] != UNICODE_PATH_SEP);
  679. i++) {
  680. NOTHING;
  681. }
  682. if (i != cwCurrentPrefix) {
  683. ustrComputerName.Length = (USHORT) ((i-1) * sizeof(WCHAR));
  684. ustrComputerName.MaximumLength = ustrComputerName.Length;
  685. } else {
  686. Status = STATUS_INTERNAL_DB_CORRUPTION;
  687. }
  688. }
  689. if (NT_SUCCESS(Status)) {
  690. pustrPrefix->Buffer = wszCurrentPrefix;
  691. pustrPrefix->Length = (USHORT) cbPrefix;
  692. pustrPrefix->MaximumLength = (USHORT)cbPrefix + sizeof(UNICODE_NULL);
  693. } else {
  694. if (wszCurrentPrefix != NULL)
  695. kreg_free( wszCurrentPrefix );
  696. }
  697. return( Status );
  698. }
  699. //+----------------------------------------------------------------------------
  700. //
  701. // Function: DfspSavePrefix
  702. //
  703. // Synopsis: Saves a prefix to the registry.
  704. //
  705. // Arguments: [wszKey] -- Name of key (relative to current root)
  706. // [wszValue] -- Name of value to save prefix to.
  707. // [pustrPrefix] -- The prefix to store.
  708. //
  709. // Returns: Status from registry operation
  710. //
  711. //-----------------------------------------------------------------------------
  712. NTSTATUS
  713. DfspSavePrefix(
  714. IN PWSTR wszKey,
  715. IN PWSTR wszValue,
  716. IN PUNICODE_STRING pustrPrefix)
  717. {
  718. NTSTATUS Status;
  719. Status = KRegSetValue(
  720. wszKey,
  721. wszValue,
  722. REG_SZ,
  723. pustrPrefix->Length,
  724. (LPBYTE) pustrPrefix->Buffer);
  725. return( Status );
  726. }
  727. //+----------------------------------------------------------------------------
  728. //
  729. // Function: DfspUpgradePrefix
  730. //
  731. // Synopsis: If a machine rename has occured since the last time a prefix
  732. // was updated, this routine will upgrade the first component
  733. // of the prefix to match the computer name.
  734. //
  735. // Arguments: [wszKey] -- Name of key (relative to current root)
  736. // [wszValue] -- Name of value to save updated prefix to.
  737. // [cbComputerName] -- size, in bytes, of the first component of
  738. // the input prefix.
  739. // [pcbPrefix] -- On entry, size in bytes of the input prefix.
  740. // On return, size in bytes of the new prefix. Neither
  741. // sizes includes the terminating NULL.
  742. // [pwszPrefix] -- On entry, the prefix as it currently exists in
  743. // the registry. On return, points to a new block of
  744. // memory that has the new prefix.
  745. //
  746. // Returns: [STATUS_SUCCESS] -- Successfully updated prefix.
  747. //
  748. // [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition
  749. //
  750. //-----------------------------------------------------------------------------
  751. NTSTATUS
  752. DfspUpgradePrefix(
  753. IN PWSTR wszKey,
  754. IN PWSTR wszValue,
  755. IN USHORT cbComputerName,
  756. IN PULONG pcbPrefix,
  757. IN OUT PWSTR *pwszPrefix)
  758. {
  759. NTSTATUS Status;
  760. ULONG cbPrefix;
  761. PWSTR wszCurrentPrefix, wszNewPrefix;
  762. wszCurrentPrefix = *pwszPrefix;
  763. cbPrefix = (*pcbPrefix) -
  764. cbComputerName +
  765. DfsData.NetBIOSName.Length;
  766. wszNewPrefix = (PWSTR) kreg_alloc( cbPrefix + sizeof(UNICODE_NULL) );
  767. if (wszNewPrefix != NULL) {
  768. wszNewPrefix[0] = UNICODE_PATH_SEP;
  769. RtlCopyMemory(
  770. &wszNewPrefix[1],
  771. DfsData.NetBIOSName.Buffer,
  772. DfsData.NetBIOSName.Length);
  773. RtlCopyMemory(
  774. &wszNewPrefix[ DfsData.NetBIOSName.Length/sizeof(WCHAR) + 1],
  775. &wszCurrentPrefix[ cbComputerName/sizeof(WCHAR) + 1 ],
  776. (*pcbPrefix) - cbComputerName);
  777. *pcbPrefix = cbPrefix;
  778. *pwszPrefix = wszNewPrefix;
  779. kreg_free( wszCurrentPrefix );
  780. //
  781. // We try to update the prefix in the registry. Failure to do so is
  782. // ok, we'll just try again next time we try to read it.
  783. //
  784. (VOID) KRegSetValue(
  785. wszKey,
  786. wszValue,
  787. REG_SZ,
  788. cbPrefix,
  789. (LPBYTE) wszNewPrefix);
  790. Status = STATUS_SUCCESS;
  791. } else {
  792. Status = STATUS_INSUFFICIENT_RESOURCES;
  793. }
  794. return( Status );
  795. }
  796. //+----------------------------------------------------------------------------
  797. //
  798. // Function: GuidToString
  799. //
  800. // Synopsis: Converts a GUID to a 32 char wchar null terminated string.
  801. //
  802. // Arguments: [pGuid] -- Pointer to Guid structure.
  803. // [pwszGuid] -- wchar buffer into which to put the string
  804. // representation of the GUID. Must be atleast
  805. // 2 * sizeof(GUID) + 1 long.
  806. //
  807. // Returns: Nothing
  808. //
  809. //-----------------------------------------------------------------------------
  810. const WCHAR rgwchHexDigits[] = L"0123456789ABCDEF";
  811. VOID GuidToString(
  812. IN GUID *pGuid,
  813. OUT PWSTR pwszGuid)
  814. {
  815. PBYTE pbBuffer = (PBYTE) pGuid;
  816. USHORT i;
  817. for(i = 0; i < sizeof(GUID); i++) {
  818. pwszGuid[2 * i] = rgwchHexDigits[(pbBuffer[i] >> 4) & 0xF];
  819. pwszGuid[2 * i + 1] = rgwchHexDigits[pbBuffer[i] & 0xF];
  820. }
  821. pwszGuid[2 * i] = UNICODE_NULL;
  822. }
  823. //+----------------------------------------------------------------------------
  824. //
  825. // Function: StringToGuid
  826. //
  827. // Synopsis: Converts a 32 wchar null terminated string to a GUID.
  828. //
  829. // Arguments: [pwszGuid] -- the string to convert
  830. // [pGuid] -- Pointer to destination GUID.
  831. //
  832. // Returns: Nothing
  833. //
  834. //-----------------------------------------------------------------------------
  835. #define HEX_DIGIT_TO_INT(d, i) \
  836. ASSERT(((d) >= L'0' && (d) <= L'9') || \
  837. ((d) >= L'A' && (d) <= L'F')); \
  838. if ((d) <= L'9') { \
  839. i = (d) - L'0'; \
  840. } else { \
  841. i = (d) - L'A' + 10; \
  842. }
  843. VOID StringToGuid(
  844. IN PWSTR pwszGuid,
  845. OUT GUID *pGuid)
  846. {
  847. PBYTE pbBuffer = (PBYTE) pGuid;
  848. USHORT i, n;
  849. for (i = 0; i < sizeof(GUID); i++) {
  850. HEX_DIGIT_TO_INT(pwszGuid[2 * i], n);
  851. pbBuffer[i] = n << 4;
  852. HEX_DIGIT_TO_INT(pwszGuid[2 * i + 1], n);
  853. pbBuffer[i] |= n;
  854. }
  855. }