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.

381 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. sisdrive.cpp
  5. Abstract:
  6. SIS Groveler SIS drive checker class
  7. Authors:
  8. John Douceur, 1998
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "all.hxx"
  14. SISDrives::SISDrives()
  15. {
  16. num_partitions = 0;
  17. num_lettered_partitions = 0;
  18. partition_guid_names = 0;
  19. partition_mount_names = 0;
  20. buffer_size = 0;
  21. buffer_index = 0;
  22. buffer = 0;
  23. }
  24. void
  25. SISDrives::open()
  26. {
  27. num_partitions = 0;
  28. num_lettered_partitions = 0;
  29. partition_mount_names = 0;
  30. int name_array_size = 1;
  31. partition_guid_names = new int[name_array_size];
  32. buffer_size = 256;
  33. buffer_index = 0;
  34. buffer = new _TCHAR[buffer_size];
  35. SERVICE_CHECKPOINT();
  36. Volumes volumes;
  37. bool done = false;
  38. //
  39. // Enumerate all existing volumes getting their GUID names
  40. //
  41. while (!done)
  42. {
  43. DWORD error_code =
  44. volumes.find(&buffer[buffer_index], buffer_size - buffer_index);
  45. while (error_code != NO_ERROR)
  46. {
  47. if (error_code != ERROR_INSUFFICIENT_BUFFER &&
  48. error_code != ERROR_BUFFER_OVERFLOW &&
  49. error_code != ERROR_FILENAME_EXCED_RANGE)
  50. {
  51. done = true;
  52. break;
  53. }
  54. resize_buffer();
  55. SERVICE_CHECKPOINT();
  56. error_code =
  57. volumes.find(&buffer[buffer_index], buffer_size - buffer_index);
  58. }
  59. if (!done)
  60. {
  61. if (num_partitions >= name_array_size)
  62. {
  63. name_array_size *= 2;
  64. int *new_name_array = new int[name_array_size];
  65. memcpy(new_name_array,partition_guid_names,num_partitions * sizeof(int));
  66. delete[] partition_guid_names;
  67. partition_guid_names = new_name_array;
  68. }
  69. partition_guid_names[num_partitions] = buffer_index;
  70. num_partitions++;
  71. buffer_index += _tcslen(&buffer[buffer_index]) + 1;
  72. }
  73. SERVICE_CHECKPOINT();
  74. }
  75. //
  76. // Setup to scan for DRIVE LETTERS and MOUNT POINTS and correlate
  77. // them with the drive letters.
  78. //
  79. partition_mount_names = new int[num_partitions];
  80. int *next_indices = new int[num_partitions + 3];
  81. int *work_list = &next_indices[num_partitions + 1];
  82. int *scan_list = &next_indices[num_partitions + 2];
  83. *scan_list = 0;
  84. for (int index = 0; index < num_partitions; index++)
  85. {
  86. partition_mount_names[index] = -1;
  87. next_indices[index] = index + 1;
  88. }
  89. next_indices[num_partitions - 1] = -1;
  90. *work_list = num_partitions;
  91. next_indices[num_partitions] = -1;
  92. int work_list_end = num_partitions;
  93. //
  94. // Now that we have the GUID names, this will correlate the GUID names
  95. // with the MOUNT names, this does both direct drive letters and
  96. // mount point names.
  97. //
  98. while (*scan_list != -1 && *work_list != -1)
  99. {
  100. _TCHAR *mount_name = 0;
  101. int mount_size = 0;
  102. if (*work_list < num_partitions)
  103. {
  104. mount_name = &buffer[partition_mount_names[*work_list]];
  105. mount_size = _tcslen(mount_name);
  106. while (buffer_size - buffer_index <= mount_size)
  107. {
  108. resize_buffer();
  109. }
  110. _tcscpy(&buffer[buffer_index], mount_name);
  111. }
  112. VolumeMountPoints mount_points(mount_name);
  113. //
  114. // We have the next name, scan the list looking for that name
  115. //
  116. done = false;
  117. while (!done)
  118. {
  119. DWORD error_code = mount_points.find(
  120. &buffer[buffer_index + mount_size],
  121. buffer_size - buffer_index - mount_size);
  122. while (error_code != NO_ERROR)
  123. {
  124. if (error_code != ERROR_INSUFFICIENT_BUFFER &&
  125. error_code != ERROR_BUFFER_OVERFLOW &&
  126. error_code != ERROR_FILENAME_EXCED_RANGE)
  127. {
  128. done = true;
  129. break;
  130. }
  131. resize_buffer();
  132. SERVICE_CHECKPOINT();
  133. error_code = mount_points.find(
  134. &buffer[buffer_index + mount_size],
  135. buffer_size - buffer_index - mount_size);
  136. }
  137. if (!done)
  138. {
  139. _TCHAR volume_guid_name[MAX_PATH + 1];
  140. BOOL ok = GetVolumeNameForVolumeMountPoint(
  141. &buffer[buffer_index], volume_guid_name, MAX_PATH + 1);
  142. if (!ok)
  143. {
  144. continue;
  145. }
  146. int scan_index = *scan_list;
  147. int prev_index = num_partitions + 2;
  148. while (scan_index >= 0)
  149. {
  150. _TCHAR *scan_name =
  151. &buffer[partition_guid_names[scan_index]];
  152. if (_tcscmp(scan_name, volume_guid_name) == 0)
  153. {
  154. partition_mount_names[scan_index] = buffer_index;
  155. buffer_index += _tcslen(&buffer[buffer_index]) + 1;
  156. next_indices[prev_index] = next_indices[scan_index];
  157. next_indices[scan_index] = -1;
  158. next_indices[work_list_end] = scan_index;
  159. work_list_end = scan_index;
  160. if (mount_name) {
  161. _tcscpy(&buffer[buffer_index], mount_name); //get ready for next time through the loop
  162. }
  163. break;
  164. }
  165. prev_index = scan_index;
  166. scan_index = next_indices[scan_index];
  167. SERVICE_CHECKPOINT();
  168. }
  169. }
  170. SERVICE_CHECKPOINT();
  171. }
  172. *work_list = next_indices[*work_list];
  173. SERVICE_CHECKPOINT();
  174. }
  175. delete[] next_indices;
  176. next_indices = 0;
  177. //
  178. // We are now going to sort all of the drive letter entries to the front
  179. // this does keep the driver letter/guid name correlation intact.
  180. //
  181. index = 0;
  182. while (index < num_partitions)
  183. {
  184. if (partition_mount_names[index] < 0 ||
  185. !is_sis_drive(&buffer[partition_guid_names[index]]))
  186. {
  187. //
  188. // The given entry either doesn't have a name or SIS is
  189. // not currently running on the volume. Move it to the end
  190. // of the list.
  191. int temp = partition_guid_names[index];
  192. partition_guid_names[index] =
  193. partition_guid_names[num_partitions - 1];
  194. partition_guid_names[num_partitions - 1] = temp;
  195. temp = partition_mount_names[index];
  196. partition_mount_names[index] =
  197. partition_mount_names[num_partitions - 1];
  198. partition_mount_names[num_partitions - 1] = temp;
  199. num_partitions--;
  200. continue;
  201. }
  202. if (buffer[partition_mount_names[index] + 3] == _T('\0'))
  203. {
  204. //
  205. // If this is a drive letter (not a mount point) then
  206. // it will be moved to the front of the list
  207. //
  208. int temp = partition_guid_names[index];
  209. partition_guid_names[index] =
  210. partition_guid_names[num_lettered_partitions];
  211. partition_guid_names[num_lettered_partitions] = temp;
  212. temp = partition_mount_names[index];
  213. partition_mount_names[index] =
  214. partition_mount_names[num_lettered_partitions];
  215. partition_mount_names[num_lettered_partitions] = temp;
  216. num_lettered_partitions++;
  217. }
  218. index++;
  219. SERVICE_CHECKPOINT();
  220. }
  221. #if DBG
  222. TRACE_PRINTF(TC_sisdrive,2,
  223. (_T("Num Partitions=%d\nNum Lettered_partitions=%d\n"),
  224. num_partitions,
  225. num_lettered_partitions));
  226. for (index=0;index < num_partitions;index++)
  227. {
  228. TRACE_PRINTF(TC_sisdrive,2,
  229. (_T("Name=\"%s\" GuidName=\"%s\"\n"),
  230. &buffer[partition_mount_names[index]],
  231. &buffer[partition_guid_names[index]]));
  232. }
  233. #endif
  234. }
  235. SISDrives::~SISDrives()
  236. {
  237. if (partition_guid_names != 0)
  238. {
  239. delete[] partition_guid_names;
  240. partition_guid_names = 0;
  241. }
  242. if (partition_mount_names != 0)
  243. {
  244. delete[] partition_mount_names;
  245. partition_mount_names = 0;
  246. }
  247. if (buffer != 0)
  248. {
  249. delete[] buffer;
  250. buffer = 0;
  251. }
  252. }
  253. int SISDrives::partition_count() const
  254. {
  255. return num_partitions;
  256. }
  257. int SISDrives::lettered_partition_count() const
  258. {
  259. return num_lettered_partitions;
  260. }
  261. _TCHAR * SISDrives::partition_guid_name(
  262. int partition_index) const
  263. {
  264. if (partition_index < num_partitions)
  265. {
  266. return &buffer[partition_guid_names[partition_index]];
  267. }
  268. else
  269. {
  270. return 0;
  271. }
  272. }
  273. _TCHAR * SISDrives::partition_mount_name(
  274. int partition_index) const
  275. {
  276. if (partition_index < num_partitions)
  277. {
  278. return &buffer[partition_mount_names[partition_index]];
  279. }
  280. else
  281. {
  282. return 0;
  283. }
  284. }
  285. bool
  286. SISDrives::is_sis_drive(
  287. _TCHAR *drive_name)
  288. {
  289. UINT drive_type = GetDriveType(drive_name);
  290. if (drive_type != DRIVE_FIXED)
  291. {
  292. return false;
  293. }
  294. _TCHAR fs_name[8];
  295. BOOL ok = GetVolumeInformation(drive_name, 0, 0, 0, 0, 0, fs_name, 8);
  296. if (!ok)
  297. {
  298. DWORD err = GetLastError();
  299. PRINT_DEBUG_MSG((_T("GROVELER: GetVolumeInformation() failed with error %d\n"),
  300. err));
  301. return false;
  302. }
  303. if (_tcsicmp(fs_name, _T("NTFS")) != 0)
  304. {
  305. return false;
  306. }
  307. int drive_name_len = _tcslen(drive_name);
  308. _TCHAR *sis_directory =
  309. new _TCHAR[SIS_CSDIR_STRING_NCHARS + drive_name_len];
  310. _tcscpy(sis_directory, drive_name);
  311. _tcscpy(&sis_directory[drive_name_len - 1], SIS_CSDIR_STRING);
  312. ok = SetCurrentDirectory(sis_directory);
  313. delete[] sis_directory;
  314. sis_directory = 0;
  315. if (!ok)
  316. {
  317. return false;
  318. }
  319. BOOL sis_installed = Groveler::is_sis_installed(drive_name);
  320. if (!sis_installed)
  321. {
  322. return false;
  323. }
  324. return true;
  325. }
  326. void SISDrives::resize_buffer()
  327. {
  328. buffer_size *= 2;
  329. _TCHAR *new_buffer = new _TCHAR[buffer_size];
  330. memcpy(new_buffer, buffer, buffer_index * sizeof(_TCHAR));
  331. delete[] buffer;
  332. buffer = new_buffer;
  333. }