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.

334 lines
8.9 KiB

  1. #include "stdafx.h"
  2. #ifdef OFFLINEDK
  3. extern "C"{
  4. #include <stdio.h>
  5. }
  6. #endif
  7. #ifdef BOOTIME
  8. #include "Offline.h"
  9. #else
  10. #include "Windows.h"
  11. #endif
  12. #include <winioctl.h>
  13. extern "C" {
  14. #include "SysStruc.h"
  15. }
  16. #include "ErrMacro.h"
  17. #include "DfrgCmn.h"
  18. #include "DfrgRes.h"
  19. #include "Alloc.h"
  20. #define THIS_MODULE 'U'
  21. #include "logfile.h"
  22. //
  23. // start of helpers for IsValidVolume functions below
  24. //
  25. /////////////////////////////////////////
  26. // Is this a valid drive type?
  27. // Check if we have a drive that is even in the ball park.
  28. //
  29. static BOOL IsValidDriveType(UINT uDriveType)
  30. {
  31. //sks bug #211782 take out CDROM and RAMDISK to allow for DVD-RAM drives
  32. if (uDriveType == DRIVE_UNKNOWN ||
  33. uDriveType == DRIVE_NO_ROOT_DIR ||
  34. uDriveType == DRIVE_REMOTE
  35. ) {
  36. return FALSE;
  37. }
  38. return TRUE;
  39. }
  40. /////////////////////////////////////////
  41. // Get a handle to a volume
  42. //
  43. static HANDLE GetVolumeHandle(PTCHAR cVolume)
  44. {
  45. HANDLE hVolume = INVALID_HANDLE_VALUE;
  46. // Get a handle to the volume
  47. UINT uiErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  48. hVolume = CreateFile(cVolume,
  49. 0,
  50. FILE_SHARE_READ|FILE_SHARE_WRITE,
  51. NULL,
  52. OPEN_EXISTING,
  53. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING,
  54. NULL);
  55. SetErrorMode(uiErrorMode);
  56. return hVolume;
  57. }
  58. /////////////////////////////////////////
  59. // Is this volume valid (actual work routine)
  60. //
  61. // Note: volumeName is required to get volumeLabel and fileSystem
  62. //
  63. static BOOL IsValidVolumeCheck(HANDLE hVolume, // IN volume handle
  64. UINT uDriveType, // IN drive type
  65. PTCHAR volumeName, // IN volume name
  66. PTCHAR volumeLabel, // OUT volume label
  67. PTCHAR fileSystem) // OUT file system
  68. {
  69. require(hVolume != INVALID_HANDLE_VALUE && hVolume != NULL);
  70. require(volumeName != NULL);
  71. BOOL bReturn = FALSE; // assume not valid
  72. HANDLE hFsDevInfo = NULL;
  73. FILE_FS_DEVICE_INFORMATION * pFsDevInfo = NULL;
  74. // clear return values
  75. if (volumeLabel != NULL) {
  76. _tcscpy(volumeLabel, TEXT(""));
  77. }
  78. if (fileSystem != NULL) {
  79. _tcscpy(fileSystem, TEXT(""));
  80. }
  81. __try {
  82. // read-only, network, etc. check
  83. if (!AllocateMemory(sizeof(FILE_FS_DEVICE_INFORMATION) + MAX_PATH,
  84. &hFsDevInfo, (void**) &pFsDevInfo)) {
  85. EH(FALSE);
  86. __leave;
  87. }
  88. IO_STATUS_BLOCK IoStatus = {0};
  89. NTSTATUS Status = NtQueryVolumeInformationFile(hVolume,
  90. &IoStatus,
  91. pFsDevInfo,
  92. sizeof(FILE_FS_DEVICE_INFORMATION) + 50,
  93. FileFsDeviceInformation);
  94. if (NT_SUCCESS(Status)) {
  95. if (pFsDevInfo->Characteristics &
  96. (FILE_READ_ONLY_DEVICE | FILE_WRITE_ONCE_MEDIA | FILE_REMOTE_DEVICE)) {
  97. __leave;
  98. }
  99. }
  100. else {
  101. __leave;
  102. }
  103. // media check
  104. if (uDriveType == DRIVE_REMOVABLE) {
  105. DISK_GEOMETRY medias[20];
  106. DWORD nummedias = 0;
  107. DWORD numbytes;
  108. if (DeviceIoControl(hVolume, IOCTL_STORAGE_GET_MEDIA_TYPES,
  109. NULL, 0, medias, 20 * sizeof(DISK_GEOMETRY), &numbytes, NULL)) {
  110. nummedias = numbytes / sizeof(DISK_GEOMETRY);
  111. for (UINT i=0; i<nummedias; i++) {
  112. switch (medias[i].MediaType) {
  113. // these are OK
  114. case F3_20Pt8_512: // 3.5", 20.8MB, 512 bytes/sector
  115. case FixedMedia: // Fixed hard disk media
  116. case F3_120M_512: // 3.5", 120M Floppy
  117. case F3_128Mb_512: // 3.5" MO 128Mb 512 bytes/sector
  118. case F3_230Mb_512: // 3.5" MO 230Mb 512 bytes/sector
  119. break;
  120. // but nothing else is
  121. default:
  122. __leave;
  123. break;
  124. }
  125. }
  126. }
  127. else {
  128. GetLastError(); // debug
  129. // TODO: figure out why JAZ drives fail on the above call
  130. // we should probably __leave here, but then JAZ drives are filtered out
  131. // maybe we should EH so at least it will register albeit every second or two
  132. // question: do or should every removable drive type report supported media?
  133. // EH(FALSE);
  134. // __leave;
  135. }
  136. }
  137. // file system check
  138. TCHAR tmpVolumeLabel[100];
  139. TCHAR tmpFileSystem[20];
  140. TCHAR tmpVolumeName[GUID_LENGTH];
  141. _tcscpy(tmpVolumeName, volumeName);
  142. if (volumeName[_tcslen(tmpVolumeName) - 1] != TEXT('\\')){
  143. _tcscat(tmpVolumeName, TEXT("\\"));
  144. }
  145. BOOL isOk = GetVolumeInformation(tmpVolumeName,
  146. tmpVolumeLabel,
  147. 100,
  148. NULL,
  149. NULL,
  150. NULL,
  151. tmpFileSystem,
  152. 20);
  153. if (!isOk) {
  154. __leave;
  155. }
  156. if (volumeLabel != NULL) {
  157. _tcscpy(volumeLabel, tmpVolumeLabel);
  158. }
  159. if (fileSystem != NULL) {
  160. _tcscpy(fileSystem, tmpFileSystem);
  161. }
  162. // Only NTFS, FAT or FAT32
  163. if (_tcscmp(tmpFileSystem, TEXT("NTFS")) &&
  164. _tcscmp(tmpFileSystem, TEXT("FAT")) &&
  165. _tcscmp(tmpFileSystem, TEXT("FAT32"))) {
  166. __leave; // if none of the above, bail
  167. }
  168. bReturn = TRUE; // all the checks "passed"
  169. }
  170. __finally {
  171. if (hFsDevInfo) {
  172. EH_ASSERT(GlobalUnlock(hFsDevInfo) == FALSE);
  173. EH_ASSERT(GlobalFree(hFsDevInfo) == NULL);
  174. }
  175. }
  176. return bReturn;
  177. }
  178. /////////////////////////////////////////
  179. // Is this volume valid (drive letter only version)
  180. //
  181. BOOL IsValidVolume(TCHAR cDrive)
  182. {
  183. // Check if we have a drive that is even in the ball park.
  184. // If so, then continue on and gather more data (mostly for removable drives)
  185. TCHAR cRootPath[100];
  186. _stprintf(cRootPath, TEXT("%c:\\"), cDrive);
  187. UINT uDriveType = GetDriveType(cRootPath);
  188. if (!IsValidDriveType(uDriveType)) {
  189. return FALSE;
  190. }
  191. // Get a handle to the volume
  192. TCHAR cVolume[MAX_PATH];
  193. _stprintf(cVolume, TEXT("\\\\.\\%c:"), cDrive);
  194. HANDLE hVolume = GetVolumeHandle(cVolume);
  195. if (hVolume == INVALID_HANDLE_VALUE) {
  196. return FALSE;
  197. }
  198. // check volume
  199. BOOL bReturn = IsValidVolumeCheck(hVolume, uDriveType, cVolume, NULL, NULL);
  200. CloseHandle(hVolume);
  201. return bReturn;
  202. }
  203. /////////////////////////////////////////
  204. // Is this volume valid (version 2)
  205. //
  206. // INPUT:
  207. // volumeName
  208. //
  209. // OUTPUT:
  210. // volumeLabel
  211. // fileSystem
  212. //
  213. BOOL IsValidVolume(PTCHAR volumeName, PTCHAR volumeLabel, PTCHAR fileSystem)
  214. {
  215. BOOL bReturn = FALSE; // assume error
  216. if(!volumeName) {
  217. assert(0);
  218. return FALSE;
  219. }
  220. // Check if we have a drive that is even in the ball park.
  221. // If so, then continue on and gather more data (mostly for removable drives)
  222. UINT uDriveType = GetDriveType(volumeName);
  223. if (!IsValidDriveType(uDriveType)) {
  224. return FALSE;
  225. }
  226. //sks 8/30/2000 fix for prefix bug #109657
  227. TCHAR tmpVolumeName[GUID_LENGTH + 1];
  228. _tcsncpy(tmpVolumeName, volumeName, GUID_LENGTH);
  229. tmpVolumeName[GUID_LENGTH] = (TCHAR) NULL;
  230. // strip off the trailing whack
  231. if (tmpVolumeName[_tcslen(tmpVolumeName)-1] == TEXT('\\')){
  232. tmpVolumeName[_tcslen(tmpVolumeName)-1] = (TCHAR) NULL;
  233. }
  234. // Get a handle to the volume
  235. HANDLE hVolume = GetVolumeHandle(tmpVolumeName);
  236. if (hVolume == INVALID_HANDLE_VALUE) {
  237. return FALSE;
  238. }
  239. // check volume
  240. bReturn = IsValidVolumeCheck(hVolume, uDriveType, volumeName, volumeLabel, fileSystem);
  241. CloseHandle(hVolume);
  242. return bReturn;
  243. }
  244. // is the file system supported?
  245. BOOL IsVolumeWriteable(PTCHAR volumeName, DWORD* dLastError)
  246. {
  247. *dLastError = 0;
  248. // create a temp file name
  249. TCHAR cTempFile[MAX_PATH + 50];
  250. if (0 == GetTempFileName(volumeName, L"DFRG", 0, cTempFile)) {
  251. *dLastError = GetLastError();
  252. return FALSE;
  253. }
  254. // get rid of the temp file
  255. DeleteFile(cTempFile);
  256. // true means that we can write to it
  257. return TRUE;
  258. }