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.

398 lines
11 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. //TRACE_PRINTF(TC_sisdrive,2,
  70. // (_T("Found volume \"%s\"\n"),&buffer[buffer_index]));
  71. partition_guid_names[num_partitions] = buffer_index;
  72. num_partitions++;
  73. buffer_index += _tcslen(&buffer[buffer_index]) + 1;
  74. }
  75. SERVICE_CHECKPOINT();
  76. }
  77. //
  78. // Setup to scan for DRIVE LETTERS and MOUNT POINTS and correlate
  79. // them with the GUID names.
  80. //
  81. partition_mount_names = new int[num_partitions];
  82. int *next_indices = new int[num_partitions + 3];
  83. int *work_list = &next_indices[num_partitions + 1];
  84. int *scan_list = &next_indices[num_partitions + 2];
  85. *scan_list = 0;
  86. for (int index = 0; index < num_partitions; index++)
  87. {
  88. partition_mount_names[index] = -1;
  89. next_indices[index] = index + 1;
  90. }
  91. next_indices[num_partitions - 1] = -1;
  92. *work_list = num_partitions;
  93. next_indices[num_partitions] = -1;
  94. int work_list_end = num_partitions;
  95. //
  96. // Now that we have the GUID names, this will correlate the GUID names
  97. // with the MOUNT names, this does both direct drive letters and
  98. // mount point names.
  99. //
  100. while (*scan_list != -1 && *work_list != -1)
  101. {
  102. _TCHAR *mount_name = 0;
  103. int mount_size = 0;
  104. if (*work_list < num_partitions)
  105. {
  106. mount_name = &buffer[partition_mount_names[*work_list]];
  107. mount_size = _tcslen(mount_name);
  108. while (buffer_size - buffer_index <= mount_size)
  109. {
  110. resize_buffer();
  111. }
  112. _tcscpy(&buffer[buffer_index], mount_name);
  113. }
  114. VolumeMountPoints mount_points(mount_name);
  115. //
  116. // We have the next name, scan the list looking for that name
  117. //
  118. done = false;
  119. while (!done)
  120. {
  121. DWORD error_code = mount_points.find(
  122. &buffer[buffer_index + mount_size],
  123. buffer_size - buffer_index - mount_size);
  124. while (error_code != NO_ERROR)
  125. {
  126. if (error_code != ERROR_INSUFFICIENT_BUFFER &&
  127. error_code != ERROR_BUFFER_OVERFLOW &&
  128. error_code != ERROR_FILENAME_EXCED_RANGE)
  129. {
  130. done = true;
  131. break;
  132. }
  133. resize_buffer();
  134. SERVICE_CHECKPOINT();
  135. error_code = mount_points.find(
  136. &buffer[buffer_index + mount_size],
  137. buffer_size - buffer_index - mount_size);
  138. }
  139. if (!done)
  140. {
  141. _TCHAR volume_guid_name[MAX_PATH + 1];
  142. //TRACE_PRINTF(TC_sisdrive,2,
  143. // (_T("Correlating volume \"%s\"\n"),&buffer[buffer_index+mount_size]));
  144. BOOL ok = GetVolumeNameForVolumeMountPoint(
  145. &buffer[buffer_index], volume_guid_name, MAX_PATH + 1);
  146. if (!ok)
  147. {
  148. continue;
  149. }
  150. int scan_index = *scan_list;
  151. int prev_index = num_partitions + 2;
  152. while (scan_index >= 0)
  153. {
  154. _TCHAR *scan_name =
  155. &buffer[partition_guid_names[scan_index]];
  156. if (_tcscmp(scan_name, volume_guid_name) == 0)
  157. {
  158. partition_mount_names[scan_index] = buffer_index;
  159. buffer_index += _tcslen(&buffer[buffer_index]) + 1;
  160. next_indices[prev_index] = next_indices[scan_index];
  161. next_indices[scan_index] = -1;
  162. next_indices[work_list_end] = scan_index;
  163. work_list_end = scan_index;
  164. if (mount_name) {
  165. _tcscpy(&buffer[buffer_index], mount_name); //get ready for next time through the loop
  166. }
  167. break;
  168. }
  169. prev_index = scan_index;
  170. scan_index = next_indices[scan_index];
  171. SERVICE_CHECKPOINT();
  172. }
  173. }
  174. SERVICE_CHECKPOINT();
  175. }
  176. *work_list = next_indices[*work_list];
  177. SERVICE_CHECKPOINT();
  178. }
  179. delete[] next_indices;
  180. next_indices = 0;
  181. //
  182. // We are now going to sort all of the drive letter entries to the front
  183. // this does keep the driver letter/guid name correlation intact.
  184. //
  185. index = 0;
  186. while (index < num_partitions)
  187. {
  188. if (partition_mount_names[index] < 0 ||
  189. !is_sis_drive(&buffer[partition_guid_names[index]]) ||
  190. (!GrovelAllPaths &&
  191. (!RISVolumeGuidName ||
  192. _wcsicmp(RISVolumeGuidName,&buffer[partition_guid_names[index]]) != 0)))
  193. {
  194. TRACE_PRINTF(TC_sisdrive,2,
  195. (_T("Ignoring: Name=\"%s\" GuidName=\"%s\"\n"),
  196. (partition_mount_names[index] > 0) ? &buffer[partition_mount_names[index]] : NULL,
  197. &buffer[partition_guid_names[index]]));
  198. //
  199. // The given entry either doesn't have a name or SIS is
  200. // not currently running on the volume. Move it to the end
  201. // of the list.
  202. int temp = partition_guid_names[index];
  203. partition_guid_names[index] =
  204. partition_guid_names[num_partitions - 1];
  205. partition_guid_names[num_partitions - 1] = temp;
  206. temp = partition_mount_names[index];
  207. partition_mount_names[index] =
  208. partition_mount_names[num_partitions - 1];
  209. partition_mount_names[num_partitions - 1] = temp;
  210. num_partitions--;
  211. continue;
  212. }
  213. if (buffer[partition_mount_names[index] + 3] == _T('\0'))
  214. {
  215. //
  216. // If this is a drive letter (not a mount point) then
  217. // it will be moved to the front of the list
  218. //
  219. int temp = partition_guid_names[index];
  220. partition_guid_names[index] =
  221. partition_guid_names[num_lettered_partitions];
  222. partition_guid_names[num_lettered_partitions] = temp;
  223. temp = partition_mount_names[index];
  224. partition_mount_names[index] =
  225. partition_mount_names[num_lettered_partitions];
  226. partition_mount_names[num_lettered_partitions] = temp;
  227. num_lettered_partitions++;
  228. }
  229. index++;
  230. SERVICE_CHECKPOINT();
  231. }
  232. #if DBG
  233. TRACE_PRINTF(TC_sisdrive,2,
  234. (_T("Num Partitions=%d\nNum Lettered_partitions=%d\n"),
  235. num_partitions,
  236. num_lettered_partitions));
  237. for (index=0;index < num_partitions;index++)
  238. {
  239. TRACE_PRINTF(TC_sisdrive,2,
  240. (_T("Name=\"%s\" GuidName=\"%s\"\n"),
  241. &buffer[partition_mount_names[index]],
  242. &buffer[partition_guid_names[index]]));
  243. }
  244. #endif
  245. }
  246. SISDrives::~SISDrives()
  247. {
  248. if (partition_guid_names != 0)
  249. {
  250. delete[] partition_guid_names;
  251. partition_guid_names = 0;
  252. }
  253. if (partition_mount_names != 0)
  254. {
  255. delete[] partition_mount_names;
  256. partition_mount_names = 0;
  257. }
  258. if (buffer != 0)
  259. {
  260. delete[] buffer;
  261. buffer = 0;
  262. }
  263. }
  264. int SISDrives::partition_count() const
  265. {
  266. return num_partitions;
  267. }
  268. int SISDrives::lettered_partition_count() const
  269. {
  270. return num_lettered_partitions;
  271. }
  272. _TCHAR * SISDrives::partition_guid_name(
  273. int partition_index) const
  274. {
  275. if (partition_index < num_partitions)
  276. {
  277. return &buffer[partition_guid_names[partition_index]];
  278. }
  279. else
  280. {
  281. return 0;
  282. }
  283. }
  284. _TCHAR * SISDrives::partition_mount_name(
  285. int partition_index) const
  286. {
  287. if (partition_index < num_partitions)
  288. {
  289. return &buffer[partition_mount_names[partition_index]];
  290. }
  291. else
  292. {
  293. return 0;
  294. }
  295. }
  296. bool
  297. SISDrives::is_sis_drive(
  298. _TCHAR *drive_name)
  299. {
  300. UINT drive_type = GetDriveType(drive_name);
  301. if (drive_type != DRIVE_FIXED)
  302. {
  303. return false;
  304. }
  305. _TCHAR fs_name[8];
  306. BOOL ok = GetVolumeInformation(drive_name, 0, 0, 0, 0, 0, fs_name, 8);
  307. if (!ok)
  308. {
  309. DWORD err = GetLastError();
  310. PRINT_DEBUG_MSG((_T("GROVELER: GetVolumeInformation() failed with error %d\n"),
  311. err));
  312. return false;
  313. }
  314. if (_tcsicmp(fs_name, _T("NTFS")) != 0)
  315. {
  316. return false;
  317. }
  318. int bLen = SIS_CSDIR_STRING_NCHARS + wcslen(drive_name) + (sizeof(WCHAR)*2);
  319. _TCHAR *sis_directory = new _TCHAR[bLen];
  320. (void)StringCchCopy(sis_directory, bLen, drive_name);
  321. TrimTrailingChar(sis_directory, L'\\');
  322. (void)StringCchCat(sis_directory, bLen, SIS_CSDIR_STRING);
  323. ok = SetCurrentDirectory(sis_directory);
  324. delete[] sis_directory;
  325. sis_directory = 0;
  326. if (!ok)
  327. {
  328. return false;
  329. }
  330. BOOL sis_installed = Groveler::is_sis_installed(drive_name);
  331. if (!sis_installed)
  332. {
  333. return false;
  334. }
  335. return true;
  336. }
  337. void SISDrives::resize_buffer()
  338. {
  339. buffer_size *= 2;
  340. _TCHAR *new_buffer = new _TCHAR[buffer_size];
  341. memcpy(new_buffer, buffer, buffer_index * sizeof(_TCHAR));
  342. delete[] buffer;
  343. buffer = new_buffer;
  344. }