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.

344 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. params.cpp
  5. Abstract:
  6. Class the manages the dump parameters
  7. Author:
  8. Stefan R. Steiner [ssteiner] 02-18-2000
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #define VERSION_INFO1 L"FsDumplib.lib Version 1.3g - 8/23/2000"
  13. #define VERSION_INFO2 L" Checksum version 2 - 2/22/2000"
  14. // Forward defines
  15. static BOOL
  16. AssertPrivilege(
  17. IN LPCWSTR privName
  18. );
  19. /*++
  20. Routine Description:
  21. Based on the class variables, sets up the utility to write to the
  22. correct files and gets backup privs.
  23. Arguments:
  24. None
  25. Return Value:
  26. <Enter return values here>
  27. --*/
  28. INT
  29. CDumpParameters::Initialize(
  30. IN INT argc,
  31. IN WCHAR *argv[]
  32. )
  33. {
  34. LPWSTR pwszFileName;
  35. //
  36. // Get the directory the fsdump.exe lives in. For use for finding .exclude files amoung
  37. // other things.
  38. //
  39. if ( ::GetFullPathName(
  40. m_cwsArgv0,
  41. FSD_MAX_PATH,
  42. m_cwsFullPathToEXE.GetBufferSetLength( FSD_MAX_PATH ),
  43. &pwszFileName ) == 0 )
  44. {
  45. ::fwprintf( stderr, L"ERROR getting full path for '%s', won't be able to find .include files\n", m_cwsArgv0.c_str() );
  46. m_cwsFullPathToEXE.ReleaseBuffer();
  47. }
  48. else
  49. {
  50. m_cwsFullPathToEXE.ReleaseBuffer();
  51. m_cwsArgv0 = m_cwsFullPathToEXE; // Keep the full path version
  52. CBsString m_cwsRight4 = m_cwsArgv0.Right( 4 );
  53. m_cwsRight4.MakeLower();
  54. if ( m_cwsRight4 != L".exe" )
  55. m_cwsArgv0 += L".exe";
  56. m_cwsFullPathToEXE = m_cwsFullPathToEXE.Left( m_cwsFullPathToEXE.GetLength() - ::wcslen( pwszFileName ) );
  57. }
  58. //
  59. // Set up checksum format
  60. //
  61. if ( m_bDumpCommaDelimited )
  62. ::wcscpy( m_pwszULongHexFmt, L"0x%08x" );
  63. else
  64. ::wcscpy( m_pwszULongHexFmt, L"%08x" );
  65. //
  66. // Set up the dump file
  67. //
  68. if ( m_cwsDumpFileName.IsEmpty() )
  69. {
  70. wprintf( L"fsdump: Printing dump information to 'stdout'\n" );
  71. }
  72. else
  73. {
  74. CBsString cwsFullPath;
  75. LPWSTR pwszFileName;
  76. //
  77. // Get the full path name for the dump file in case we change the working
  78. // directory later.
  79. //
  80. if ( ::GetFullPathName(
  81. m_cwsDumpFileName,
  82. FSD_MAX_PATH,
  83. cwsFullPath.GetBufferSetLength( FSD_MAX_PATH ),
  84. &pwszFileName ) == 0 )
  85. {
  86. ::fwprintf( stderr, L"ERROR - Unable to get full path name of dump file '%s' for write\n", m_cwsDumpFileName.c_str() );
  87. return 10;
  88. }
  89. cwsFullPath.ReleaseBuffer();
  90. m_cwsDumpFileName = cwsFullPath;
  91. m_fpDump = ::_wfopen( m_cwsDumpFileName, m_bUnicode ? L"wb" : L"w" );
  92. if ( m_fpDump == NULL )
  93. {
  94. ::fwprintf( stderr, L"ERROR - Unable to open dump file '%s' for write\n", m_cwsDumpFileName.c_str() );
  95. return 10;
  96. }
  97. if ( m_bNoHeaderFooter )
  98. {
  99. //
  100. // Try to create a named stream with the header and summary information
  101. //
  102. m_fpExtraInfoDump = ::_wfopen( m_cwsDumpFileName + L":Info", m_bUnicode ? L"wb" : L"w" );
  103. if ( m_fpExtraInfoDump != NULL )
  104. {
  105. wprintf( L"fsdump: Printing dump header and summary information to NTFS stream '%s'\n", (m_cwsDumpFileName + L":Info").c_str() );
  106. }
  107. else
  108. {
  109. m_fpExtraInfoDump = ::_wfopen( m_cwsDumpFileName + L".Info", m_bUnicode ? L"wb" : L"w" );
  110. if ( m_fpExtraInfoDump != NULL )
  111. {
  112. wprintf( L"fsdump: Printing dump header and summary information to file '%s'\n", (m_cwsDumpFileName + L".Info").c_str() );
  113. }
  114. else
  115. {
  116. wprintf( L"fsdump: Unable to create dump header and summary information file '%s'\n", (m_cwsDumpFileName + L".Info").c_str() );
  117. }
  118. }
  119. }
  120. else
  121. m_fpExtraInfoDump = m_fpDump;
  122. wprintf( L"fsdump: Printing dump information to '%s'\n", m_cwsDumpFileName.c_str() );
  123. }
  124. //
  125. // Set up the error log file
  126. //
  127. if ( m_cwsErrLogFileName.IsEmpty() )
  128. {
  129. wprintf( L"fsdump: Printing errors to 'stderr'\n" );
  130. }
  131. else
  132. {
  133. CBsString cwsFullPath;
  134. LPWSTR pwszFileName;
  135. //
  136. // Get the full path name for the dump file in case we change the working
  137. // directory later.
  138. //
  139. if ( ::GetFullPathName(
  140. m_cwsErrLogFileName,
  141. 1024,
  142. cwsFullPath.GetBufferSetLength( 1024 ),
  143. &pwszFileName ) == 0 )
  144. {
  145. fwprintf( stderr, L"ERROR - Unable to get full path name of error log file '%s' for write\n", m_cwsDumpFileName.c_str() );
  146. return 11;
  147. }
  148. cwsFullPath.ReleaseBuffer();
  149. m_cwsErrLogFileName = cwsFullPath;
  150. m_fpErrLog = ::_wfopen( m_cwsErrLogFileName, m_bUnicode ? L"wb" : L"w" );
  151. if ( m_fpErrLog == NULL )
  152. {
  153. ::fwprintf( stderr, L"ERROR - Unable to open error log file '%s' for write\n", m_cwsErrLogFileName.c_str() );
  154. return 11;
  155. }
  156. ::wprintf( L"fsdump: Printing errors to '%s'\n", m_cwsErrLogFileName.c_str() );
  157. }
  158. //
  159. // Print out a header in the dump file so that it is easy to determine
  160. // if dump formats are the same.
  161. //
  162. DumpPrint( VERSION_INFO1 );
  163. DumpPrint( VERSION_INFO2 );
  164. //
  165. // Dump out the command-line
  166. //
  167. CBsString cwsCommandLine;
  168. for ( INT idx = 0; idx < argc; ++idx )
  169. {
  170. cwsCommandLine += L" \"";
  171. cwsCommandLine += argv[ idx ];
  172. cwsCommandLine += L"\"";
  173. }
  174. DumpPrint( L" Command-line: %s", cwsCommandLine.c_str() );
  175. //
  176. // Enable backup and security privs
  177. //
  178. if ( !::AssertPrivilege( SE_BACKUP_NAME ) )
  179. DumpPrint( L" n.b. could not get SE_BACKUP_NAME Privilege (%d), will be unable to get certain information",
  180. ::GetLastError() );
  181. if ( !::AssertPrivilege( SE_SECURITY_NAME ) )
  182. {
  183. DumpPrint( L" n.b. could not get SE_SECURITY_NAME Privilege (%d), SACL entries information will be invalid",
  184. ::GetLastError() );
  185. m_bHaveSecurityPrivilege = FALSE;
  186. }
  187. DumpPrint( L" File attributes masked: %04x", m_dwFileAttributesMask );
  188. DumpPrint( L" Command line options enabled:" );
  189. if ( m_bHex )
  190. DumpPrint( L" Printing sizes in hexidecimal" );
  191. if ( m_bNoChecksums )
  192. DumpPrint( L" Checksums disabled" );
  193. if ( m_bUnicode )
  194. DumpPrint( L" Unicode output" );
  195. if ( m_bDontTraverseMountpoints )
  196. DumpPrint( L" Mountpoint traversal disabled" );
  197. if ( !m_bDontChecksumHighLatencyData )
  198. DumpPrint( L" High latency data checksum enabled" );
  199. if ( m_bAddMillisecsToTimestamps )
  200. DumpPrint( L" Adding millsecs to timestamps" );
  201. if ( m_bShowSymbolicSIDNames )
  202. DumpPrint( L" Converting SIDs to symbolic DOMAIN\\ACCOUNTNAME format" );
  203. if ( !m_bDontShowDirectoryTimestamps )
  204. DumpPrint( L" Dumping directory timestamps" );
  205. if ( m_bUseExcludeProcessor )
  206. {
  207. if ( m_bDontUseRegistryExcludes )
  208. DumpPrint( L" Excluding file based on exclude files" );
  209. else
  210. DumpPrint( L" Excluding file based on FilesNotToBackup reg keys and exclude files" );
  211. }
  212. if ( m_bDisableLongPaths )
  213. DumpPrint( L" Long path support disabled" );
  214. if ( m_bEnableObjectIdExtendedDataChecksums )
  215. DumpPrint( L" Object Id extended data checksums Enabled" );
  216. DumpPrint( L"" );
  217. fflush( GetDumpFile() );
  218. return 0;
  219. }
  220. /*++
  221. Routine Description:
  222. Destructor for the CDumpParameters class
  223. Arguments:
  224. None
  225. Return Value:
  226. <Enter return values here>
  227. --*/
  228. CDumpParameters::~CDumpParameters()
  229. {
  230. if ( m_fpDump != NULL && m_fpDump != stdout )
  231. ::fclose( m_fpDump );
  232. if ( m_fpExtraInfoDump != NULL && m_fpExtraInfoDump != m_fpDump )
  233. ::fclose( m_fpExtraInfoDump );
  234. if ( m_fpErrLog != NULL && m_fpErrLog != stderr )
  235. ::fclose( m_fpErrLog );
  236. }
  237. /*++
  238. Routine Description:
  239. Enables an NT privilege. Used to get backup privs in the utility.
  240. Arguments:
  241. privName - The privilege name.
  242. Return Value:
  243. <Enter return values here>
  244. --*/
  245. static BOOL
  246. AssertPrivilege(
  247. IN LPCWSTR privName
  248. )
  249. {
  250. HANDLE tokenHandle;
  251. BOOL stat = FALSE;
  252. if ( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &tokenHandle ) )
  253. {
  254. LUID value;
  255. if ( LookupPrivilegeValue( NULL, privName, &value ) )
  256. {
  257. TOKEN_PRIVILEGES newState;
  258. DWORD error;
  259. newState.PrivilegeCount = 1;
  260. newState.Privileges[0].Luid = value;
  261. newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  262. /*
  263. * We will always call GetLastError below, so clear
  264. * any prior error values on this thread.
  265. */
  266. SetLastError( ERROR_SUCCESS );
  267. stat = AdjustTokenPrivileges(
  268. tokenHandle,
  269. FALSE,
  270. &newState,
  271. (DWORD)0,
  272. NULL,
  273. NULL );
  274. /*
  275. * Supposedly, AdjustTokenPriveleges always returns TRUE
  276. * (even when it fails). So, call GetLastError to be
  277. * extra sure everything's cool.
  278. */
  279. if ( (error = GetLastError()) != ERROR_SUCCESS )
  280. {
  281. stat = FALSE;
  282. }
  283. }
  284. CloseHandle( tokenHandle );
  285. }
  286. return stat;
  287. }