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.

283 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. wsbvol.cpp
  5. Abstract:
  6. Definitions for volume support routines
  7. Author:
  8. Ran Kalach [rankala] 27, January 2000
  9. Revision History:
  10. --*/
  11. #include <stdafx.h>
  12. #include <wsbvol.h>
  13. // Internal functions
  14. static HRESULT FindMountPoint(IN PWSTR enumName, IN PWSTR volumeName, OUT PWSTR firstMountPoint, IN ULONG maxSize);
  15. HRESULT
  16. WsbGetFirstMountPoint(
  17. IN PWSTR volumeName,
  18. OUT PWSTR firstMountPoint,
  19. IN ULONG maxSize
  20. )
  21. /*++
  22. Routine Description:
  23. Find one Mount Point path (if exists) for the given volume
  24. Arguments:
  25. volumeName - The volume name to search mount path for.
  26. It should have the \\?\volume{GUID}\ format
  27. firstMountPoint - Buffer for the output mount point path
  28. maxSize - Buffer size
  29. Return Value:
  30. S_OK - If at least one Mount Point is found
  31. --*/
  32. {
  33. HRESULT hr = S_FALSE;
  34. WCHAR name[10];
  35. UCHAR driveLetter;
  36. WCHAR tempName[MAX_PATH];
  37. WCHAR driveName[10];
  38. FILE_FS_DEVICE_INFORMATION DeviceInfo;
  39. IO_STATUS_BLOCK StatusBlock;
  40. HANDLE hDrive = NULL ;
  41. NTSTATUS status;
  42. WsbTraceIn(OLESTR("WsbGetFirstMountPoint"), OLESTR("volume name = <%ls>"), volumeName);
  43. name[1] = ':';
  44. name[2] = '\\';
  45. name[3] = 0;
  46. driveName[0] = '\\';
  47. driveName[1] = '\\';
  48. driveName[2] = '.';
  49. driveName[3] = '\\';
  50. driveName[5] = ':';
  51. driveName[6] = 0;
  52. for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++) {
  53. name[0] = driveLetter;
  54. // Exclude network drives
  55. if (! GetVolumeNameForVolumeMountPoint(name, tempName, MAX_PATH)) {
  56. continue;
  57. }
  58. // Verify that the drive is not removable or floppy,
  59. // this is required to avoid popups when the drive is empty
  60. driveName[4] = driveLetter;
  61. hDrive = CreateFile(driveName,
  62. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  63. FILE_SHARE_READ | FILE_SHARE_WRITE,
  64. 0,
  65. OPEN_EXISTING,
  66. FILE_ATTRIBUTE_NORMAL,
  67. 0);
  68. if (hDrive == INVALID_HANDLE_VALUE) {
  69. // Can't open it - won't search on it
  70. WsbTrace(OLESTR("WsbGetFirstMountPoint: Could not open volume %ls, status = %lu - Skipping it!\n"), driveName, GetLastError());
  71. continue;
  72. }
  73. status = NtQueryVolumeInformationFile(hDrive,
  74. &StatusBlock,
  75. (PVOID) &DeviceInfo,
  76. sizeof(FILE_FS_DEVICE_INFORMATION),
  77. FileFsDeviceInformation);
  78. if (!NT_SUCCESS(status)) {
  79. // Can't query it - won't search on it
  80. WsbTrace(OLESTR("WsbGetFirstMountPoint: Could not query information for volume %ls, status = %ld - Skipping it!\n"), driveName, (LONG)status);
  81. CloseHandle(hDrive);
  82. continue;
  83. }
  84. if ((DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE) || (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)) {
  85. // Skip removable/floppy drives
  86. WsbTrace(OLESTR("WsbGetFirstMountPoint: Skipping removable/floppy volume %ls\n"), driveName);
  87. CloseHandle(hDrive);
  88. continue;
  89. }
  90. CloseHandle(hDrive);
  91. WsbTrace(OLESTR("WsbGetFirstMountPoint: Checking mount points on volume %ls\n"), driveName);
  92. // Check mount points on drive
  93. hr = FindMountPoint(name, volumeName, firstMountPoint, maxSize);
  94. if (S_OK == hr) {
  95. // Looking for only one mount point
  96. break;
  97. }
  98. }
  99. WsbTraceOut(OLESTR("WsbGetFirstMountPoint"), OLESTR("hr = <%ls> mount point = <%ls>"), WsbHrAsString(hr), firstMountPoint);
  100. return hr;
  101. }
  102. HRESULT
  103. FindMountPoint(
  104. IN PWSTR enumName,
  105. IN PWSTR volumeName,
  106. OUT PWSTR firstMountPoint,
  107. IN ULONG maxSize
  108. )
  109. /*++
  110. Routine Description:
  111. Find one Mount Point path (if exists) for the given volume on the given enumeration-volume
  112. Arguments:
  113. enumName - Volume to enumerate, i.e. search for a mount point on it
  114. which corresponds to the given volume
  115. volumeName - The volume name to search mount path for.
  116. It should have the \\?\volume{GUID}\ format
  117. firstMountPoint - Buffer for the output mount point path
  118. maxSize - Buffer size
  119. Comments:
  120. Avoid the standard HSM try-catch paradigm for performance, especially since this
  121. function is recursive
  122. Return Value:
  123. S_OK - if at least one Mount Point is found
  124. S_FALSE - Otherwise
  125. --*/
  126. {
  127. HANDLE hEnum;
  128. WCHAR *enumVolumeName = NULL;
  129. WCHAR *volumeMountPoint = NULL;
  130. WCHAR *mountPointPath = NULL;
  131. WCHAR c1, c2;
  132. WCHAR *linkName1 = NULL;
  133. WCHAR *linkName2 = NULL;
  134. HRESULT hr = S_OK;
  135. enumVolumeName = (WCHAR*)WsbAlloc(MAX_PATH * sizeof(WCHAR));
  136. if (NULL == enumVolumeName) {
  137. hr = E_OUTOFMEMORY;
  138. goto exit;
  139. }
  140. volumeMountPoint = (WCHAR*)WsbAlloc(maxSize * sizeof(WCHAR));
  141. if (NULL == volumeMountPoint) {
  142. hr = E_OUTOFMEMORY;
  143. goto exit;
  144. }
  145. mountPointPath = (WCHAR*)WsbAlloc((maxSize + wcslen(enumName)) * sizeof(WCHAR));
  146. if (NULL == mountPointPath) {
  147. hr = E_OUTOFMEMORY;
  148. goto exit;
  149. }
  150. if (! GetVolumeNameForVolumeMountPoint(enumName, enumVolumeName, MAX_PATH)) {
  151. DWORD dwErr = GetLastError();
  152. hr = HRESULT_FROM_WIN32(dwErr);
  153. goto exit;
  154. }
  155. if (!wcscmp(enumVolumeName, volumeName)) {
  156. // The volume to enumerate on is the one we are looking for
  157. wcscpy(firstMountPoint, enumName);
  158. hr = S_OK;
  159. goto exit;
  160. } else {
  161. linkName1 = (WCHAR*)WsbAlloc((maxSize * 2) * sizeof(WCHAR));
  162. if (NULL == linkName1) {
  163. hr = E_OUTOFMEMORY;
  164. goto exit;
  165. }
  166. linkName2 = (WCHAR*)WsbAlloc((maxSize * 2) * sizeof(WCHAR));
  167. if (NULL == linkName1) {
  168. hr = E_OUTOFMEMORY;
  169. goto exit;
  170. }
  171. c1 = enumVolumeName[48];
  172. c2 = volumeName[48];
  173. enumVolumeName[48] = 0;
  174. volumeName[48] = 0;
  175. if (QueryDosDevice(&enumVolumeName[4], linkName1, maxSize*2) &&
  176. QueryDosDevice(&volumeName[4], linkName2, maxSize*2)) {
  177. if (!wcscmp(linkName1, linkName2)) {
  178. wcscpy(firstMountPoint, enumName);
  179. enumVolumeName[48] = c1;
  180. volumeName[48] = c2;
  181. hr = S_OK;
  182. goto exit;
  183. }
  184. }
  185. enumVolumeName[48] = c1;
  186. volumeName[48] = c2;
  187. }
  188. hEnum = FindFirstVolumeMountPoint(enumVolumeName, volumeMountPoint, maxSize);
  189. if (hEnum == INVALID_HANDLE_VALUE) {
  190. hr = S_FALSE;
  191. goto exit;
  192. }
  193. for (;;) {
  194. wcscpy(mountPointPath, enumName);
  195. wcscat(mountPointPath, volumeMountPoint);
  196. // Enumerate on the mount path we found
  197. hr = FindMountPoint(mountPointPath, volumeName, firstMountPoint, maxSize);
  198. if (S_OK == hr) {
  199. // Found one mount point path, no need to continue
  200. FindVolumeMountPointClose(hEnum);
  201. goto exit;
  202. }
  203. if (! FindNextVolumeMountPoint(hEnum, volumeMountPoint, maxSize)) {
  204. FindVolumeMountPointClose(hEnum);
  205. hr = S_FALSE;
  206. goto exit;
  207. }
  208. }
  209. exit:
  210. if (enumVolumeName) {
  211. WsbFree(enumVolumeName);
  212. }
  213. if (volumeMountPoint) {
  214. WsbFree(volumeMountPoint);
  215. }
  216. if (mountPointPath) {
  217. WsbFree(mountPointPath);
  218. }
  219. if (linkName1) {
  220. WsbFree(linkName1);
  221. }
  222. if (linkName2) {
  223. WsbFree(linkName2);
  224. }
  225. return hr;
  226. }