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.

220 lines
5.6 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. typedef LONG NTSTATUS;
  4. #include <ntdskreg.h>
  5. #include <ntddft.h>
  6. UCHAR
  7. QueryDriveLetter(
  8. IN ULONG Signature,
  9. IN LONGLONG Offset
  10. )
  11. {
  12. PDRIVE_LAYOUT_INFORMATION layout;
  13. UCHAR c;
  14. TCHAR name[80], result[80], num[10];
  15. DWORD i, j;
  16. HANDLE h;
  17. BOOL b;
  18. DWORD bytes;
  19. PARTITION_INFORMATION partInfo;
  20. DWORD em;
  21. layout = MALLOC(4096);
  22. if (!layout) {
  23. return 0;
  24. }
  25. em = SetErrorMode(0);
  26. SetErrorMode( em | SEM_FAILCRITICALERRORS );
  27. for (c = 'C'; c <= 'Z'; c++) {
  28. name[0] = (TCHAR)c;
  29. name[1] = (TCHAR)':';
  30. name[2] = (TCHAR)'\0';
  31. if (QueryDosDevice(name, result, sizeof(result)/sizeof(TCHAR)) < 17) {
  32. continue;
  33. }
  34. j = 0;
  35. for (i = 16; result[i]; i++) {
  36. if (result[i] == (TCHAR)'\\') {
  37. break;
  38. }
  39. num[j++] = result[i];
  40. }
  41. num[j] = (TCHAR)'\0';
  42. wsprintf(name, TEXT("\\\\.\\PhysicalDrive%s"), num);
  43. h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  44. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  45. INVALID_HANDLE_VALUE);
  46. if (h == INVALID_HANDLE_VALUE) {
  47. continue;
  48. }
  49. b = DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_LAYOUT, NULL, 0, layout,
  50. 4096, &bytes, NULL);
  51. CloseHandle(h);
  52. if (!b) {
  53. continue;
  54. }
  55. if (layout->Signature != Signature) {
  56. continue;
  57. }
  58. wsprintf(name, TEXT("\\\\.\\%c:"), c);
  59. h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  60. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  61. INVALID_HANDLE_VALUE);
  62. if (h == INVALID_HANDLE_VALUE) {
  63. continue;
  64. }
  65. b = DeviceIoControl(h, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
  66. &partInfo, sizeof(partInfo), &bytes, NULL);
  67. CloseHandle(h);
  68. if (!b) {
  69. continue;
  70. }
  71. if (partInfo.StartingOffset.QuadPart == Offset) {
  72. break;
  73. }
  74. }
  75. FREE(layout);
  76. SetErrorMode( em );
  77. return (c <= 'Z') ? c : 0;
  78. }
  79. VOID
  80. ForceStickyDriveLetters(
  81. )
  82. {
  83. LONG error;
  84. HKEY key;
  85. TCHAR name[10];
  86. UCHAR driveLetter;
  87. UINT driveType;
  88. TCHAR targetPath[MAX_PATH];
  89. DWORD type;
  90. DWORD size;
  91. PBYTE registryValue;
  92. PDISK_CONFIG_HEADER header;
  93. PDISK_REGISTRY diskRegistry;
  94. PDISK_DESCRIPTION diskDescription;
  95. ULONG i, j;
  96. PDISK_PARTITION diskPartition;
  97. DWORD d;
  98. error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\DISK"), 0,
  99. KEY_QUERY_VALUE | KEY_SET_VALUE, &key);
  100. if (error != ERROR_SUCCESS) {
  101. #ifdef _X86_
  102. if (IsNEC98() && Upgrade){
  103. error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  104. TEXT("SYSTEM\\DISK"),
  105. 0,
  106. NULL,
  107. REG_OPTION_NON_VOLATILE,
  108. KEY_QUERY_VALUE | KEY_SET_VALUE,
  109. NULL,
  110. &key,
  111. &d
  112. );
  113. if (error != ERROR_SUCCESS) {
  114. return;
  115. }
  116. }else{
  117. return;
  118. }
  119. #else
  120. return;
  121. #endif
  122. }
  123. name[1] = (TCHAR)':';
  124. name[2] = (TCHAR)'\\';
  125. name[3] = (TCHAR)'\0';
  126. for (driveLetter = 'C'; driveLetter <= 'Z'; driveLetter++) {
  127. name[0] = (TCHAR)driveLetter;
  128. name[2] = (TCHAR)'\\';
  129. driveType = GetDriveType(name);
  130. if (driveType != DRIVE_REMOVABLE && driveType != DRIVE_CDROM) {
  131. continue;
  132. }
  133. name[2] = (TCHAR)'\0';
  134. if (!QueryDosDevice(name, targetPath, MAX_PATH)) {
  135. continue;
  136. }
  137. RegSetValueEx(key, targetPath, 0, REG_SZ, (PBYTE)name, 3*sizeof(TCHAR));
  138. }
  139. error = RegQueryValueEx(key, TEXT("Information"), NULL, &type, NULL,
  140. &size);
  141. if (error != ERROR_SUCCESS) {
  142. RegCloseKey(key);
  143. return;
  144. }
  145. registryValue = MALLOC(size);
  146. if (!registryValue) {
  147. RegCloseKey(key);
  148. return;
  149. }
  150. error = RegQueryValueEx(key, TEXT("Information"), NULL, &type,
  151. registryValue, &size);
  152. if (error != ERROR_SUCCESS) {
  153. FREE(registryValue);
  154. RegCloseKey(key);
  155. return;
  156. }
  157. header = (PDISK_CONFIG_HEADER) registryValue;
  158. diskRegistry = (PDISK_REGISTRY) ((PCHAR) header +
  159. header->DiskInformationOffset);
  160. diskDescription = &diskRegistry->Disks[0];
  161. for (i = 0; i < diskRegistry->NumberOfDisks; i++) {
  162. for (j = 0; j < diskDescription->NumberOfPartitions; j++) {
  163. diskPartition = &diskDescription->Partitions[j];
  164. if (diskPartition->AssignDriveLetter &&
  165. !diskPartition->DriveLetter) {
  166. driveLetter = QueryDriveLetter(diskDescription->Signature,
  167. diskPartition->StartingOffset.QuadPart);
  168. if (driveLetter) {
  169. diskPartition->DriveLetter = driveLetter;
  170. }
  171. }
  172. }
  173. diskDescription = (PDISK_DESCRIPTION) &diskDescription->
  174. Partitions[diskDescription->NumberOfPartitions];
  175. }
  176. RegSetValueEx(key, TEXT("Information"), 0, type, registryValue, size);
  177. FREE(registryValue);
  178. RegCloseKey(key);
  179. }