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.

388 lines
8.6 KiB

  1. #include "std.hxx"
  2. class CException
  3. {
  4. protected:
  5. CException(
  6. PCTSTR pcszDescription,
  7. PCTSTR pcszFile,
  8. const DWORD dwLine) :
  9. m_pcszDescription(pcszDescription),
  10. m_pcszFile(pcszFile),
  11. m_dwLine(dwLine) {}
  12. public:
  13. PCTSTR GetDescription() { return m_pcszDescription; }
  14. PCTSTR GetFile() { return m_pcszFile; }
  15. DWORD GetLine() { return m_dwLine; }
  16. virtual void Throw() = 0;
  17. protected:
  18. PCTSTR m_pcszDescription;
  19. PCTSTR m_pcszFile;
  20. DWORD m_dwLine;
  21. };
  22. class CMemoryException : public CException
  23. {
  24. public:
  25. CMemoryException(
  26. DWORD dwSize,
  27. PCTSTR pcszDescription,
  28. PCTSTR pcszFile,
  29. DWORD dwLine) :
  30. CException(pcszDescription, pcszFile, dwLine),
  31. m_dwSize(dwSize) {}
  32. public:
  33. DWORD GetSize() { return m_dwSize; }
  34. void Throw() { throw *this; }
  35. protected:
  36. DWORD m_dwSize;
  37. };
  38. class CApiException : public CException
  39. {
  40. public:
  41. CApiException(
  42. DWORD dwGleCode,
  43. PCTSTR pcszDescription,
  44. PCTSTR pcszFile,
  45. DWORD dwLine) :
  46. CException(pcszDescription, pcszFile, dwLine),
  47. m_dwGleCode(dwGleCode) {}
  48. public:
  49. DWORD GetError() { return m_dwGleCode; }
  50. void Throw() { throw *this; }
  51. protected:
  52. DWORD m_dwGleCode;
  53. };
  54. #define THROW_API_EXCEPTION(description) \
  55. throw CApiException( \
  56. GetLastError(), \
  57. description, \
  58. _T(__FILE__), \
  59. __LINE__)
  60. void CountReparsePoints(PCTSTR pcszInput);
  61. void xGetRootDirectory(PCTSTR pcszInput, PTSTR* pszRootDir);
  62. HANDLE xOpenReparseIndex(PCTSTR pcszVolume);
  63. BOOL xGetNextReparseRecord(
  64. HANDLE hIndex,
  65. PFILE_REPARSE_POINT_INFORMATION ReparseInfo);
  66. HANDLE xOpenVolume(PCTSTR pcszVolume);
  67. void DisplayFileName(
  68. PTSTR pszVolume,
  69. HANDLE hVolume,
  70. LONGLONG llFileId);
  71. extern "C"
  72. void __cdecl _tmain(int argc, PTSTR argv[], PTSTR envv[])
  73. {
  74. if (argc==2)
  75. {
  76. CountReparsePoints(
  77. argv[1]);
  78. }
  79. else
  80. {
  81. _tprintf(
  82. _T("sisenum: Enumerates and lists all SIS files on a given volume.\n")
  83. _T("Usage: sisenum <location> <count>"));
  84. }
  85. }
  86. void CountReparsePoints(PCTSTR pcszInput)
  87. {
  88. PTSTR pszVolume = NULL;
  89. DWORD dwCount = 0;
  90. HANDLE hIndex = INVALID_HANDLE_VALUE;
  91. HANDLE hVolume = INVALID_HANDLE_VALUE;
  92. FILE_REPARSE_POINT_INFORMATION ReparseInfo;
  93. try
  94. {
  95. xGetRootDirectory(
  96. pcszInput,
  97. &pszVolume);
  98. hIndex = xOpenReparseIndex(
  99. pszVolume);
  100. hVolume = xOpenVolume(
  101. pszVolume);
  102. BOOL fDone = xGetNextReparseRecord(
  103. hIndex,
  104. &ReparseInfo);
  105. while (!fDone)
  106. {
  107. if (IO_REPARSE_TAG_SIS==ReparseInfo.Tag)
  108. {
  109. dwCount++;
  110. DisplayFileName(
  111. pszVolume,
  112. hVolume,
  113. ReparseInfo.FileReference);
  114. }
  115. fDone = xGetNextReparseRecord(
  116. hIndex,
  117. &ReparseInfo);
  118. }
  119. CloseHandle(hIndex);
  120. hIndex = INVALID_HANDLE_VALUE;
  121. _tprintf(
  122. _T("This volume (%s) contains %u SIS files.\n"),
  123. pszVolume,
  124. dwCount);
  125. }
  126. catch (CApiException& e)
  127. {
  128. _tprintf(
  129. _T("Failure: %s\nFile: %s\nLine: %u\nError: %u"),
  130. e.GetDescription(),
  131. e.GetFile(),
  132. e.GetLine(),
  133. e.GetError());
  134. }
  135. catch (CMemoryException& e)
  136. {
  137. _tprintf(
  138. _T("Out of memory.\n"));
  139. }
  140. if (hIndex!=INVALID_HANDLE_VALUE)
  141. {
  142. CloseHandle(
  143. hIndex);
  144. }
  145. if (hVolume!=INVALID_HANDLE_VALUE)
  146. {
  147. CloseHandle(
  148. hVolume);
  149. }
  150. delete []pszVolume;
  151. }
  152. void xGetRootDirectory(PCTSTR pcszInput, PTSTR* pszRootDir)
  153. {
  154. DWORD dwBufferSize = MAX_PATH;
  155. PTSTR pszTemp;
  156. *pszRootDir = NULL;
  157. BOOL bResult;
  158. DWORD dwGleCode;
  159. do
  160. {
  161. pszTemp = new TCHAR[dwBufferSize];
  162. bResult = GetVolumePathName(
  163. pcszInput,
  164. pszTemp,
  165. dwBufferSize);
  166. if (!bResult)
  167. {
  168. delete []pszTemp;
  169. dwGleCode = GetLastError();
  170. if (ERROR_BUFFER_OVERFLOW==dwGleCode)
  171. {
  172. dwBufferSize *= 2;
  173. }
  174. else
  175. {
  176. THROW_API_EXCEPTION(_T("GetVolumePathName failed."));
  177. }
  178. }
  179. } while (!bResult);
  180. *pszRootDir = pszTemp;
  181. }
  182. HANDLE xOpenReparseIndex(PCTSTR pcszVolume)
  183. {
  184. HANDLE hReparseIndex;
  185. PTSTR pszReparseIndex = NULL;
  186. pszReparseIndex = new TCHAR[_tcslen(pcszVolume)+64];
  187. _tcscpy(
  188. pszReparseIndex,
  189. pcszVolume);
  190. PathAddBackslash(pszReparseIndex);
  191. _tcscat(
  192. pszReparseIndex,
  193. _T("$Extend\\$Reparse:$R:$INDEX_ALLOCATION"));
  194. hReparseIndex = CreateFile(
  195. pszReparseIndex,
  196. GENERIC_READ,
  197. FILE_SHARE_READ,
  198. NULL,
  199. OPEN_EXISTING,
  200. FILE_FLAG_BACKUP_SEMANTICS | SECURITY_IMPERSONATION,
  201. NULL);
  202. delete []pszReparseIndex;
  203. if (INVALID_HANDLE_VALUE == hReparseIndex)
  204. {
  205. THROW_API_EXCEPTION(_T("Unable to open reparse index."));
  206. }
  207. return hReparseIndex;
  208. }
  209. HANDLE xOpenVolume(PCTSTR pcszVolume)
  210. {
  211. HANDLE hVolume = INVALID_HANDLE_VALUE;
  212. PTSTR pszVolumeName = NULL;
  213. pszVolumeName = new TCHAR[MAX_PATH];
  214. BOOL bResult = GetVolumeNameForVolumeMountPoint(
  215. pcszVolume,
  216. pszVolumeName,
  217. MAX_PATH);
  218. if (bResult)
  219. {
  220. hVolume = CreateFile(
  221. pszVolumeName,
  222. GENERIC_READ,
  223. FILE_SHARE_READ,
  224. NULL,
  225. OPEN_EXISTING,
  226. FILE_FLAG_BACKUP_SEMANTICS | SECURITY_IMPERSONATION,
  227. NULL);
  228. }
  229. delete []pszVolumeName;
  230. if (INVALID_HANDLE_VALUE == hVolume)
  231. {
  232. THROW_API_EXCEPTION(_T("Unable to open volume."));
  233. }
  234. return hVolume;
  235. }
  236. BOOL xGetNextReparseRecord(
  237. HANDLE hIndex,
  238. PFILE_REPARSE_POINT_INFORMATION ReparseInfo)
  239. {
  240. BOOL bResult = FALSE;
  241. IO_STATUS_BLOCK ioStatus;
  242. NTSTATUS status = NtQueryDirectoryFile(hIndex,
  243. NULL,
  244. NULL,
  245. NULL,
  246. &ioStatus,
  247. ReparseInfo,
  248. sizeof(FILE_REPARSE_POINT_INFORMATION),
  249. FileReparsePointInformation,
  250. TRUE,
  251. NULL,
  252. FALSE);
  253. if (!NT_SUCCESS(status))
  254. {
  255. SetLastError(RtlNtStatusToDosError(status));
  256. if (GetLastError() != ERROR_NO_MORE_FILES)
  257. {
  258. THROW_API_EXCEPTION(_T("Unable to open reparse index."));
  259. }
  260. bResult = TRUE;
  261. }
  262. return bResult;
  263. }
  264. void DisplayFileName(
  265. PTSTR pszVolume,
  266. HANDLE hVolume,
  267. LONGLONG llFileId)
  268. {
  269. UNICODE_STRING usIdString;
  270. NTSTATUS status;
  271. OBJECT_ATTRIBUTES ObjectAttributes;
  272. HANDLE hFile = INVALID_HANDLE_VALUE;
  273. IO_STATUS_BLOCK IoStatusBlock;
  274. struct {
  275. FILE_NAME_INFORMATION FileInformation;
  276. WCHAR FileName[MAX_PATH];
  277. } NameFile;
  278. ZeroMemory(
  279. &NameFile,
  280. sizeof(NameFile));
  281. usIdString.Length = sizeof(LONGLONG);
  282. usIdString.MaximumLength = sizeof(LONGLONG);
  283. usIdString.Buffer = (PWCHAR)&llFileId;
  284. InitializeObjectAttributes(
  285. &ObjectAttributes,
  286. &usIdString,
  287. OBJ_CASE_INSENSITIVE,
  288. hVolume,
  289. NULL); // security descriptor
  290. status = NtCreateFile(
  291. &hFile,
  292. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  293. &ObjectAttributes,
  294. &IoStatusBlock,
  295. NULL, // allocation size
  296. FILE_ATTRIBUTE_NORMAL,
  297. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  298. FILE_OPEN,
  299. FILE_NON_DIRECTORY_FILE | FILE_OPEN_BY_FILE_ID,
  300. NULL, // EA buffer
  301. 0); // EA length
  302. if (NT_SUCCESS(status))
  303. {
  304. status = NtQueryInformationFile(
  305. hFile,
  306. &IoStatusBlock,
  307. &(NameFile.FileInformation),
  308. sizeof(NameFile),
  309. FileNameInformation);
  310. if (NT_SUCCESS(status))
  311. {
  312. wprintf(L"%s\n",NameFile.FileInformation.FileName);
  313. }
  314. else
  315. {
  316. _tprintf(_T("Unable to query file name.\n"));
  317. }
  318. }
  319. else
  320. {
  321. _tprintf(_T("Unable to open file by ID.\n"));
  322. }
  323. if (hFile!=INVALID_HANDLE_VALUE)
  324. {
  325. CloseHandle(hFile);
  326. }
  327. }