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.

2135 lines
69 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. //--------------------------------------------------------------------------
  7. #include <pch.cxx>
  8. #pragma hdrstop
  9. #include <ole2.h>
  10. #define TRKDATA_ALLOCATE
  11. #include "trkwks.hxx"
  12. #include "trksvr.hxx"
  13. #include "dltadmin.hxx"
  14. OLECHAR *
  15. tcstoocs(OLECHAR *poszBuf, const TCHAR *ptsz)
  16. {
  17. #ifdef OLE2ANSI
  18. return tcstombs( poszBuf, ptsz );
  19. #else
  20. return tcstowcs( poszBuf, ptsz );
  21. #endif
  22. }
  23. TCHAR *
  24. ocstotcs(TCHAR *ptszBuf, const OLECHAR *posz)
  25. {
  26. #ifdef OLE2ANSI
  27. return mbstotcs( ptszBuf, posz );
  28. #else
  29. return wcstotcs( ptszBuf, posz );
  30. #endif
  31. }
  32. void Usage()
  33. {
  34. printf( "\nDistributed Link Tracking service admin tools\n"
  35. "\n"
  36. "Usage: dltadmin [command command-parameters]\n"
  37. "For help: dltadmin [command] -?\n"
  38. "Commands: -VolInfoFile (get volume info from a file path)\n"
  39. " -VolStat (volume statistics)\n"
  40. " -FileOid (set/get/use file Object IDs)\n"
  41. " -EnumOids (enumerate object IDs)\n"
  42. " -OidSnap (save/restore all OIDs)\n"
  43. " -Link (create/resolve shell link)\n"
  44. " -VolId (get/set volume IDs)\n"
  45. " -CleanVol (clean Object/Volume IDs)\n"
  46. " -LockVol (lock/dismount a volume)\n"
  47. " -SvrStat (trkSvr statistics)\n"
  48. " -LoadLib (load a dll into a process)\n"
  49. " -FreeLib (unload a dll from a process)\n"
  50. " -Config (configure the registry and/or runing service)\n"
  51. " -Refresh (refresh the trkwks volume list)\n"
  52. " -DebugBreak (break into a process)\n"
  53. " -LookupVolId (look up entry in DC volume table)\n"
  54. " -LookupDroid (look up entry in DC move table)\n"
  55. " -DelDcMoveId (del move table entry from DC)\n"
  56. " -DelDcVolId (del volume table entry from DC)\n"
  57. " -SetVolSeq (set volid sequence number)\n"
  58. " -SetDroidSeq (set move entry sequence number)\n" );
  59. }
  60. // Dummy function to make it link
  61. void
  62. ServiceStopCallback( PVOID pContext, BOOLEAN fTimeout )
  63. {
  64. return;
  65. }
  66. VOID
  67. TSZ2CLSID( const LPTSTR tszCLSID, CLSID *pclsid )
  68. {
  69. HRESULT hr = S_OK;
  70. OLECHAR oszCLSID[ CCH_GUID_STRING + 1 ];
  71. tcstoocs( oszCLSID, tszCLSID );
  72. hr = CLSIDFromString( oszCLSID, pclsid );
  73. if( FAILED(hr) )
  74. {
  75. TrkLog((TRKDBG_ERROR, TEXT("Couldn't convert string to CLSID") ));
  76. TrkRaiseException( hr );
  77. }
  78. }
  79. BOOL
  80. DltAdminLockVol( ULONG cArgs, TCHAR * const rgptszArgs[], ULONG *pcEaten )
  81. {
  82. HRESULT hr = S_OK;
  83. NTSTATUS status = 0;
  84. ULONG iVolume = static_cast<ULONG>(-1);
  85. TCHAR tszVolume[ ] = TEXT("\\\\.\\A:");
  86. OBJECT_ATTRIBUTES ObjAttr;
  87. IO_STATUS_BLOCK Iosb;
  88. UNICODE_STRING uPath;
  89. HANDLE hVolume = NULL;
  90. BOOL fSuccess = FALSE;
  91. CHAR rgcCommands[ 10 ];
  92. ULONG iCommand = 0, cCommands = 0;
  93. *pcEaten = 0;
  94. if( 0 == cArgs
  95. ||
  96. 1 <= cArgs && IsHelpArgument(rgptszArgs[0]) )
  97. {
  98. *pcEaten = 1;
  99. printf( "\nOption LockVol\n"
  100. " Purpose: Lock and/or dismount a volume\n"
  101. " Usage: -LockVol <options> <drive letter>:\n"
  102. " Where: <options> are any combination (up to %d) of:\n"
  103. " -d Send FSCTL_DISMOUNT_VOLUME\n"
  104. " -l Send FSCTL_LOCK_VOLUME\n"
  105. " -u Send FSCTL_UNLOCK_VOLUME\n"
  106. " -p Pause for user input\n"
  107. " E.g.: -LockVol -d -l -u c:\n"
  108. " -LockVol -l c:\n",
  109. ELEMENTS(rgcCommands) );
  110. return( TRUE );
  111. }
  112. for( int iArgs = 0; iArgs < cArgs; iArgs++ )
  113. {
  114. if( 2 == _tcslen( rgptszArgs[iArgs] ) && TEXT(':') == rgptszArgs[iArgs][1] )
  115. {
  116. TCHAR tc = rgptszArgs[iArgs][0];
  117. if( TEXT('A') <= tc && TEXT('Z') >= tc )
  118. iVolume = tc - TEXT('A');
  119. else if( TEXT('a') <= tc && TEXT('z') >= tc )
  120. iVolume = tc - TEXT('a');
  121. }
  122. else if( TEXT('-') == rgptszArgs[iArgs][0]
  123. ||
  124. TEXT('/') == rgptszArgs[iArgs][0] )
  125. {
  126. _tcslwr(rgptszArgs[iArgs]);
  127. if( iCommand >= ELEMENTS(rgcCommands) )
  128. {
  129. printf( "Too many commands to LockVol. Use -? for usage info.\n" );
  130. return( FALSE );
  131. }
  132. if( TEXT('d') == rgptszArgs[iArgs][1] )
  133. rgcCommands[iCommand] = 'd';
  134. else
  135. if( TEXT('l') == rgptszArgs[iArgs][1] )
  136. rgcCommands[iCommand] = 'l';
  137. else
  138. if( TEXT('u') == rgptszArgs[iArgs][1] )
  139. rgcCommands[iCommand] = 'u';
  140. else
  141. if( TEXT('p') == rgptszArgs[iArgs][1] )
  142. rgcCommands[iCommand] = 'p';
  143. else
  144. {
  145. printf( "Invalid option. Use -? for usage info.\n" );
  146. return( FALSE );
  147. }
  148. }
  149. cCommands++;
  150. iCommand++;
  151. (*pcEaten)++;
  152. }
  153. if( static_cast<ULONG>(-1) == iVolume )
  154. {
  155. printf( "Invalid parameter. Use -? for usage info\n" );
  156. return( FALSE );
  157. }
  158. tszVolume[4] += static_cast<TCHAR>(iVolume);
  159. if( !RtlDosPathNameToNtPathName_U( tszVolume, &uPath, NULL, NULL ))
  160. {
  161. status = STATUS_OBJECT_NAME_INVALID;
  162. goto Exit;
  163. }
  164. InitializeObjectAttributes(
  165. &ObjAttr,
  166. &uPath,
  167. OBJ_CASE_INSENSITIVE,
  168. NULL,
  169. NULL
  170. );
  171. status = NtOpenFile(
  172. &hVolume,
  173. FILE_READ_DATA|FILE_WRITE_DATA|SYNCHRONIZE,
  174. &ObjAttr,
  175. &Iosb,
  176. FILE_SHARE_READ | FILE_SHARE_WRITE,
  177. FILE_SYNCHRONOUS_IO_ALERT
  178. );
  179. if( !NT_SUCCESS(status) )
  180. {
  181. printf( "Failed NtOpenFile of %s (%08x)\n", tszVolume, status );
  182. goto Exit;
  183. }
  184. for( iCommand = 0; iCommand < cCommands; iCommand++ )
  185. {
  186. switch( rgcCommands[iCommand] )
  187. {
  188. case 'd':
  189. {
  190. status = NtFsControlFile(
  191. hVolume,
  192. NULL, /* Event */
  193. NULL, /* ApcRoutine */
  194. NULL, /* ApcContext */
  195. &Iosb,
  196. FSCTL_DISMOUNT_VOLUME,
  197. NULL, /* InputBuffer */
  198. 0, /* InputBufferLength */
  199. NULL, /* OutputBuffer */
  200. 0 /* OutputBufferLength */
  201. );
  202. if( !NT_SUCCESS(status) )
  203. printf( "Failed FSCTL_DISMOUNT_VOLUME (%08x)\n", status );
  204. else
  205. printf( "Volume dismounted\n" );
  206. }
  207. break;
  208. case 'l':
  209. {
  210. status = NtFsControlFile(
  211. hVolume,
  212. NULL, /* Event */
  213. NULL, /* ApcRoutine */
  214. NULL, /* ApcContext */
  215. &Iosb,
  216. FSCTL_LOCK_VOLUME,
  217. NULL, /* InputBuffer */
  218. 0, /* InputBufferLength */
  219. NULL, /* OutputBuffer */
  220. 0 /* OutputBufferLength */
  221. );
  222. if( !NT_SUCCESS(status) )
  223. printf( "Failed FSCTL_LOCK_VOLUME (%08x)\n", status );
  224. else
  225. printf( "Volume is locked\n" );
  226. }
  227. break;
  228. case 'u':
  229. {
  230. status = NtFsControlFile(
  231. hVolume,
  232. NULL, /* Event */
  233. NULL, /* ApcRoutine */
  234. NULL, /* ApcContext */
  235. &Iosb,
  236. FSCTL_UNLOCK_VOLUME,
  237. NULL, /* InputBuffer */
  238. 0, /* InputBufferLength */
  239. NULL, /* OutputBuffer */
  240. 0 /* OutputBufferLength */
  241. );
  242. if( !NT_SUCCESS(status) )
  243. printf( "Failed FSCTL_UNLOCK_VOLUME (%08x)\n", status );
  244. else
  245. printf( "Volume unlocked\n" );
  246. }
  247. break;
  248. case 'p':
  249. {
  250. printf( "Press enter to unlock ..." );
  251. getchar();
  252. }
  253. break;
  254. } // switch( rgcCommands[iCommand] )
  255. } // for( iCommand = 0; iCommand < cCommands; iCommand++ )
  256. fSuccess = TRUE;
  257. Exit:
  258. return( fSuccess );
  259. }
  260. void
  261. MakeAbsolutePath( TCHAR * ptszAbsolute, TCHAR * ptszRelative )
  262. {
  263. if( !_tcsncmp( TEXT("\\\\"), ptszRelative, 2 ) // A UNC path
  264. ||
  265. TEXT(':') == ptszRelative[1] ) // A drive-based path
  266. {
  267. // The command-line has an absolute path
  268. _tcscpy( ptszAbsolute, ptszRelative );
  269. }
  270. else
  271. {
  272. // The command-line has a relative path
  273. DWORD dwLength = 0;
  274. dwLength = GetCurrentDirectory( MAX_PATH, ptszAbsolute );
  275. if( 0 == dwLength )
  276. {
  277. TrkLog((TRKDBG_ERROR, TEXT("Couldn't get current directory") ));
  278. TrkRaiseLastError( );
  279. }
  280. if( TEXT('\\') != ptszAbsolute[dwLength-1] )
  281. _tcscat( ptszAbsolute, TEXT("\\") );
  282. _tcscat( ptszAbsolute, ptszRelative );
  283. }
  284. }
  285. BOOL
  286. DltAdminFileOid( ULONG cArgs, TCHAR * const rgptszArgs[], ULONG *pcEaten )
  287. {
  288. HRESULT hr = S_OK;
  289. NTSTATUS status = 0;
  290. TCHAR tszFile[ MAX_PATH + 1 ];
  291. WCHAR wszFile[ MAX_PATH + 1 ];
  292. TCHAR tszUNCPath[ MAX_PATH + 1 ];
  293. WCHAR wszOID[ CCH_GUID_STRING + 1 ];
  294. ULONG cbInBuffer;
  295. TCHAR tszMachineName[ MAX_PATH + 1 ];
  296. LPCTSTR tszVolumePath = NULL;
  297. USHORT iVolume;
  298. OLECHAR oszOID[ CCH_GUID_STRING + 1 ];
  299. EnablePrivilege( SE_RESTORE_NAME );
  300. *pcEaten = 0;
  301. // -------------------------
  302. // Validate the command-line
  303. // -------------------------
  304. if( 1 <= cArgs && IsHelpArgument( rgptszArgs[0] ))
  305. {
  306. *pcEaten = 1;
  307. printf( "\nOption FileOID\n"
  308. " Purpose: Get/set/use file Object IDs\n"
  309. " Usage: -fileoid <option> <filename or object id, depending on the option>\n"
  310. " Options: -r => Read the object ID from a file\n"
  311. " -g => Get (creating if necessary) the object ID from a file\n"
  312. " -f => Search the local machine for an object ID's filename\n"
  313. " -s => Set an ID on a file (specify objid, then filename)\n"
  314. " -sr => Make a file reborn\n"
  315. " -df => Delete the object ID from it's file, given the filename\n"
  316. " -do => Delete the object ID from it's file, given the object ID\n"
  317. " E.g.: -fileoid -g d:\\test.txt\n"
  318. " -fileoid -r d:\\test.txt\n"
  319. " -fileoid -f {C69F3AA6-8B4C-11D0-8C9D-00C04FD90F85}\n"
  320. " -fileoid -do {C69F3AA6-8B4C-11D0-8C9D-00C04FD90F85}\n"
  321. " -fileoid -df d:\\test.txt\n" );
  322. return( TRUE );
  323. }
  324. else
  325. if( 2 > cArgs
  326. ||
  327. rgptszArgs[0][0] != TEXT('-')
  328. &&
  329. rgptszArgs[0][0] != TEXT('/')
  330. )
  331. {
  332. printf( "Parameter error. Use -? for usage info\n" );
  333. }
  334. *pcEaten = 2;
  335. // Convert the option to upper case (options are case-insensitive).
  336. _tcsupr( rgptszArgs[0] );
  337. __try
  338. {
  339. // Switch on the option (e.g, the 'F' in "-F")
  340. switch( rgptszArgs[0][1] )
  341. {
  342. // --------------------------------
  343. // Get a file name from an ObjectID
  344. // --------------------------------
  345. case TEXT('F'):
  346. {
  347. CDomainRelativeObjId droidBirth;
  348. // Get the OID in binary format
  349. CObjId oid;
  350. TSZ2CLSID( rgptszArgs[1], (GUID*)&oid );
  351. // Scan the volumes for this objectID
  352. for (LONG vol = 0; vol < 26; vol++)
  353. {
  354. if( IsLocalObjectVolume( vol )
  355. &&
  356. NT_SUCCESS(FindLocalPath(vol, oid, &droidBirth, &tszUNCPath[2])) )
  357. {
  358. tszUNCPath[0] = VolChar(vol);
  359. tszUNCPath[1] = TEXT(':');
  360. break;
  361. }
  362. }
  363. if( 'z'-'a' == vol )
  364. {
  365. hr = ERROR_FILE_NOT_FOUND;
  366. __leave;
  367. }
  368. // Display the filename
  369. wprintf( L"File name = \"%s\"\n", tszUNCPath );
  370. }
  371. break;
  372. // --------------------
  373. // Read/Get an ObjectID
  374. // --------------------
  375. case TEXT('R'):
  376. case TEXT('G'):
  377. {
  378. TCHAR tszFile[ MAX_PATH + 1 ];
  379. MakeAbsolutePath( tszFile, rgptszArgs[1] );
  380. CDomainRelativeObjId droidCurrent;
  381. CDomainRelativeObjId droidBirth;
  382. status = GetDroids( tszFile, &droidCurrent, &droidBirth,
  383. rgptszArgs[0][1] == TEXT('R') ? RGO_READ_OBJECTID : RGO_GET_OBJECTID );
  384. if( !NT_SUCCESS(status) )
  385. {
  386. hr = status;
  387. __leave;
  388. }
  389. _tprintf( TEXT("Current:\n") );
  390. _tprintf( TEXT(" volid = %s\n"),
  391. static_cast<const TCHAR*>(CStringize(droidCurrent.GetVolumeId() )));
  392. _tprintf( TEXT(" objid = %s\n"),
  393. static_cast<const TCHAR*>(CStringize(droidCurrent.GetObjId() )));
  394. _tprintf( TEXT("Birth:\n") );
  395. _tprintf( TEXT(" volid = %s\n"),
  396. static_cast<const TCHAR*>(CStringize(droidBirth.GetVolumeId() )));
  397. _tprintf( TEXT(" objid = %s\n"),
  398. static_cast<const TCHAR*>(CStringize(droidBirth.GetObjId() )));
  399. }
  400. break;
  401. // ---------------
  402. // Set an ObjectID
  403. // ---------------
  404. case TEXT('S'):
  405. {
  406. HANDLE hFile;
  407. CObjId objid;
  408. IO_STATUS_BLOCK IoStatus;
  409. TCHAR tszFile[ MAX_PATH + 1 ];
  410. if( TEXT('R') == rgptszArgs[0][2] )
  411. {
  412. if( 2 > cArgs )
  413. {
  414. printf( "Parameter error. Use -? for usage info\n" );
  415. hr = E_FAIL;
  416. goto Exit;
  417. }
  418. (*pcEaten)++;
  419. MakeAbsolutePath( tszFile, rgptszArgs[1] );
  420. status = TrkCreateFile( tszFile, FILE_READ_ATTRIBUTES,
  421. FILE_ATTRIBUTE_NORMAL,
  422. FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
  423. FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_NO_RECALL | FILE_SYNCHRONOUS_IO_NONALERT,
  424. NULL,
  425. &hFile );
  426. if (!NT_SUCCESS(status))
  427. {
  428. printf( "TrkCreateFile failed\n" );
  429. hr = status;
  430. __leave;
  431. }
  432. status = MakeObjIdReborn( hFile );
  433. if( NT_SUCCESS(status) )
  434. printf( "File is reborn\n" );
  435. else
  436. printf( "Failed to make reborn (%08x)\n", status );
  437. }
  438. else
  439. {
  440. TSZ2CLSID( rgptszArgs[1], (GUID*)&objid );
  441. if( 3 > cArgs )
  442. {
  443. printf( "Parameter error. Use -? for usage info\n" );
  444. hr = E_FAIL;
  445. goto Exit;
  446. }
  447. (*pcEaten)++;
  448. MakeAbsolutePath( tszFile, rgptszArgs[2] );
  449. status = TrkCreateFile( tszFile, FILE_READ_ATTRIBUTES,
  450. FILE_ATTRIBUTE_NORMAL,
  451. FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
  452. FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_NO_RECALL | FILE_SYNCHRONOUS_IO_NONALERT,
  453. NULL,
  454. &hFile );
  455. if (!NT_SUCCESS(status))
  456. {
  457. printf( "TrkCreateFile failed\n" );
  458. hr = status;
  459. __leave;
  460. }
  461. status = SetObjId( hFile, objid, CDomainRelativeObjId() );
  462. if (!NT_SUCCESS(status))
  463. {
  464. printf( "FSCTL_SET_OBJECT_ID failed\n" );
  465. hr = status;
  466. __leave;
  467. }
  468. printf( "ID set ok\n" );
  469. }
  470. }
  471. break;
  472. case TEXT('D'):
  473. {
  474. if( TEXT('F') == rgptszArgs[0][2] )
  475. {
  476. TCHAR tszFile[ MAX_PATH + 1 ];
  477. HANDLE hFile;
  478. NTSTATUS status;
  479. IO_STATUS_BLOCK IoStatus;
  480. MakeAbsolutePath( tszFile, rgptszArgs[1] );
  481. status = TrkCreateFile( tszFile, FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  482. FILE_ATTRIBUTE_NORMAL,
  483. FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
  484. FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_NO_RECALL | FILE_SYNCHRONOUS_IO_NONALERT,
  485. NULL,
  486. &hFile );
  487. if (!NT_SUCCESS(status))
  488. {
  489. printf( "TrkCreateFile failed\n" );
  490. hr = status;
  491. __leave;
  492. }
  493. status = NtFsControlFile(
  494. hFile,
  495. NULL,
  496. NULL,
  497. NULL,
  498. &IoStatus,
  499. FSCTL_DELETE_OBJECT_ID,
  500. NULL, // in buffer
  501. 0, // in buffer size
  502. NULL, // Out buffer
  503. 0); // Out buffer size
  504. if (!NT_SUCCESS(status))
  505. {
  506. printf( "FSCTL_DELETE_OBJECT_ID failed\n" );
  507. hr = status;
  508. __leave;
  509. }
  510. printf( "Deleted ok\n" );
  511. }
  512. else if( TEXT('O') == rgptszArgs[0][2] )
  513. {
  514. // Get the OID in binary format
  515. CObjId oid;
  516. CDomainRelativeObjId droidBirth;
  517. TSZ2CLSID( rgptszArgs[1], (GUID*)&oid );
  518. BOOL fFound = FALSE;
  519. for (int vol='a'-'a'; vol<'z'-'a'; vol++)
  520. {
  521. if( IsLocalObjectVolume(CVolumeDeviceName(vol)) )
  522. {
  523. status = FindLocalPath(vol, oid, &droidBirth, &tszUNCPath[2]);
  524. if( STATUS_OBJECT_NAME_NOT_FOUND == status )
  525. continue;
  526. if( !NT_SUCCESS(status) ) goto Exit;
  527. tszUNCPath[0] = VolChar(vol);
  528. tszUNCPath[1] = TEXT(':');
  529. _tprintf( TEXT("Deleting object ID on %s\n"), tszUNCPath );
  530. status = DelObjId( vol, oid );
  531. if( !NT_SUCCESS(status) ) goto Exit;
  532. printf( "Deleted ok\n" );
  533. break;
  534. }
  535. }
  536. if( fFound ) printf( "Not found\n" );
  537. }
  538. else
  539. printf( "Bad parameter\n" );
  540. } // case TEXT('D'):
  541. break;
  542. } // switch
  543. hr = S_OK;
  544. } // __try
  545. __except( BreakOnDebuggableException() )
  546. {
  547. hr = GetExceptionCode();
  548. }
  549. Exit:
  550. if( FAILED(hr) )
  551. printf( "HR = %08X\n", hr );
  552. return SUCCEEDED(hr);
  553. }
  554. BOOL
  555. DltAdminTemp( ULONG cArgs, TCHAR * const rgptszArgs[], ULONG *pcEaten )
  556. {
  557. HRESULT hr = E_FAIL;
  558. RPC_STATUS rpcstatus;
  559. RPC_TCHAR * ptszStringBinding;
  560. RPC_BINDING_HANDLE hBinding = NULL;
  561. BOOL fBound = FALSE;
  562. LONG iVol = 4;
  563. GUID volid = { /* 9f1534ee-ceab-4710-98b9-daaf048e3ad2 */
  564. 0x9f1534ee,
  565. 0xceab,
  566. 0x4710,
  567. {0x98, 0xb9, 0xda, 0xaf, 0x04, 0x8e, 0x3a, 0xd2}
  568. };
  569. if( 1 <= cArgs && IsHelpArgument( rgptszArgs[0] ))
  570. {
  571. printf("\nOption Refresh\n"
  572. " Purpose: Temp test placeholder\n"
  573. " Usage: -temp\n" );
  574. return( TRUE );
  575. }
  576. rpcstatus = RpcStringBindingCompose( NULL, TEXT("ncalrpc"), NULL, TEXT("trkwks"),
  577. NULL, &ptszStringBinding);
  578. if( rpcstatus )
  579. {
  580. TrkLog(( TRKDBG_ERROR, TEXT("Failed RpcStringBindingCompose %lu"), rpcstatus ));
  581. hr = HRESULT_FROM_WIN32(rpcstatus);
  582. goto Exit;
  583. }
  584. rpcstatus = RpcBindingFromStringBinding( ptszStringBinding, &hBinding );
  585. RpcStringFree( &ptszStringBinding );
  586. if( rpcstatus )
  587. {
  588. TrkLog(( TRKDBG_ERROR, TEXT("Failed RpcBindingFromStringBinding") ));
  589. hr = HRESULT_FROM_WIN32(rpcstatus);
  590. goto Exit;
  591. }
  592. fBound = TRUE;
  593. __try
  594. {
  595. hr = LnkSetVolumeId( hBinding, iVol, volid );
  596. }
  597. __except( EXCEPTION_EXECUTE_HANDLER )
  598. {
  599. hr = HRESULT_FROM_WIN32( GetExceptionCode() );
  600. }
  601. if( FAILED(hr) )
  602. {
  603. _tprintf( TEXT("Failed call to service (%08x)\n"), hr );
  604. goto Exit;
  605. }
  606. Exit:
  607. if( fBound )
  608. RpcBindingFree( &hBinding );
  609. return( TRUE );
  610. } // main()
  611. CVolumeId
  612. DisplayLogStatus( LONG iVol )
  613. {
  614. NTSTATUS status = STATUS_SUCCESS;
  615. HANDLE hFile = NULL;
  616. TCHAR tszLog[ MAX_PATH + 1 ];
  617. ULONG cbRead;
  618. LogHeader logheader;
  619. LogInfo loginfo;
  620. VolumePersistentInfo volinfo;
  621. _tcscpy( tszLog, CVolumeDeviceName(iVol) );
  622. _tcscat( tszLog, s_tszLogFileName );
  623. status = TrkCreateFile( tszLog, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL,
  624. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  625. FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, &hFile );
  626. if( !NT_SUCCESS(status) )
  627. {
  628. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't open %s"), tszLog ));
  629. TrkRaiseNtStatus(status);
  630. }
  631. if( !ReadFile( hFile, &logheader, sizeof(logheader), &cbRead, NULL )
  632. ||
  633. sizeof(logheader) != cbRead )
  634. {
  635. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't read log header") ));
  636. TrkRaiseLastError();
  637. }
  638. if( !ReadFile( hFile, &volinfo, sizeof(volinfo), &cbRead, NULL )
  639. ||
  640. sizeof(volinfo) != cbRead )
  641. {
  642. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't read volinfo") ));
  643. TrkRaiseLastError();
  644. }
  645. if( !ReadFile( hFile, &loginfo, sizeof(loginfo), &cbRead, NULL )
  646. ||
  647. sizeof(loginfo) != cbRead )
  648. {
  649. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't read loginfo") ));
  650. TrkRaiseLastError();
  651. }
  652. _tprintf( TEXT("\nLog Header:\n") );
  653. _tprintf( TEXT(" guidSignature = \t%s\n"), static_cast<const TCHAR*>(CStringize(logheader.guidSignature)) );
  654. _tprintf( TEXT(" dwFormat = \t\t0x%x,0x%x\n"), logheader.dwFormat>>16, logheader.dwFormat&0xFFFF );
  655. _tprintf( TEXT(" ProperShutdown = \t%s\n"), (logheader.dwFlags & PROPER_SHUTDOWN) ? TEXT("True") : TEXT("False") );
  656. _tprintf( TEXT(" DownlevelDirtied = \t%s\n"), (logheader.dwFlags & DOWNLEVEL_DIRTIED) ? TEXT("True") : TEXT("False") );
  657. _tprintf( TEXT(" Expansion start = \t%d\n"), logheader.expand.ilogStart );
  658. _tprintf( TEXT(" end = \t%d\n"), logheader.expand.ilogEnd );
  659. _tprintf( TEXT(" cb = \t%d\n"), logheader.expand.cbFile );
  660. _tprintf( TEXT("\nLog Information:\n") );
  661. _tprintf( TEXT(" Start = \t\t%lu\n"), loginfo.ilogStart );
  662. _tprintf( TEXT(" End = \t\t%lu\n"), loginfo.ilogEnd );
  663. _tprintf( TEXT(" Write = \t\t%lu\n"), loginfo.ilogWrite );
  664. _tprintf( TEXT(" Read = \t\t%lu\n"), loginfo.ilogRead );
  665. _tprintf( TEXT(" Last = \t\t%lu\n"), loginfo.ilogLast );
  666. _tprintf( TEXT(" seqNext = \t\t%li\n"), loginfo.seqNext );
  667. _tprintf( TEXT(" seqLastRead = \t%li\n"), loginfo.seqLastRead );
  668. CVolumeId volidNTFS;
  669. status = QueryVolumeId( iVol, &volidNTFS );
  670. if( !NT_SUCCESS(status) )
  671. {
  672. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't get NTFS volume ID") ));
  673. TrkRaiseNtStatus(status);
  674. }
  675. _tprintf( TEXT("\nVolume Information:\n") );
  676. _tprintf( TEXT(" Machine = \t\t%s\n"), static_cast<const TCHAR*>(CStringize(volinfo.machine)) );
  677. _tprintf( TEXT(" VolId (log) = \t%s\n"), static_cast<const TCHAR*>(CStringize(volinfo.volid)) );
  678. _tprintf( TEXT(" VolId (NTFS) = \t%s\n"), static_cast<const TCHAR*>(CStringize(volidNTFS)) );
  679. _tprintf( TEXT(" Secret = \t\t%s\n"), static_cast<const TCHAR*>(CStringize(volinfo.secret)) );
  680. _tprintf( TEXT(" Last Refresh = \t%d\n"), volinfo.cftLastRefresh.LowDateTime() );
  681. _tprintf( TEXT(" Enter not-owned = \t%s\n"), volinfo.cftEnterNotOwned == CFILETIME(0)
  682. ? TEXT("(N/A)")
  683. : static_cast<const TCHAR*>(CStringize(volinfo.cftEnterNotOwned)) );
  684. _tprintf( TEXT(" Make OIDs reborn = \t%s\n"), volinfo.fDoMakeAllOidsReborn ? TEXT("True") : TEXT("False") );
  685. _tprintf( TEXT(" Not-Created = \t%s\n"), volinfo.fNotCreated ? TEXT("True") : TEXT("False") );
  686. if( NULL != hFile )
  687. NtClose( hFile );
  688. return( volinfo.volid );
  689. }
  690. void
  691. DisplayDcStatus( const CVolumeId &volid )
  692. {
  693. CRpcClientBinding rc;
  694. TRKSVR_SYNC_VOLUME SyncVolume;
  695. TRKSVR_MESSAGE_UNION Msg;
  696. CMachineId mcidLocal( MCID_LOCAL );
  697. HRESULT hr = S_OK;
  698. rc.RcInitialize( mcidLocal, s_tszTrkWksLocalRpcProtocol, s_tszTrkWksLocalRpcEndPoint, NO_AUTHENTICATION );
  699. printf( "\nDC Information:\n" );
  700. __try
  701. {
  702. Msg.MessageType = SYNC_VOLUMES;
  703. Msg.ptszMachineID = NULL;
  704. Msg.Priority = PRI_9;
  705. Msg.SyncVolumes.cVolumes = 1;
  706. Msg.SyncVolumes.pVolumes = &SyncVolume;
  707. SyncVolume.hr = S_OK;
  708. SyncVolume.SyncType = QUERY_VOLUME;
  709. SyncVolume.volume = volid;
  710. hr = LnkCallSvrMessage( rc, &Msg );
  711. }
  712. __except( EXCEPTION_EXECUTE_HANDLER )
  713. {
  714. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  715. }
  716. if( FAILED(hr) )
  717. {
  718. printf( " Couldn't get status from DC: %08x\n", hr );
  719. if( HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr )
  720. printf( " Make sure you have the 0x1 bit set in the TestFlags registry value\n" );
  721. goto Exit;
  722. }
  723. if( TRK_S_VOLUME_NOT_FOUND == SyncVolume.hr )
  724. {
  725. printf( " Volume is not in DC\n" );
  726. }
  727. else if( TRK_S_VOLUME_NOT_OWNED == SyncVolume.hr )
  728. {
  729. printf( " Volume is not owned by this machine\n" );
  730. }
  731. else if( S_OK == SyncVolume.hr )
  732. {
  733. _tprintf( TEXT(" Sequence # = \t%li\n"), SyncVolume.seq );
  734. _tprintf( TEXT(" Last Refresh = \t%lu\n"), SyncVolume.ftLastRefresh.dwLowDateTime );
  735. //static_cast<const TCHAR*>(CStringize(CFILETIME(SyncVolume.ftLastRefresh))) );
  736. }
  737. else
  738. {
  739. printf( " Volume state couldn't get queried from DC: %08x\n", hr );
  740. }
  741. Exit:
  742. return;
  743. }
  744. void
  745. DisplayOidInformation( LONG iVol )
  746. {
  747. CObjId objid;
  748. CDomainRelativeObjId droid;
  749. CObjIdEnumerator oie;
  750. ULONG cFilesWithOid = 0;
  751. ULONG cCrossVolumeBitSet = 0;
  752. if(oie.Initialize(CVolumeDeviceName(iVol)) == TRUE)
  753. {
  754. if(oie.FindFirst(&objid, &droid))
  755. {
  756. do
  757. {
  758. cFilesWithOid++;
  759. if( droid.GetVolumeId().GetUserBitState() )
  760. cCrossVolumeBitSet++;
  761. } while(oie.FindNext(&objid, &droid));
  762. }
  763. }
  764. printf( "\nObjectID Information\n" );
  765. printf( " Files with ObjectIDs = \t\t%lu\n", cFilesWithOid );
  766. printf( " Files with x-volume bit set = \t%lu\n", cCrossVolumeBitSet );
  767. }
  768. VolumeStatistics( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten )
  769. {
  770. NTSTATUS status = 0;
  771. TCHAR tszFile[ MAX_PATH + 1 ];
  772. TCHAR tszDir[ MAX_PATH + 1 ];
  773. TCHAR* ptcTmp = NULL;
  774. BOOL fSuccess = FALSE;
  775. LONG iVol = 0;
  776. *pcEaten = 0;
  777. if( 1 > cArgs || IsHelpArgument(rgptszArgs[0]) )
  778. {
  779. printf( "\nOption VolStat\n"
  780. " Purpose: Get link tracking info about a volume\n"
  781. " Usage: -volstat <drive letter>\n"
  782. " E.g.: -volstat D:\n" );
  783. *pcEaten = 1;
  784. return( TRUE );
  785. }
  786. if( TEXT('a') > rgptszArgs[0][0]
  787. &&
  788. TEXT('z') < rgptszArgs[0][0]
  789. &&
  790. TEXT('A') > rgptszArgs[0][0]
  791. &&
  792. TEXT('Z') < rgptszArgs[0][0]
  793. ||
  794. TEXT(':') != rgptszArgs[0][1] )
  795. {
  796. printf( "Parameter error. Use -? for usage info\n" );
  797. return( FALSE );
  798. }
  799. iVol = (LONG)((ULONG_PTR)CharLower((LPTSTR)rgptszArgs[0][0]) - TEXT('a'));
  800. if( !IsLocalObjectVolume( iVol ))
  801. {
  802. _tprintf( TEXT("%c: isn't a local NTFS5 volume\n"), VolChar(iVol) );
  803. goto Exit;
  804. }
  805. __try
  806. {
  807. CVolumeId volid;
  808. EnablePrivilege( SE_RESTORE_NAME );
  809. volid = DisplayLogStatus(iVol);
  810. DisplayDcStatus( volid );
  811. DisplayOidInformation( iVol );
  812. fSuccess = TRUE;
  813. }
  814. __except( EXCEPTION_EXECUTE_HANDLER )
  815. {
  816. printf( "Fatal error: %08x\n", GetExceptionCode() );
  817. }
  818. Exit:
  819. return( fSuccess );
  820. } // main()
  821. VolumeIdSetOrGet( ULONG cArgs, TCHAR * const rgptszArgs[], ULONG *pcEaten )
  822. {
  823. HRESULT hr = E_FAIL;
  824. NTSTATUS status = STATUS_SUCCESS;
  825. TCHAR tszFile[ MAX_PATH + 1 ];
  826. WCHAR wszFile[ MAX_PATH + 1 ];
  827. TCHAR tszUNCPath[ MAX_PATH + 1 ];
  828. WCHAR wszOID[ CCH_GUID_STRING + 1 ];
  829. ULONG cbInBuffer;
  830. TCHAR tszMachineName[ MAX_PATH + 1 ];
  831. LPCTSTR tszVolumePath = NULL;
  832. USHORT iVolume;
  833. OLECHAR oszOID[ CCH_GUID_STRING + 1 ];
  834. if( 1 == cArgs && IsHelpArgument( rgptszArgs[0] ))
  835. {
  836. printf( "\nOption VolId\n"
  837. " Purpose: Set or get volume IDs\n"
  838. " Usage: -volid [-s <drive>: {GUID} | -g <drive>:]\n"
  839. " Where: '-s' means Set, and '-g' means Get\n"
  840. " E.g.: -volid -g d:\n"
  841. " -volid -s d: {d2a2ac27-b89a-11d2-9335-00805ffe11b8}\n" );
  842. // The volid in this example is actually the well-known invalid volid
  843. *pcEaten = 1;
  844. return( TRUE );
  845. }
  846. else
  847. if( 2 > cArgs
  848. ||
  849. TEXT('-') != rgptszArgs[0][0]
  850. &&
  851. TEXT('/') != rgptszArgs[0][0]
  852. ||
  853. TEXT(':') != rgptszArgs[1][1] )
  854. {
  855. printf( "Invalid parameter. Use -? for help\n" );
  856. *pcEaten = 0;
  857. return( FALSE );
  858. }
  859. *pcEaten = 2;
  860. __try
  861. {
  862. CVolumeId volid;
  863. TCHAR tcCommand = (TCHAR)CharUpper( (LPTSTR) rgptszArgs[0][1] );
  864. TCHAR tcDrive = (TCHAR)CharUpper( (LPTSTR) rgptszArgs[1][0] );
  865. LONG iVol = tcDrive - TEXT('A');
  866. if( TEXT('G') == tcCommand )
  867. {
  868. OLECHAR *poszVolId;
  869. status = QueryVolumeId( iVol, &volid );
  870. if( FAILED(status) )
  871. {
  872. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't query for volume id") ));
  873. TrkRaiseNtStatus(status);
  874. }
  875. hr = StringFromCLSID( *(GUID*)&volid, &poszVolId );
  876. if( FAILED(hr) )
  877. {
  878. TrkLog(( TRKDBG_ERROR, TEXT("Failed StringFromClsid %08x"), hr ));
  879. TrkRaiseException( hr );
  880. }
  881. _tprintf( TEXT("VolID = %s\n"), poszVolId );
  882. CoTaskMemFree( poszVolId );
  883. }
  884. else if( TEXT('S') == tcCommand && 3 <= cArgs )
  885. {
  886. TSZ2CLSID( rgptszArgs[2], (GUID*)&volid );
  887. EnablePrivilege( SE_RESTORE_NAME );
  888. status = SetVolId( iVol, volid );
  889. if( FAILED(status) )
  890. {
  891. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't set volume id") ));
  892. TrkRaiseNtStatus(status);
  893. }
  894. }
  895. else
  896. {
  897. printf( "Invalid parameter. Use -? for help\n" );
  898. goto Exit;
  899. }
  900. hr = S_OK;
  901. }
  902. __except( BreakOnDebuggableException() )
  903. {
  904. hr = GetExceptionCode();
  905. }
  906. Exit:
  907. if( FAILED(hr) )
  908. printf( "Failed: hr = %08x\n", hr );
  909. return( SUCCEEDED(hr) );
  910. } // main()
  911. BOOL
  912. DltAdminVolInfoFile( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten )
  913. {
  914. NTSTATUS status;
  915. HRESULT hr;
  916. HANDLE hFile = NULL;
  917. IO_STATUS_BLOCK Iosb;
  918. OLECHAR *poszVolId = NULL;
  919. BYTE rgb[ 2 * MAX_PATH ];
  920. PFILE_FS_VOLUME_INFORMATION pfile_fs_volume_information
  921. = reinterpret_cast<PFILE_FS_VOLUME_INFORMATION>(rgb);
  922. PFILE_FS_ATTRIBUTE_INFORMATION pfile_fs_attribute_information
  923. = reinterpret_cast<PFILE_FS_ATTRIBUTE_INFORMATION>(rgb);
  924. PFILE_FS_OBJECTID_INFORMATION pfile_fs_objectid_information
  925. = reinterpret_cast<PFILE_FS_OBJECTID_INFORMATION>(rgb);
  926. FILE_FS_SIZE_INFORMATION file_fs_size_information;
  927. FILE_FS_FULL_SIZE_INFORMATION file_fs_full_size_information;
  928. FILE_FS_DEVICE_INFORMATION file_fs_device_information;
  929. TCHAR tszFileSystemAttributes[ 2 * MAX_PATH ];
  930. DWORD dwFileSystemAttributeMask;
  931. TCHAR *ptszDeviceType = NULL;
  932. if( 0 == cArgs )
  933. {
  934. printf( "Missing parameter: a file/directory name must be specified\n" );
  935. *pcEaten = 0;
  936. return( FALSE );
  937. }
  938. if( IsHelpArgument( rgptszArgs[0] ))
  939. {
  940. printf( "\nOption VolInfoFile\n"
  941. " Purpose: Get volume information, given a file or directory name\n"
  942. " Usage: -volinfofile <file or directory>\n"
  943. " E.g. -volinfofile C:\\foo.doc\n"
  944. " -volinfofile \\\\scratch\\scratch\\jdoe\n" );
  945. *pcEaten = 1;
  946. return( TRUE );
  947. }
  948. __try
  949. {
  950. *pcEaten = 1;
  951. TCHAR tszFileTime[ 80 ];
  952. status = TrkCreateFile(
  953. rgptszArgs[0],
  954. FILE_READ_ATTRIBUTES,
  955. FILE_ATTRIBUTE_NORMAL,
  956. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  957. FILE_OPEN,
  958. FILE_SYNCHRONOUS_IO_NONALERT,
  959. NULL,
  960. &hFile );
  961. if( !NT_SUCCESS(status) )
  962. {
  963. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't open file \"%s\" (%08x)"), rgptszArgs[1], status ));
  964. TrkRaiseNtStatus(status);
  965. }
  966. status = NtQueryVolumeInformationFile( hFile, &Iosb,
  967. pfile_fs_volume_information,
  968. sizeof(rgb),
  969. FileFsVolumeInformation );
  970. if( !NT_SUCCESS(status) )
  971. {
  972. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't query volume information (%08x)"), status ));
  973. TrkRaiseNtStatus(status);
  974. }
  975. pfile_fs_volume_information->VolumeLabel[ pfile_fs_volume_information->VolumeLabelLength/sizeof(WCHAR) ]
  976. = L'\0';
  977. static_cast<CFILETIME>(pfile_fs_volume_information->VolumeCreationTime)
  978. .Stringize( ELEMENTS(tszFileTime), tszFileTime );
  979. _tprintf( TEXT("\n")
  980. TEXT("Volume creation time:\t%08x:%08x (%s)\n")
  981. TEXT("Volume serial number:\t%08x\n")
  982. TEXT("Supports objects:\t%s\n")
  983. TEXT("Volume label:\t\t%s\n"),
  984. pfile_fs_volume_information->VolumeCreationTime.HighPart,
  985. pfile_fs_volume_information->VolumeCreationTime.LowPart,
  986. tszFileTime,
  987. pfile_fs_volume_information->VolumeSerialNumber,
  988. pfile_fs_volume_information->SupportsObjects ? TEXT("True") : TEXT("False"),
  989. pfile_fs_volume_information->VolumeLabel );
  990. status = NtQueryVolumeInformationFile( hFile, &Iosb,
  991. pfile_fs_attribute_information,
  992. sizeof(rgb),
  993. FileFsAttributeInformation );
  994. if( !NT_SUCCESS(status) )
  995. {
  996. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't query attribute information (%08x)"), status ));
  997. TrkRaiseNtStatus(status);
  998. }
  999. pfile_fs_attribute_information->FileSystemName[ pfile_fs_attribute_information->FileSystemNameLength/sizeof(WCHAR) ]
  1000. = L'\0';
  1001. _tcscpy( tszFileSystemAttributes, TEXT("") );
  1002. dwFileSystemAttributeMask = FILE_CASE_SENSITIVE_SEARCH
  1003. | FILE_CASE_PRESERVED_NAMES
  1004. | FILE_UNICODE_ON_DISK
  1005. | FILE_PERSISTENT_ACLS
  1006. | FILE_FILE_COMPRESSION
  1007. | FILE_VOLUME_QUOTAS
  1008. | FILE_SUPPORTS_SPARSE_FILES
  1009. | FILE_SUPPORTS_REPARSE_POINTS
  1010. | FILE_SUPPORTS_REMOTE_STORAGE
  1011. | FILE_VOLUME_IS_COMPRESSED
  1012. | FILE_SUPPORTS_OBJECT_IDS
  1013. | FILE_SUPPORTS_ENCRYPTION;
  1014. if( FILE_CASE_SENSITIVE_SEARCH & pfile_fs_attribute_information->FileSystemAttributes )
  1015. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tCase sensitive search\n"));
  1016. if( FILE_CASE_PRESERVED_NAMES & pfile_fs_attribute_information->FileSystemAttributes )
  1017. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tCase preserved names\n"));
  1018. if( FILE_UNICODE_ON_DISK & pfile_fs_attribute_information->FileSystemAttributes )
  1019. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tUnicode on disk\n"));
  1020. if( FILE_PERSISTENT_ACLS & pfile_fs_attribute_information->FileSystemAttributes )
  1021. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tPersistent ACLs\n"));
  1022. if( FILE_FILE_COMPRESSION & pfile_fs_attribute_information->FileSystemAttributes )
  1023. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tFile compression\n"));
  1024. if( FILE_VOLUME_QUOTAS & pfile_fs_attribute_information->FileSystemAttributes )
  1025. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tVolume quotas\n"));
  1026. if( FILE_SUPPORTS_SPARSE_FILES & pfile_fs_attribute_information->FileSystemAttributes )
  1027. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tSupports sparse files\n"));
  1028. if( FILE_SUPPORTS_REPARSE_POINTS & pfile_fs_attribute_information->FileSystemAttributes )
  1029. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tSupports reparse points\n"));
  1030. if( FILE_SUPPORTS_REMOTE_STORAGE & pfile_fs_attribute_information->FileSystemAttributes )
  1031. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tSupports remote storage\n"));
  1032. if( FILE_VOLUME_IS_COMPRESSED & pfile_fs_attribute_information->FileSystemAttributes )
  1033. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tVolume is compressed\n"));
  1034. if( FILE_SUPPORTS_OBJECT_IDS & pfile_fs_attribute_information->FileSystemAttributes )
  1035. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tSupports object IDs\n"));
  1036. if( FILE_SUPPORTS_ENCRYPTION & pfile_fs_attribute_information->FileSystemAttributes )
  1037. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tSupports encryption\n"));
  1038. if( FILE_NAMED_STREAMS & pfile_fs_attribute_information->FileSystemAttributes )
  1039. _tcscat( tszFileSystemAttributes, TEXT("\t\t\tSupports named streams\n"));
  1040. if( !dwFileSystemAttributeMask & pfile_fs_attribute_information->FileSystemAttributes )
  1041. _tcscat( tszFileSystemAttributes, TEXT("\t\t\t(Unknown bit)"));
  1042. _tprintf( TEXT("File system attributes:\t%08x\n%s")
  1043. TEXT("Max component name:\t%d\n")
  1044. TEXT("File system name\t%s\n"),
  1045. pfile_fs_attribute_information->FileSystemAttributes, tszFileSystemAttributes,
  1046. pfile_fs_attribute_information->MaximumComponentNameLength,
  1047. pfile_fs_attribute_information->FileSystemName );
  1048. status = NtQueryVolumeInformationFile( hFile, &Iosb,
  1049. pfile_fs_objectid_information,
  1050. sizeof(rgb),
  1051. FileFsObjectIdInformation );
  1052. if( NT_SUCCESS(status) )
  1053. {
  1054. hr = StringFromCLSID( *(GUID*)pfile_fs_objectid_information->ObjectId, &poszVolId );
  1055. if( FAILED(hr) )
  1056. {
  1057. TrkLog(( TRKDBG_ERROR, TEXT("Failed StringFromClsid %08x"), hr ));
  1058. TrkRaiseException( hr );
  1059. }
  1060. _tprintf( TEXT("Volume Id:\t\t%s\n"), poszVolId );
  1061. CoTaskMemFree( poszVolId );
  1062. }
  1063. else if( status != STATUS_INVALID_PARAMETER && status != STATUS_OBJECT_NAME_NOT_FOUND )
  1064. {
  1065. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't query objectid information (%08x)"), status ));
  1066. TrkRaiseNtStatus(status);
  1067. }
  1068. status = NtQueryVolumeInformationFile( hFile, &Iosb,
  1069. &file_fs_full_size_information,
  1070. sizeof(file_fs_full_size_information),
  1071. FileFsFullSizeInformation );
  1072. if( !NT_SUCCESS(status) )
  1073. {
  1074. status = NtQueryVolumeInformationFile( hFile, &Iosb,
  1075. &file_fs_size_information,
  1076. sizeof(file_fs_size_information),
  1077. FileFsSizeInformation );
  1078. if( !NT_SUCCESS(status) )
  1079. {
  1080. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't query full size info or size info (%08x)"), status ));
  1081. TrkRaiseNtStatus( status );
  1082. }
  1083. double TotalAllocInMB = file_fs_size_information.TotalAllocationUnits.QuadPart
  1084. *
  1085. file_fs_size_information.SectorsPerAllocationUnit
  1086. *
  1087. file_fs_size_information.BytesPerSector
  1088. /
  1089. 1000000.0;
  1090. _tprintf( TEXT("Total allocation units:\t%I64u (%.2fMB)\n")
  1091. TEXT("Available alloc:\t%I64u units\n")
  1092. TEXT("Sectors per alloc unit:\t%d\n")
  1093. TEXT("Bytes per sector:\t%d\n"),
  1094. file_fs_size_information.TotalAllocationUnits.QuadPart,
  1095. TotalAllocInMB,
  1096. file_fs_size_information.AvailableAllocationUnits.QuadPart,
  1097. file_fs_size_information.SectorsPerAllocationUnit,
  1098. file_fs_size_information.BytesPerSector );
  1099. }
  1100. else
  1101. {
  1102. double TotalAllocInMB = file_fs_full_size_information.TotalAllocationUnits.QuadPart
  1103. *
  1104. file_fs_full_size_information.SectorsPerAllocationUnit
  1105. *
  1106. file_fs_full_size_information.BytesPerSector
  1107. /
  1108. 1000000.0;
  1109. double CallerAvailAllocInMB
  1110. = file_fs_full_size_information.CallerAvailableAllocationUnits.QuadPart
  1111. *
  1112. file_fs_full_size_information.SectorsPerAllocationUnit
  1113. *
  1114. file_fs_full_size_information.BytesPerSector
  1115. /
  1116. 1000000.0;
  1117. double ActualAvailAllocInMB
  1118. = file_fs_full_size_information.ActualAvailableAllocationUnits.QuadPart
  1119. *
  1120. file_fs_full_size_information.SectorsPerAllocationUnit
  1121. *
  1122. file_fs_full_size_information.BytesPerSector
  1123. /
  1124. 1000000.0;
  1125. _tprintf( TEXT("Total allocation units:\t%I64u (%.2fMB)\n")
  1126. TEXT("Caller avail alloc:\t%I64u units (%.2fMB)\n")
  1127. TEXT("Actual avail alloc:\t%I64u units (%.2fMB)\n")
  1128. TEXT("Sectors per alloc unit:\t%d\n")
  1129. TEXT("Bytes per sector:\t%d\n"),
  1130. file_fs_full_size_information.TotalAllocationUnits.QuadPart,
  1131. TotalAllocInMB,
  1132. file_fs_full_size_information.CallerAvailableAllocationUnits.QuadPart,
  1133. CallerAvailAllocInMB,
  1134. file_fs_full_size_information.ActualAvailableAllocationUnits.QuadPart,
  1135. ActualAvailAllocInMB,
  1136. file_fs_full_size_information.SectorsPerAllocationUnit,
  1137. file_fs_full_size_information.BytesPerSector );
  1138. }
  1139. status = NtQueryVolumeInformationFile( hFile, &Iosb,
  1140. &file_fs_device_information,
  1141. sizeof(file_fs_device_information),
  1142. FileFsDeviceInformation );
  1143. if( !NT_SUCCESS(status) )
  1144. {
  1145. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't query file fs device information (%08x)"), status ));
  1146. TrkRaiseNtStatus(status);
  1147. }
  1148. switch( file_fs_device_information.DeviceType )
  1149. {
  1150. case FILE_DEVICE_NETWORK:
  1151. ptszDeviceType = L"Network"; break;
  1152. case FILE_DEVICE_NETWORK_FILE_SYSTEM:
  1153. ptszDeviceType = L"Network file system"; break;
  1154. case FILE_DEVICE_CD_ROM:
  1155. ptszDeviceType = L"CDROM"; break;
  1156. case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
  1157. ptszDeviceType = L"CDROM file system"; break;
  1158. case FILE_DEVICE_VIRTUAL_DISK:
  1159. ptszDeviceType = L"Virtual disk"; break;
  1160. case FILE_DEVICE_DISK:
  1161. ptszDeviceType = file_fs_device_information.Characteristics & FILE_REMOVABLE_MEDIA
  1162. ? L"Removable disk" : L"Fixed disk";
  1163. break;
  1164. case FILE_DEVICE_DISK_FILE_SYSTEM:
  1165. ptszDeviceType = file_fs_device_information.Characteristics & FILE_REMOVABLE_MEDIA
  1166. ? L"Removable disk file system" : L"Fixed disk file system";
  1167. break;
  1168. default:
  1169. ptszDeviceType = L"Unknown";
  1170. }
  1171. _tprintf( TEXT("Device Type:\t\t%s%s\n"),
  1172. ptszDeviceType,
  1173. (file_fs_device_information.Characteristics & FILE_REMOTE_DEVICE)
  1174. ? TEXT(" (remote)")
  1175. : TEXT("")
  1176. );
  1177. hr = S_OK;
  1178. }
  1179. __except( EXCEPTION_EXECUTE_HANDLER )
  1180. {
  1181. hr = GetExceptionCode();
  1182. }
  1183. if( NULL != hFile )
  1184. NtClose( hFile );
  1185. if( FAILED(hr) )
  1186. printf( "Failed: hr = %08x\n", hr );
  1187. return SUCCEEDED(hr);
  1188. }
  1189. BOOL
  1190. DeleteIdFromVolumeTable( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten )
  1191. {
  1192. CVolumeId volid;
  1193. CStringize stringize;
  1194. CRpcClientBinding rc;
  1195. TRKSVR_SYNC_VOLUME SyncVolume;
  1196. TRKSVR_MESSAGE_UNION Msg;
  1197. CMachineId mcidLocal( MCID_LOCAL );
  1198. HRESULT hr = S_OK;
  1199. if( 0 == cArgs )
  1200. {
  1201. printf( "Missing parameter: a volume ID name must be specified\n"
  1202. "(in \"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" form)\n" );
  1203. *pcEaten = 0;
  1204. return( FALSE );
  1205. }
  1206. _tprintf( TEXT("Deleting volume %s from DC volume table\n"), rgptszArgs[0] );
  1207. if( IsHelpArgument( rgptszArgs[0] ))
  1208. {
  1209. printf( "\nOption DelDcVolId\n"
  1210. " Purpose: Delete a volume ID from the DC volume table\n"
  1211. " Usage: -deldcvolid <stringized volume ID>\n"
  1212. " E.g. -deldcvolid {56730825-3ddc-11d2-a168-00805ffe11b8}\n"
  1213. " Note: The volume ID must be owned by this machine.\n"
  1214. " Also, the services\\trkwks\\parameters\\configuration\\trkflags\n"
  1215. " reg value must have the 0x1 bit set.\n" );
  1216. *pcEaten = 1;
  1217. return( TRUE );
  1218. }
  1219. *pcEaten = 1;
  1220. // Convert the volid string to a volid
  1221. stringize.Use( rgptszArgs[0] );
  1222. volid = stringize;
  1223. if( CVolumeId() == volid )
  1224. {
  1225. _tprintf( TEXT("Error: Invalid volume ID\n") );
  1226. return( FALSE );
  1227. }
  1228. // Send the delete request
  1229. rc.RcInitialize( mcidLocal, s_tszTrkWksLocalRpcProtocol, s_tszTrkWksLocalRpcEndPoint, NO_AUTHENTICATION );
  1230. __try
  1231. {
  1232. Msg.MessageType = SYNC_VOLUMES;
  1233. Msg.ptszMachineID = NULL;
  1234. Msg.Priority = PRI_9;
  1235. Msg.SyncVolumes.cVolumes = 1;
  1236. Msg.SyncVolumes.pVolumes = &SyncVolume;
  1237. SyncVolume.hr = S_OK;
  1238. SyncVolume.SyncType = DELETE_VOLUME;
  1239. SyncVolume.volume = volid;
  1240. hr = LnkCallSvrMessage( rc, &Msg );
  1241. }
  1242. __except( EXCEPTION_EXECUTE_HANDLER )
  1243. {
  1244. hr = HRESULT_FROM_WIN32(GetLastError());
  1245. }
  1246. if( SUCCEEDED(hr) )
  1247. hr = SyncVolume.hr;
  1248. if( FAILED(hr) )
  1249. _tprintf( TEXT("Error: %08x\n"), hr );
  1250. else if( S_OK != hr )
  1251. _tprintf( TEXT("Success code: %08x\n"), hr );
  1252. if( FAILED(hr) )
  1253. printf( "Failed: hr = %08x\n", hr );
  1254. return( SUCCEEDED(hr) );
  1255. }
  1256. BOOL
  1257. DeleteIdFromMoveTable( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten )
  1258. {
  1259. CDomainRelativeObjId droid;
  1260. CStringize stringize;
  1261. CRpcClientBinding rc;
  1262. TRKSVR_MESSAGE_UNION Msg;
  1263. CMachineId mcidLocal( MCID_LOCAL );
  1264. HRESULT hr = S_OK;
  1265. if( 0 == cArgs )
  1266. {
  1267. printf( "Missing parameter: a birth ID name must be specified\n"
  1268. "(in \"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" form)\n" );
  1269. *pcEaten = 0;
  1270. return( FALSE );
  1271. }
  1272. _tprintf( TEXT("Deleting file %s from DC move table\n"), rgptszArgs[0] );
  1273. if( IsHelpArgument( rgptszArgs[0] ))
  1274. {
  1275. printf( "\nOption DelDcMoveId\n"
  1276. " Purpose: Delete an entry from the DC move table\n"
  1277. " Usage: -deldcmoveid <stringized GUIDs of birth ID>\n"
  1278. " E.g. -deldcmoveid {xxx...xxx}{xxx...xxx}\n"
  1279. " Where: a stringized GUID is e.g. \"{56730825-3ddc-11d2-a168-00805ffe11b8}\"\n"
  1280. " Note: The birth ID must be owned by this machine.\n"
  1281. " Also, the services\\trkwks\\parameters\\configuration\\trkflags\n"
  1282. " reg value must have the 0x1 bit set.\n" );
  1283. *pcEaten = 1;
  1284. return( TRUE );
  1285. }
  1286. *pcEaten = 1;
  1287. stringize.Use( rgptszArgs[0] );
  1288. droid = stringize;
  1289. if( CDomainRelativeObjId() == droid )
  1290. {
  1291. _tprintf( TEXT("Error: Invalid birth ID\n") );
  1292. return( FALSE );
  1293. }
  1294. rc.RcInitialize( mcidLocal, s_tszTrkWksLocalRpcProtocol, s_tszTrkWksLocalRpcEndPoint, NO_AUTHENTICATION );
  1295. __try
  1296. {
  1297. CVolumeId volidDummy;
  1298. Msg.MessageType = DELETE_NOTIFY;
  1299. Msg.ptszMachineID = NULL;
  1300. Msg.Priority = PRI_5;
  1301. Msg.Delete.cVolumes = 0;
  1302. Msg.Delete.pVolumes = &volidDummy;
  1303. Msg.Delete.adroidBirth = &droid;
  1304. Msg.Delete.cdroidBirth = 1;
  1305. LnkCallSvrMessage(rc, &Msg);
  1306. }
  1307. __except( EXCEPTION_EXECUTE_HANDLER )
  1308. {
  1309. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  1310. }
  1311. if( FAILED(hr) )
  1312. _tprintf( TEXT("Error: %08x\n"), hr );
  1313. else if( S_OK != hr )
  1314. _tprintf( TEXT("Success code: %x\n"), hr );
  1315. return( SUCCEEDED(hr) );
  1316. }
  1317. BOOL
  1318. DltAdminLookupVolId( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten )
  1319. {
  1320. CVolumeId volid;
  1321. CStringize stringize;
  1322. CRpcClientBinding rc;
  1323. TRKSVR_SYNC_VOLUME SyncVolume;
  1324. TRKSVR_MESSAGE_UNION Msg;
  1325. CMachineId mcidLocal( MCID_LOCAL );
  1326. HRESULT hr = S_OK;
  1327. if( 0 == cArgs )
  1328. {
  1329. printf( "Missing parameter: a volume ID name must be specified\n"
  1330. "(in \"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" form)\n" );
  1331. *pcEaten = 0;
  1332. return( FALSE );
  1333. }
  1334. _tprintf( TEXT("Searching for volume %s in DC volume table\n"), rgptszArgs[0] );
  1335. if( IsHelpArgument( rgptszArgs[0] ))
  1336. {
  1337. printf( "\nOption LookupVolId\n"
  1338. " Purpose: Look up a volume ID from the DC volume table\n"
  1339. " Usage: -lookupvolid <stringized volume ID>\n"
  1340. " E.g. -lookupvolid {56730825-3ddc-11d2-a168-00805ffe11b8}\n"
  1341. " Note: The services\\trkwks\\parameters\\configuration\\trkflags\n"
  1342. " reg value must have the 0x1 bit set before trkwks is started.\n" );
  1343. *pcEaten = 1;
  1344. return( TRUE );
  1345. }
  1346. *pcEaten = 1;
  1347. // Convert the volid string to a volid
  1348. stringize.Use( rgptszArgs[0] );
  1349. volid = stringize;
  1350. if( CVolumeId() == volid )
  1351. {
  1352. _tprintf( TEXT("Error: Invalid volume ID\n") );
  1353. return( FALSE );
  1354. }
  1355. // Send the delete request
  1356. rc.RcInitialize( mcidLocal, s_tszTrkWksLocalRpcProtocol, s_tszTrkWksLocalRpcEndPoint, NO_AUTHENTICATION );
  1357. __try
  1358. {
  1359. Msg.MessageType = SYNC_VOLUMES;
  1360. Msg.ptszMachineID = NULL;
  1361. Msg.Priority = PRI_9;
  1362. Msg.SyncVolumes.cVolumes = 1;
  1363. Msg.SyncVolumes.pVolumes = &SyncVolume;
  1364. SyncVolume.hr = S_OK;
  1365. SyncVolume.SyncType = FIND_VOLUME;
  1366. SyncVolume.volume = volid;
  1367. hr = LnkCallSvrMessage( rc, &Msg );
  1368. }
  1369. __except( EXCEPTION_EXECUTE_HANDLER )
  1370. {
  1371. hr = HRESULT_FROM_WIN32(GetLastError());
  1372. }
  1373. if( SUCCEEDED(hr) )
  1374. hr = SyncVolume.hr;
  1375. if( FAILED(hr) )
  1376. _tprintf( TEXT("Error: %08x\n"), hr );
  1377. else
  1378. {
  1379. if( S_OK != hr )
  1380. _tprintf( TEXT("Success code is %08x\n"), hr );
  1381. _tprintf( TEXT("Machine = \"%s\"\n"), static_cast<const TCHAR*>(CStringize(SyncVolume.machine)) );
  1382. }
  1383. if( FAILED(hr) )
  1384. printf( "Failed: hr = %08x\n", hr );
  1385. return( SUCCEEDED(hr) );
  1386. }
  1387. BOOL
  1388. DltAdminLookupDroid( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten )
  1389. {
  1390. CVolumeId volid;
  1391. CStringize stringize;
  1392. CRpcClientBinding rc;
  1393. TRK_FILE_TRACKING_INFORMATION FileTrackingInformation;
  1394. TRKSVR_MESSAGE_UNION Msg;
  1395. CDomainRelativeObjId droid;
  1396. CMachineId mcidLocal( MCID_LOCAL );
  1397. HRESULT hr = S_OK;
  1398. if( 0 == cArgs )
  1399. {
  1400. printf( "Missing parameter: a DROID must be specified\n"
  1401. "(in \"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" form)\n" );
  1402. *pcEaten = 0;
  1403. return( FALSE );
  1404. }
  1405. _tprintf( TEXT("Searching for move ID %s in DC volume table\n"), rgptszArgs[0] );
  1406. if( IsHelpArgument( rgptszArgs[0] ))
  1407. {
  1408. printf( "\nOption LookupDroid\n"
  1409. " Purpose: Look up a DROID from the DC move table\n"
  1410. " Usage: -lookupdroid <stringized DROIID>\n"
  1411. " E.g. -lookupdroid {f8b534f0-b65b-11d2-8fd8-0008c709d19e}{0ed45deb-03ed-11d3-b766-00805ffe11b8}\n"
  1412. " Note: You must be running as an administrator\n" );
  1413. *pcEaten = 1;
  1414. return( TRUE );
  1415. }
  1416. *pcEaten = 1;
  1417. stringize.Use( rgptszArgs[0] );
  1418. droid = stringize;
  1419. if( CDomainRelativeObjId() == droid )
  1420. {
  1421. _tprintf( TEXT("Error: Invalid birth ID\n") );
  1422. return( FALSE );
  1423. }
  1424. rc.RcInitialize( mcidLocal, s_tszTrkWksLocalRpcProtocol, s_tszTrkWksLocalRpcEndPoint, NO_AUTHENTICATION );
  1425. __try
  1426. {
  1427. memset( &FileTrackingInformation, 0, sizeof(FileTrackingInformation) );
  1428. FileTrackingInformation.droidLast = droid;
  1429. Msg.MessageType = SEARCH;
  1430. Msg.ptszMachineID = NULL;
  1431. Msg.Priority = PRI_5;
  1432. Msg.Search.cSearch = 1;
  1433. Msg.Search.pSearches = &FileTrackingInformation;
  1434. LnkCallSvrMessage(rc, &Msg);
  1435. }
  1436. __except( EXCEPTION_EXECUTE_HANDLER )
  1437. {
  1438. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  1439. }
  1440. if( SUCCEEDED(hr) )
  1441. hr = FileTrackingInformation.hr;
  1442. if( FAILED(hr) )
  1443. _tprintf( TEXT("Error: %08x\n"), hr );
  1444. else
  1445. {
  1446. if( S_OK != hr )
  1447. _tprintf( TEXT("Success code is %08x\n"), hr );
  1448. _tprintf( TEXT("Machine = \"%s\"\n"), static_cast<const TCHAR*>(CStringize(FileTrackingInformation.mcidLast)) );
  1449. }
  1450. return( TRUE );
  1451. }
  1452. EXTERN_C void __cdecl _tmain( int cArgs, TCHAR *prgtszArg[])
  1453. {
  1454. HRESULT hr = S_OK;
  1455. NTSTATUS status = STATUS_SUCCESS;
  1456. int iArg = 0;
  1457. int iError = 0;
  1458. OLECHAR oszOID[ CCH_GUID_STRING + 1 ];
  1459. TrkDebugCreate( TRK_DBG_FLAGS_WRITE_TO_DBG, "DltAdmin" );
  1460. hr = CoInitialize( NULL );
  1461. if (FAILED(hr))
  1462. {
  1463. _tprintf( TEXT("Unable to CoInitialize( NULL )-- aborting. (0x%08x)\n"),
  1464. hr );
  1465. return;
  1466. }
  1467. TCHAR tszStringizedTime[ 80 ];
  1468. __try
  1469. {
  1470. // Skip over the executable name
  1471. iArg++;
  1472. cArgs--;
  1473. if( 0 == cArgs )
  1474. {
  1475. Usage();
  1476. exit(1);
  1477. }
  1478. for( ; iArg <= cArgs; cArgs--, iArg++ )
  1479. {
  1480. ULONG cEaten = 0;
  1481. if( TEXT('-') != prgtszArg[iArg][0]
  1482. &&
  1483. TEXT('/') != prgtszArg[iArg][0] )
  1484. {
  1485. _tprintf( TEXT("Invalid option, ignoring: %s\n"), prgtszArg[iArg] );
  1486. iError = max( iError, 1 );
  1487. continue;
  1488. }
  1489. if( !_tcsicmp( TEXT("deldcvolid"), &prgtszArg[iArg][1] ) )
  1490. {
  1491. iArg++;
  1492. cArgs--;
  1493. if( !DeleteIdFromVolumeTable( cArgs, &prgtszArg[iArg], &cEaten ))
  1494. iError = max( iError, 2 );
  1495. iArg += cEaten;
  1496. cArgs -= cEaten;
  1497. }
  1498. else if( !_tcsicmp( TEXT("deldcmoveid"), &prgtszArg[iArg][1] ))
  1499. {
  1500. iArg++;
  1501. cArgs--;
  1502. if( !DeleteIdFromMoveTable( cArgs, &prgtszArg[iArg], &cEaten ))
  1503. iError = max( iError, 2 );
  1504. iArg += cEaten;
  1505. cArgs -= cEaten;
  1506. }
  1507. else if( !_tcsicmp( TEXT("lookupvolid"), &prgtszArg[iArg][1] ))
  1508. {
  1509. iArg++;
  1510. cArgs--;
  1511. if( !DltAdminLookupVolId( cArgs, &prgtszArg[iArg], &cEaten ))
  1512. iError = max( iError, 2 );
  1513. iArg += cEaten;
  1514. cArgs -= cEaten;
  1515. }
  1516. else if( !_tcsicmp( TEXT("lookupdroid"), &prgtszArg[iArg][1] ))
  1517. {
  1518. iArg++;
  1519. cArgs--;
  1520. if( !DltAdminLookupDroid( cArgs, &prgtszArg[iArg], &cEaten ))
  1521. iError = max( iError, 2 );
  1522. iArg += cEaten;
  1523. cArgs -= cEaten;
  1524. }
  1525. else if( !_tcsicmp( TEXT("volinfofile"), &prgtszArg[iArg][1] ))
  1526. {
  1527. iArg++;
  1528. cArgs--;
  1529. if( !DltAdminVolInfoFile( cArgs, &prgtszArg[iArg], &cEaten ))
  1530. iError = max( iError, 2 );
  1531. iArg += cEaten;
  1532. cArgs -= cEaten;
  1533. }
  1534. else if( !_tcsicmp( TEXT("cleanvol"), &prgtszArg[iArg][1] ))
  1535. {
  1536. iArg++;
  1537. cArgs--;
  1538. if( !DltAdminCleanVol( cArgs, &prgtszArg[iArg], &cEaten ))
  1539. iError = max( iError, 2 );
  1540. iArg += cEaten;
  1541. cArgs -= cEaten;
  1542. }
  1543. else if( !_tcsicmp( TEXT("svrstat"), &prgtszArg[iArg][1] ))
  1544. {
  1545. iArg++;
  1546. cArgs--;
  1547. if( !DltAdminSvrStat( cArgs, &prgtszArg[iArg], &cEaten ))
  1548. iError = max( iError, 2 );
  1549. iArg += cEaten;
  1550. cArgs -= cEaten;
  1551. }
  1552. else if( !_tcsicmp( TEXT("volstat"), &prgtszArg[iArg][1] ))
  1553. {
  1554. iArg++;
  1555. cArgs--;
  1556. if( !VolumeStatistics( cArgs, &prgtszArg[iArg], &cEaten ))
  1557. iError = max( iError, 2 );
  1558. iArg += cEaten;
  1559. cArgs -= cEaten;
  1560. }
  1561. else if( !_tcsicmp( TEXT("volid"), &prgtszArg[iArg][1] ))
  1562. {
  1563. iArg++;
  1564. cArgs--;
  1565. if( !VolumeIdSetOrGet( cArgs, &prgtszArg[iArg], &cEaten ))
  1566. iError = max( iError, 2 );
  1567. iArg += cEaten;
  1568. cArgs -= cEaten;
  1569. }
  1570. else if( !_tcsicmp( TEXT("lockvol"), &prgtszArg[iArg][1] ))
  1571. {
  1572. iArg++;
  1573. cArgs--;
  1574. if( !DltAdminLockVol( cArgs, &prgtszArg[iArg], &cEaten ))
  1575. iError = max( iError, 2 );
  1576. iArg += cEaten;
  1577. cArgs -= cEaten;
  1578. }
  1579. else if( !_tcsicmp( TEXT("fileoid"), &prgtszArg[iArg][1] ))
  1580. {
  1581. iArg++;
  1582. cArgs--;
  1583. if( !DltAdminFileOid( cArgs, &prgtszArg[iArg], &cEaten ))
  1584. iError = max( iError, 2 );
  1585. iArg += cEaten;
  1586. cArgs -= cEaten;
  1587. }
  1588. else if( !_tcsicmp( TEXT("enumoids"), &prgtszArg[iArg][1] ))
  1589. {
  1590. iArg++;
  1591. cArgs--;
  1592. if( !DltAdminEnumOids( cArgs, &prgtszArg[iArg], &cEaten ))
  1593. iError = max( iError, 2 );
  1594. iArg += cEaten;
  1595. cArgs -= cEaten;
  1596. }
  1597. else if( !_tcsicmp( TEXT("oidsnap"), &prgtszArg[iArg][1] ))
  1598. {
  1599. iArg++;
  1600. cArgs--;
  1601. if( !DltAdminOidSnap( cArgs, &prgtszArg[iArg], &cEaten ))
  1602. iError = max( iError, 2 );
  1603. iArg += cEaten;
  1604. cArgs -= cEaten;
  1605. }
  1606. else if( !_tcsicmp( TEXT("link"), &prgtszArg[iArg][1] ))
  1607. {
  1608. iArg++;
  1609. cArgs--;
  1610. if( !DltAdminLink( cArgs, &prgtszArg[iArg], &cEaten ))
  1611. iError = max( iError, 2 );
  1612. iArg += cEaten;
  1613. cArgs -= cEaten;
  1614. }
  1615. else if( !_tcsicmp( TEXT("loadlib"), &prgtszArg[iArg][1] ))
  1616. {
  1617. iArg++;
  1618. cArgs--;
  1619. if( !DltAdminProcessAction( LOAD_LIBRARY, cArgs, &prgtszArg[iArg], &cEaten ))
  1620. iError = max( iError, 2 );
  1621. iArg += cEaten;
  1622. cArgs -= cEaten;
  1623. }
  1624. else if( !_tcsicmp( TEXT("freelib"), &prgtszArg[iArg][1] ))
  1625. {
  1626. iArg++;
  1627. cArgs--;
  1628. if( !DltAdminProcessAction( FREE_LIBRARY, cArgs, &prgtszArg[iArg], &cEaten ))
  1629. iError = max( iError, 2 );
  1630. iArg += cEaten;
  1631. cArgs -= cEaten;
  1632. }
  1633. else if( !_tcsicmp( TEXT("debugbreak"), &prgtszArg[iArg][1] ))
  1634. {
  1635. iArg++;
  1636. cArgs--;
  1637. if( !DltAdminProcessAction( DEBUG_BREAK, cArgs, &prgtszArg[iArg], &cEaten ))
  1638. iError = max( iError, 2 );
  1639. iArg += cEaten;
  1640. cArgs -= cEaten;
  1641. }
  1642. else if( !_tcsicmp( TEXT("createprocess"), &prgtszArg[iArg][1] ))
  1643. {
  1644. iArg++;
  1645. cArgs--;
  1646. if( !DltAdminProcessAction( CREATE_PROCESS, cArgs, &prgtszArg[iArg], &cEaten ))
  1647. iError = max( iError, 2 );
  1648. iArg += cEaten;
  1649. cArgs -= cEaten;
  1650. }
  1651. else if( !_tcsicmp( TEXT("config"), &prgtszArg[iArg][1] ))
  1652. {
  1653. iArg++;
  1654. cArgs--;
  1655. if( !DltAdminConfig( cArgs, &prgtszArg[iArg], &cEaten ))
  1656. iError = max( iError, 2 );
  1657. iArg += cEaten;
  1658. cArgs -= cEaten;
  1659. }
  1660. else if( !_tcsicmp( TEXT("refresh"), &prgtszArg[iArg][1] ))
  1661. {
  1662. iArg++;
  1663. cArgs--;
  1664. if( !DltAdminRefresh( cArgs, &prgtszArg[iArg], &cEaten ))
  1665. iError = max( iError, 2 );
  1666. iArg += cEaten;
  1667. cArgs -= cEaten;
  1668. }
  1669. else if( !_tcsicmp( TEXT("setvolseq"), &prgtszArg[iArg][1] ))
  1670. {
  1671. iArg++;
  1672. cArgs--;
  1673. if( !DltAdminSetVolumeSeqNumber( cArgs, &prgtszArg[iArg], &cEaten ))
  1674. iError = max( iError, 2 );
  1675. iArg += cEaten;
  1676. cArgs -= cEaten;
  1677. }
  1678. else if( !_tcsicmp( TEXT("setdroidseq"), &prgtszArg[iArg][1] ))
  1679. {
  1680. iArg++;
  1681. cArgs--;
  1682. if( !DltAdminSetDroidSeqNumber( cArgs, &prgtszArg[iArg], &cEaten ))
  1683. iError = max( iError, 2 );
  1684. iArg += cEaten;
  1685. cArgs -= cEaten;
  1686. }
  1687. else if( !_tcsicmp( TEXT("backupread"), &prgtszArg[iArg][1] ))
  1688. {
  1689. iArg++;
  1690. cArgs--;
  1691. if( !DltAdminBackupRead( cArgs, &prgtszArg[iArg], &cEaten ))
  1692. iError = max( iError, 2 );
  1693. iArg += cEaten;
  1694. cArgs -= cEaten;
  1695. }
  1696. else if( !_tcsicmp( TEXT("backupwrite"), &prgtszArg[iArg][1] ))
  1697. {
  1698. iArg++;
  1699. cArgs--;
  1700. if( !DltAdminBackupWrite( cArgs, &prgtszArg[iArg], &cEaten ))
  1701. iError = max( iError, 2 );
  1702. iArg += cEaten;
  1703. cArgs -= cEaten;
  1704. }
  1705. else if( !_tcsicmp( TEXT("sleep"), &prgtszArg[iArg][1] ))
  1706. {
  1707. iArg++;
  1708. cArgs--;
  1709. Sleep( 1000 );
  1710. }
  1711. else if( !_tcsicmp( TEXT("temp"), &prgtszArg[iArg][1] ))
  1712. {
  1713. if( !DltAdminTemp( cArgs, &prgtszArg[iArg], &cEaten ))
  1714. iError = max( iError, 2 );
  1715. iArg += cEaten;
  1716. cArgs -= cEaten;
  1717. }
  1718. else if( TEXT('?') == prgtszArg[iArg][1] )
  1719. {
  1720. Usage();
  1721. exit( 1 );
  1722. }
  1723. else
  1724. {
  1725. _tprintf( TEXT("Invalid option, ignoring: %s\n"), prgtszArg[iArg] );
  1726. iError = max( iError, 1 );
  1727. continue;
  1728. }
  1729. }
  1730. }
  1731. __except( BreakOnDebuggableException() )
  1732. {
  1733. hr = GetExceptionCode();
  1734. iError = max( iError, 2 );
  1735. }
  1736. if( FAILED(hr) )
  1737. printf( "HR = %08X\n", hr );
  1738. CoUninitialize();
  1739. // return( iError );
  1740. } // main()