Leaked source code of windows server 2003
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.

412 lines
11 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spdrmmgr.c
  5. Abstract:
  6. Revision History:
  7. Initial Code Michael Peterson (v-michpe) 13.Dec.1997
  8. Code cleanup and changes Guhan Suriyanarayanan (guhans) 21.Aug.1999
  9. --*/
  10. #include "spprecmp.h"
  11. #pragma hdrstop
  12. #define THIS_MODULE L"spdrmmgr.c"
  13. #define THIS_MODULE_CODE L"M"
  14. #define DOS_DEVICES L"\\DosDevices\\?:"
  15. #define DOS_DEVICES_DRV_LTR_POS 12
  16. typedef struct _NAMETABLE {
  17. ULONG Elements;
  18. PWSTR SymbolicName[1];
  19. } NAMETABLE, *PNAMETABLE;
  20. // Imported from sppartit.c
  21. extern WCHAR
  22. SpDeleteDriveLetter(IN PWSTR DeviceName);
  23. NTSTATUS
  24. SpAsrOpenMountManager(
  25. OUT HANDLE *Handle
  26. )
  27. {
  28. NTSTATUS status = STATUS_SUCCESS;
  29. IO_STATUS_BLOCK ioStatusBlock;
  30. OBJECT_ATTRIBUTES objectAttributes;
  31. UNICODE_STRING unicodeString;
  32. INIT_OBJA(&objectAttributes, &unicodeString, MOUNTMGR_DEVICE_NAME);
  33. status = ZwOpenFile(Handle,
  34. (ACCESS_MASK)(FILE_GENERIC_READ),
  35. &objectAttributes,
  36. &ioStatusBlock,
  37. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE ,
  38. FILE_NON_DIRECTORY_FILE
  39. );
  40. if (!NT_SUCCESS(status)) {
  41. DbgErrorMesg((_asrerr, "Could not open the mount manager (0x%x). \n", status));
  42. ASSERT(0 && L"Could not open mount manager");
  43. }
  44. return status;
  45. }
  46. VOID
  47. SpAsrAllocateMountPointForCreate(
  48. IN PWSTR PartitionDeviceName,
  49. IN PWSTR MountPointNameString,
  50. OUT PMOUNTMGR_CREATE_POINT_INPUT *pMpt,
  51. OUT ULONG *MountPointSize
  52. )
  53. {
  54. PMOUNTMGR_CREATE_POINT_INPUT pMountPoint = NULL;
  55. *pMpt = NULL;
  56. *MountPointSize = sizeof(MOUNTMGR_CREATE_POINT_INPUT) +
  57. (wcslen(PartitionDeviceName) + wcslen(MountPointNameString)) * sizeof(WCHAR);
  58. pMountPoint = (PMOUNTMGR_CREATE_POINT_INPUT) SpAsrMemAlloc(*MountPointSize, TRUE); // does not return on failure
  59. pMountPoint->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
  60. pMountPoint->SymbolicLinkNameLength = wcslen(MountPointNameString) * sizeof(WCHAR);
  61. RtlCopyMemory(((PCHAR) pMountPoint + pMountPoint->SymbolicLinkNameOffset),
  62. MountPointNameString,
  63. pMountPoint->SymbolicLinkNameLength
  64. );
  65. pMountPoint->DeviceNameLength = (USHORT) (wcslen(PartitionDeviceName) * sizeof(WCHAR));
  66. pMountPoint->DeviceNameOffset = (USHORT) pMountPoint->SymbolicLinkNameOffset +
  67. pMountPoint->SymbolicLinkNameLength;
  68. RtlCopyMemory(((PCHAR)pMountPoint + pMountPoint->DeviceNameOffset),
  69. PartitionDeviceName,
  70. pMountPoint->DeviceNameLength
  71. );
  72. *pMpt = pMountPoint;
  73. }
  74. NTSTATUS
  75. SpAsrCreateMountPoint(
  76. IN PWSTR PartitionDeviceName,
  77. IN PWSTR MountPointNameString
  78. )
  79. /*++
  80. Description:
  81. Creates the specified mount point for the specified partition region.
  82. These strings will usually be in the form of a symbolic names, such as:
  83. "\DosDevices\?:"
  84. Where ? can be any supported drive letter,
  85. or,
  86. a GUID string in the form of, for example:
  87. "\??\Volume{1234abcd-1234-5678-abcd-000000000000}"
  88. Arguments:
  89. PartitionDeviceName Specifies the partitioned region portion of the
  90. mount point.
  91. MountPointNameString Specifies the symbolic name to be associated with
  92. the specified partition.
  93. Returns:
  94. NTSTATUS
  95. --*/
  96. {
  97. NTSTATUS status = STATUS_SUCCESS;
  98. IO_STATUS_BLOCK ioStatusBlock;
  99. HANDLE handle = NULL;
  100. ULONG mountPointSize = 0;
  101. PMOUNTMGR_CREATE_POINT_INPUT pMountPoint = NULL;
  102. //
  103. // Create the input structure.
  104. //
  105. SpAsrAllocateMountPointForCreate(PartitionDeviceName,
  106. MountPointNameString,
  107. &pMountPoint,
  108. &mountPointSize
  109. );
  110. status = SpAsrOpenMountManager(&handle);
  111. if (!NT_SUCCESS(status)) {
  112. DbgFatalMesg((_asrerr, "SpAsrCreateMountPoint([%ws],[%ws]). SpAsrOpenMountManager failed (0x%x). mountPointSize:%lu handle:0x%x.\n",
  113. PartitionDeviceName,
  114. MountPointNameString,
  115. status,
  116. mountPointSize,
  117. handle
  118. ));
  119. SpMemFree(pMountPoint);
  120. //
  121. // There's nothing the user can do in this case.
  122. //
  123. INTERNAL_ERROR(L"SpAsrOpenMountManager() Failed"); // ok
  124. // does not return
  125. }
  126. //
  127. // IOCTL_CREATE_POINT
  128. //
  129. status = ZwDeviceIoControlFile(handle,
  130. NULL,
  131. NULL,
  132. NULL,
  133. &ioStatusBlock,
  134. IOCTL_MOUNTMGR_CREATE_POINT,
  135. pMountPoint,
  136. mountPointSize,
  137. NULL,
  138. 0
  139. );
  140. if (!NT_SUCCESS(status)) {
  141. //
  142. // We couldn't restore the volume guid for this volume. This is expected if the
  143. // volume is on a non-critical disk--we only recreate critical disks in textmode
  144. // Setup.
  145. //
  146. DbgErrorMesg((_asrwarn, "SpAsrCreateMountPoint([%ws], [%ws]). ZwDeviceIoControlFile(IOCTL_MOUNTMGR_CREATE_POINT) failed (0x%x). handle:0x%x, pMountPoint:0x%x, mountPointSize:0x%x\n",
  147. PartitionDeviceName,
  148. MountPointNameString,
  149. status,
  150. handle,
  151. pMountPoint,
  152. mountPointSize
  153. ));
  154. }
  155. SpMemFree(pMountPoint);
  156. ZwClose(handle);
  157. return status;
  158. }
  159. //////////////////////////////////////////////////////////////////////////////
  160. // EXPORTED FUNCTIONS //
  161. //////////////////////////////////////////////////////////////////////////////
  162. NTSTATUS
  163. SpAsrSetPartitionDriveLetter(
  164. IN PDISK_REGION pRegion,
  165. IN WCHAR NewDriveLetter
  166. )
  167. /*++
  168. Description:
  169. Checks whether a drive letter exists for the specified partitioned region.
  170. If one does, then if the existing drive letter is the same as the
  171. specified drive letter, return STATUS_SUCCESS. If the existing drive
  172. letter is different from that specified by the caller, delete and recreate
  173. the region's mount point using the symbolic name built from the drive letter
  174. parameter.
  175. Arguments:
  176. pRegion A pointer to a partitioned region descriptor.
  177. NewDriveLetter Specifies the drive letter to be assigned to the region.
  178. Returns:
  179. NTSTATUS
  180. --*/
  181. {
  182. NTSTATUS status = STATUS_UNSUCCESSFUL;
  183. WCHAR existingDriveLetter = 0;
  184. PWSTR partitionDeviceName = NULL;
  185. PWSTR symbolicName = NULL;
  186. //
  187. // Check input parameters: these better be valid
  188. //
  189. if (!pRegion || !SPPT_IS_REGION_PARTITIONED(pRegion)) {
  190. DbgErrorMesg((_asrwarn,
  191. "SpAsrSetPartitionDriveLetter. Invalid Parameter, pRegion %p is NULL or not partitioned.\n",
  192. pRegion
  193. ));
  194. ASSERT(0 && L"Invalid Parameter, pRegion is NULL or not partitioned."); // debug
  195. return STATUS_INVALID_PARAMETER;
  196. }
  197. if (NewDriveLetter < ((!IsNEC_98) ? L'C' : L'A') || NewDriveLetter > L'Z') {
  198. DbgErrorMesg((_asrwarn, "SpAsrSetPartitionDriveLetter. Invalid Parameter, NewDriveLetter [%wc].\n", NewDriveLetter));
  199. ASSERT(0 && L"Invalid Parameter, NewDriveLetter"); // debug
  200. return STATUS_INVALID_PARAMETER;
  201. }
  202. //
  203. // Check if the drive letter already exists
  204. //
  205. partitionDeviceName = SpAsrGetRegionName(pRegion);
  206. existingDriveLetter = SpGetDriveLetter(partitionDeviceName, NULL);
  207. if (NewDriveLetter == existingDriveLetter) {
  208. DbgStatusMesg((_asrinfo,
  209. "SpAsrSetPartitionDriveLetter. Ptn [%ws] already has drv letter %wc.\n",
  210. partitionDeviceName,
  211. NewDriveLetter
  212. ));
  213. SpMemFree(partitionDeviceName);
  214. return STATUS_SUCCESS;
  215. }
  216. //
  217. // The existing drive letter does not match. Delete it.
  218. //
  219. if (existingDriveLetter) {
  220. DbgStatusMesg((_asrinfo,
  221. "SpAsrSetPartitionDriveLetter. [%ws] has driveLetter %wc, deleting.\n",
  222. partitionDeviceName,
  223. existingDriveLetter
  224. ));
  225. SpDeleteDriveLetter(partitionDeviceName);
  226. }
  227. symbolicName = SpDupStringW(DOS_DEVICES);
  228. pRegion->DriveLetter = symbolicName[DOS_DEVICES_DRV_LTR_POS] = NewDriveLetter;
  229. //
  230. // Create the mount point with the correct drive letter
  231. //
  232. status = SpAsrCreateMountPoint(partitionDeviceName, symbolicName);
  233. if (NT_SUCCESS(status)) {
  234. DbgStatusMesg((_asrinfo,
  235. "SpAsrSetPartitionDriveLetter. [%ws] is drive %wc.\n",
  236. partitionDeviceName,
  237. NewDriveLetter
  238. ));
  239. }
  240. else {
  241. DbgErrorMesg((_asrwarn,
  242. "SpAsrSetPartitionDriveLetter. SpAsrCreateMountPoint([%ws],[%ws]) failed (0x%x). Drive letter %wc not assigned to [%ws].\n",
  243. partitionDeviceName,
  244. symbolicName,
  245. status,
  246. NewDriveLetter,
  247. partitionDeviceName
  248. ));
  249. }
  250. SpMemFree(partitionDeviceName);
  251. SpMemFree(symbolicName);
  252. return status;
  253. }
  254. NTSTATUS
  255. SpAsrDeleteMountPoint(IN PWSTR PartitionDevicePath)
  256. {
  257. //
  258. // Check the DevicePath: it better not be NULL.
  259. //
  260. if (!PartitionDevicePath) {
  261. DbgErrorMesg((_asrwarn,
  262. "SpAsrDeleteMountPoint. Invalid Parameter, ParititionDevicePath is NULL.\n"
  263. ));
  264. ASSERT(0 && L"Invalid Parameter, ParititionDevicePath is NULL."); // debug
  265. return STATUS_INVALID_PARAMETER;
  266. }
  267. DbgStatusMesg((_asrinfo,
  268. "SpAsrDeleteMountPoint. Deleting drive letter for [%ws]\n",
  269. PartitionDevicePath
  270. ));
  271. SpDeleteDriveLetter(PartitionDevicePath);
  272. return STATUS_SUCCESS;
  273. }
  274. NTSTATUS
  275. SpAsrSetVolumeGuid(
  276. IN PDISK_REGION pRegion,
  277. IN PWSTR VolumeGuid
  278. )
  279. /*++
  280. Description:
  281. Delete and recreate the region's mount point using the passed-in symbolic
  282. name GUID parameter.
  283. Arguments:
  284. pRegion A pointer to a partitioned region descriptor.
  285. VolumeGuid Specifies the GUID string to be assigned to the region.
  286. DeleteDriveLetter Specifies if the existing drive letter for the volume
  287. should be deleted. This should be TRUE for all volumes
  288. except the boot volume.
  289. Returns:
  290. NTSTATUS
  291. --*/
  292. {
  293. NTSTATUS status = STATUS_UNSUCCESSFUL;
  294. PWSTR partitionDeviceName = NULL;
  295. //
  296. // Check input parameters
  297. //
  298. if (!pRegion || !SPPT_IS_REGION_PARTITIONED(pRegion)) {
  299. DbgErrorMesg((_asrwarn,
  300. "SpAsrSetVolumeGuid. Invalid Param: pRegion (%p) NULL/not partitioned\n",
  301. pRegion
  302. ));
  303. return STATUS_INVALID_PARAMETER;
  304. }
  305. if (!VolumeGuid || !wcslen(VolumeGuid)) {
  306. DbgErrorMesg((_asrwarn,
  307. "SpAsrSetVolumeGuid. Invalid Param: VolumeGuid (%p) NULL/blank.\n",
  308. VolumeGuid
  309. ));
  310. return STATUS_INVALID_PARAMETER;
  311. }
  312. partitionDeviceName = SpAsrGetRegionName(pRegion);
  313. //
  314. // Create the mount point with the correct Guid string.
  315. //
  316. status = SpAsrCreateMountPoint(partitionDeviceName, VolumeGuid);
  317. SpMemFree(partitionDeviceName);
  318. return status;
  319. }