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.

389 lines
9.1 KiB

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