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.

368 lines
11 KiB

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