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.

382 lines
11 KiB

  1. #include <pch.cxx>
  2. #pragma hdrstop
  3. #include <ole2.h>
  4. #define TRKDATA_ALLOCATE
  5. #include "trkwks.hxx"
  6. DWORD g_Debug = 0;
  7. inline void
  8. WriteToSnapshot( HANDLE hFileSnapshot, const TCHAR *ptsz )
  9. {
  10. ULONG cb, cbWritten;
  11. if( NULL != ptsz )
  12. cb = _tcslen( ptsz ) * sizeof(TCHAR);
  13. else
  14. {
  15. cb = sizeof(TCHAR);
  16. ptsz = TEXT("");
  17. }
  18. if( !WriteFile( hFileSnapshot, ptsz, cb, &cbWritten, NULL ))
  19. {
  20. TrkLog(( TRKDBG_ERROR, TEXT("Failed WriteFile (%lu)"), GetLastError() ));
  21. TrkRaiseLastError();
  22. }
  23. if( cb != cbWritten )
  24. {
  25. TrkLog(( TRKDBG_ERROR, TEXT("Not all of the data was written (%d/%d)"),
  26. cbWritten, cb ));
  27. TrkRaiseWin32Error( ERROR_WRITE_FAULT );
  28. }
  29. }
  30. void
  31. Usage()
  32. {
  33. printf( "\n" );
  34. printf( " Purpose: Take a snapshot of the volume ID and all object IDs for a volume\n" );
  35. printf( " Usage: toidsnap [-g|-s] <drive letter>: <snapshot file>\n" );
  36. printf( " Where: -g indicates get (create a snapshot)\n" );
  37. printf( " -s indicates set (from the snapshot file)\n" );
  38. printf( " E.g.: toidsnap -g d: snapshot.txt\n" );
  39. printf( " toidsnap -s d: snapshot.txt\n" );
  40. return;
  41. }
  42. EXTERN_C void __cdecl _tmain( int cArg, TCHAR *rgtszArg[] )
  43. {
  44. NTSTATUS status = 0;
  45. TCHAR tszFile[ MAX_PATH + 1 ];
  46. TCHAR tszDir[ MAX_PATH + 1 ];
  47. TCHAR* ptcTmp = NULL;
  48. LONG iVol;
  49. BOOL fSuccess = TRUE;
  50. BOOL fSaving = FALSE;
  51. HANDLE hFileSnapshot = INVALID_HANDLE_VALUE;
  52. HANDLE hMapping = INVALID_HANDLE_VALUE;
  53. IO_STATUS_BLOCK Iosb;
  54. TCHAR tszFileData[ 3 * MAX_PATH ];
  55. ULONG cLine = 0;
  56. TrkDebugCreate( TRK_DBG_FLAGS_WRITE_TO_DBG, "TOidSnap" );
  57. // -------------------------
  58. // Validate the command-line
  59. // -------------------------
  60. if( 4 != cArg )
  61. {
  62. Usage();
  63. goto Exit;
  64. }
  65. _tcslwr( rgtszArg[1] );
  66. _tcslwr( rgtszArg[2] );
  67. if( TEXT('-') != rgtszArg[1][0] && TEXT('/') != rgtszArg[1][0]
  68. ||
  69. TEXT('g') != rgtszArg[1][1] && TEXT('s') != rgtszArg[1][1]
  70. ||
  71. TEXT(':') != rgtszArg[2][1]
  72. ||
  73. TEXT('a') > rgtszArg[2][0] || TEXT('z') < rgtszArg[2][0]
  74. )
  75. {
  76. Usage();
  77. goto Exit;
  78. }
  79. fSaving = TEXT('g') == rgtszArg[1][1];
  80. iVol = rgtszArg[2][0] - TEXT('a');
  81. if( !IsLocalObjectVolume( iVol ))
  82. {
  83. _tprintf( TEXT("%c: isn't an NTFS5 volume\n"), VolChar(iVol) );
  84. goto Exit;
  85. }
  86. __try
  87. {
  88. FILE_FS_OBJECTID_INFORMATION fsobOID;
  89. EnableRestorePrivilege();
  90. // Open the snapshot file
  91. hFileSnapshot = CreateFile( rgtszArg[3],
  92. fSaving ? GENERIC_WRITE : GENERIC_READ,
  93. 0, NULL,
  94. fSaving ? CREATE_ALWAYS : OPEN_EXISTING,
  95. FILE_ATTRIBUTE_NORMAL, NULL );
  96. if( INVALID_HANDLE_VALUE == hFileSnapshot )
  97. {
  98. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't open file: %s (%lu)"),
  99. rgtszArg[3], GetLastError() ));
  100. TrkRaiseLastError();
  101. }
  102. // ----
  103. // Save
  104. // ----
  105. if( fSaving )
  106. {
  107. // Get the volid
  108. CVolumeId volid;
  109. status = QueryVolumeId( iVol, &volid );
  110. if( STATUS_OBJECT_NAME_NOT_FOUND != status && !NT_SUCCESS(status) )
  111. TrkRaiseNtStatus( status );
  112. // Write the volid to the snapshot file.
  113. WriteToSnapshot( hFileSnapshot, TEXT("VolId, ") );
  114. CStringize strVolid(volid);
  115. WriteToSnapshot( hFileSnapshot, static_cast<const TCHAR*>(strVolid) );
  116. WriteToSnapshot( hFileSnapshot, TEXT("\n") );
  117. WriteToSnapshot( hFileSnapshot, NULL );
  118. cLine++;
  119. CObjId objid;
  120. CDomainRelativeObjId droidBirth;
  121. CObjIdEnumerator oie;
  122. // Loop through the files with object IDs
  123. if(oie.Initialize(CVolumeDeviceName(iVol)) == TRUE)
  124. {
  125. if(oie.FindFirst(&objid, &droidBirth))
  126. {
  127. do
  128. {
  129. // Open the file so that we can get its path
  130. HANDLE hFile;
  131. status = OpenFileById( iVol, objid, SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  132. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  133. 0, &hFile);
  134. if( !NT_SUCCESS(status) )
  135. {
  136. TrkLog(( TRKDBG_ERROR, TEXT("Failed OpenFileById for %s"),
  137. static_cast<const TCHAR*>(CStringize(objid)) ));
  138. TrkRaiseNtStatus(status);
  139. }
  140. // Get the local path
  141. status = QueryVolRelativePath( hFile, tszFileData );
  142. if( !NT_SUCCESS(status) )
  143. {
  144. TrkLog(( TRKDBG_ERROR, TEXT("Failed QueryVolRelativePath for %s"),
  145. static_cast<const TCHAR*>(CStringize(objid)) ));
  146. TrkRaiseNtStatus(status);
  147. }
  148. // Write the path, objid, and birth ID to the snapshot file.
  149. _tcscat( tszFileData, TEXT(" = ") );
  150. _tcscat( tszFileData, static_cast<const TCHAR*>(CStringize(objid)) );
  151. _tcscat( tszFileData, TEXT(", ") );
  152. _tcscat( tszFileData, static_cast<const TCHAR*>(CStringize(droidBirth)) );
  153. _tcscat( tszFileData, TEXT("\n") );
  154. // Write a line terminator to the snapshot file.
  155. WriteToSnapshot( hFileSnapshot, tszFileData );
  156. WriteToSnapshot( hFileSnapshot, NULL );
  157. cLine++;
  158. } while(oie.FindNext(&objid, &droidBirth));
  159. // Write an marker to show end-of-file
  160. WriteToSnapshot( hFileSnapshot, TEXT("\n") );
  161. WriteToSnapshot( hFileSnapshot, NULL );
  162. }
  163. }
  164. printf( "%d IDs saved\n", cLine );
  165. } // if fSaving
  166. // ---------
  167. // Restoring
  168. // ---------
  169. else
  170. {
  171. ULONG cCollisions = 0, cSuccess = 0;
  172. TCHAR *ptsz = NULL;
  173. // Map the snapshot file into memory.
  174. hMapping = CreateFileMapping( hFileSnapshot, NULL, PAGE_READONLY, 0, 0, NULL );
  175. if( NULL == hMapping )
  176. {
  177. TrkLog(( TRKDBG_ERROR, TEXT("Failed CreateFileMapping") ));
  178. TrkRaiseLastError();
  179. }
  180. ptsz = reinterpret_cast<TCHAR*>( MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ));
  181. if( NULL == ptsz )
  182. {
  183. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't map view of file") ));
  184. TrkRaiseLastError();
  185. }
  186. // The file should start with the volid
  187. if( NULL == _tcsstr( ptsz, TEXT("VolId, ") ))
  188. {
  189. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't find volid") ));
  190. TrkRaiseException( E_FAIL );
  191. }
  192. // Move ptsz to the start of the stringized volid
  193. ptsz += _tcslen(TEXT("VolId, "));
  194. // Unstringize the volid and set it on the volume.
  195. CVolumeId volid;
  196. CStringize stringize;
  197. stringize.Use( ptsz );
  198. volid = stringize;
  199. status = SetVolId( iVol, volid );
  200. if( !NT_SUCCESS(status) )
  201. {
  202. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't set volid") ));
  203. TrkRaiseNtStatus(status);
  204. }
  205. cSuccess++;
  206. // Move past the eol & null after the volid.
  207. ptsz = _tcschr( ptsz, TEXT('\n') );
  208. if( NULL == ptsz || TEXT('\0') != ptsz[1] )
  209. {
  210. TrkLog(( TRKDBG_ERROR, TEXT("Unexpected end of file") ));
  211. TrkRaiseException( E_FAIL );
  212. }
  213. cLine++;
  214. ptsz += 2; // Past '\n' and '\0'
  215. // Init tszPath with the drive letter.
  216. TCHAR tszPath[ MAX_PATH + 1 ];
  217. tszPath[0] = VolChar(iVol);
  218. tszPath[1] = TEXT(':');
  219. // Loop through the object IDs in the snapshot file.
  220. // They are in the form:
  221. //
  222. // <file> = <objid>, <birth ID>
  223. //
  224. // E.g.
  225. // \test = {...}, {...}{...}
  226. while( TRUE )
  227. {
  228. // Find the separator between the file name and the objid
  229. TCHAR *ptszSep;
  230. ptszSep = _tcschr( ptsz, TEXT('=') );
  231. if( NULL == ptszSep )
  232. TrkRaiseException( E_FAIL );
  233. // cch is the length of the file name
  234. ULONG cch = ptszSep - ptsz;
  235. if( 0 == cch )
  236. TrkRaiseException( E_FAIL );
  237. cch--;
  238. // Put the file name into tszPath
  239. _tcsncpy( &tszPath[2], ptsz, cch );
  240. tszPath[2+cch] = TEXT('\0');
  241. // Move ptsz to the beginning of the stringized objid
  242. ptsz = ptszSep + 1;
  243. if( TEXT(' ') != *ptsz )
  244. TrkRaiseException( E_FAIL );
  245. ptsz++;
  246. // Unstringize the objid
  247. stringize.Use( ptsz );
  248. CObjId objid = stringize;
  249. // Move ptsz to the beginning of the birth ID, and unstringize it.
  250. ptsz = _tcschr( ptsz, TEXT(',') );
  251. if( NULL == ptsz || TEXT(' ') != ptsz[1] )
  252. TrkRaiseException( E_FAIL );
  253. ptsz += 2;
  254. stringize.Use( ptsz );
  255. CDomainRelativeObjId droidBirth;
  256. droidBirth = stringize;
  257. // Set the objid and birth ID
  258. status = SetObjId( tszPath, objid, droidBirth );
  259. if( STATUS_OBJECT_NAME_COLLISION == status )
  260. {
  261. cCollisions++;
  262. status = STATUS_SUCCESS;
  263. }
  264. else if( FAILED(status) )
  265. {
  266. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't set objid on %s"), tszPath ));
  267. TrkRaiseNtStatus( status );
  268. }
  269. else
  270. cSuccess++;
  271. //_tprintf( TEXT("Set %s on %s\n"), static_cast<const TCHAR*>(CStringize(objid)), tszPath );
  272. // Move to the endo of the line
  273. ptsz = _tcschr( ptsz, TEXT('\n') );
  274. if( NULL == ptsz || TEXT('\0') != ptsz[1] )
  275. TrkRaiseException( E_FAIL );
  276. // Move to the beginning of the next line
  277. ptsz += 2; // '\n' & '\0'
  278. // If this is an empty line, then we're at the end of the file.
  279. if( TEXT('\n') == *ptsz )
  280. break;
  281. } // while( TRUE )
  282. printf( "%d IDs successfully set, %d ID collisions\n", cSuccess, cCollisions );
  283. } // if fSaving ... else
  284. }
  285. __except( EXCEPTION_EXECUTE_HANDLER )
  286. {
  287. printf( "Error exception at line %d: %08x\n", cLine, GetExceptionCode() );
  288. }
  289. Exit:
  290. return;
  291. } // main()