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.

665 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. // File: tlink.cxx
  7. //
  8. // Contents: Utility to create/mend links and move files with notify
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. //
  15. //
  16. // History: 18-Nov-96 BillMo Created.
  17. //
  18. // Notes:
  19. //
  20. // Codework:
  21. //
  22. //--------------------------------------------------------------------------
  23. #include <pch.cxx>
  24. #pragma hdrstop
  25. #define TRKDATA_ALLOCATE // This is the main module, trigger trkwks.hxx to do definitions
  26. #include <trkwks.hxx>
  27. #include <cfiletim.hxx>
  28. #include <ocidl.h>
  29. #include <shlobj.h>
  30. #include <shlguid.h>
  31. DWORD g_Debug = TRKDBG_ERROR;
  32. #define CB_LINK_CLIENT_MAX 256
  33. // Implicitely load shell32.dll, rather than waiting for the CoCreate of IShellLink,
  34. // in order to make it easier to debug in windbg.
  35. #pragma comment( lib, "shell32.lib" )
  36. enum EXTRAFLAGS
  37. {
  38. EXTRAFLAG_SHOW_IDS = 1
  39. };
  40. extern "C"
  41. IID IID_ISLTracker
  42. #ifdef TRKDATA_ALLOCATE
  43. = { /* 7c9e512f-41d7-11d1-8e2e-00c04fb9386d */
  44. 0x7c9e512f,
  45. 0x41d7,
  46. 0x11d1,
  47. {0x8e, 0x2e, 0x00, 0xc0, 0x4f, 0xb9, 0x38, 0x6d}
  48. };
  49. #else
  50. ;
  51. #endif
  52. class ISLTracker : public IUnknown
  53. {
  54. public:
  55. STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppvObj) PURE;
  56. STDMETHOD_(ULONG,AddRef) () PURE;
  57. STDMETHOD_(ULONG,Release) () PURE;
  58. STDMETHOD(Resolve)(HWND hwnd, DWORD fFlags, DWORD TrackerRestrictions) PURE;
  59. STDMETHOD(GetIDs)(CDomainRelativeObjId *pdroidBirth, CDomainRelativeObjId *pdroidLast, CMachineId *pmcid) PURE;
  60. }; // interface ISLTracker
  61. void
  62. EnumObjects()
  63. {
  64. CObjIdEnumerator oie;
  65. __try
  66. {
  67. CObjId aobjid[1000];
  68. CDomainRelativeObjId adroid[1000];
  69. int cSources=0;
  70. const int FirstDrive = 'c';
  71. const int LastDrive = 'z';
  72. for (int Drive = FirstDrive-'a';
  73. Drive < LastDrive-'a'+1;
  74. Drive ++)
  75. {
  76. // fill up the array with ids from all the drives
  77. if (oie.Initialize(CVolumeDeviceName(Drive)))
  78. {
  79. if (oie.FindFirst(aobjid, adroid))
  80. {
  81. BOOL fGotOne = FALSE;
  82. do
  83. {
  84. do
  85. {
  86. CDomainRelativeObjId droidBirth;
  87. TCHAR tszObjId[256];
  88. TCHAR tszBirthLink[256];
  89. TCHAR tszPath[MAX_PATH+1];
  90. TCHAR * ptszObjId = tszObjId;
  91. StringizeGuid(*(GUID*)&aobjid[cSources], ptszObjId);
  92. FindLocalPath( Drive, aobjid[cSources], &droidBirth, &tszPath[2]);
  93. tszPath[0] = VolChar(Drive);
  94. tszPath[1] = TEXT(':');
  95. _tprintf(TEXT("%s %s %s\n"),
  96. tszObjId,
  97. adroid[cSources].Stringize(tszBirthLink,256),
  98. tszPath);
  99. cSources ++;
  100. } while (cSources < sizeof(aobjid)/sizeof(aobjid[0]) &&
  101. (fGotOne = oie.FindNext(&aobjid[ cSources ], &adroid[ cSources ])));
  102. TrkAssert(cSources > 0);
  103. cSources = 0;
  104. } while (fGotOne);
  105. }
  106. }
  107. }
  108. }
  109. __except(BreakOnDebuggableException())
  110. {
  111. }
  112. oie.UnInitialize();
  113. }
  114. void
  115. AttackDC()
  116. {
  117. CMachineId mcidDomain(MCID_DOMAIN);
  118. CRpcClientBinding rcConnect;
  119. rcConnect.RcInitialize(mcidDomain, s_tszTrkSvrRpcProtocol, s_tszTrkSvrRpcEndPoint);
  120. TRKSVR_MESSAGE_UNION m;
  121. CObjId objidCurrent;
  122. CDomainRelativeObjId droidBirth, droidNew;
  123. CVolumeId volid;
  124. m.MessageType = MOVE_NOTIFICATION;
  125. m.Priority = PRI_0;
  126. m.MoveNotification.cNotifications = 0;
  127. m.MoveNotification.pvolid = &volid;
  128. m.MoveNotification.rgobjidCurrent = &objidCurrent;
  129. m.MoveNotification.rgdroidBirth = &droidBirth;
  130. m.MoveNotification.rgdroidNew = &droidNew;
  131. while (1)
  132. {
  133. LnkSvrMessage( rcConnect, &m);
  134. }
  135. rcConnect.UnInitialize();
  136. }
  137. void
  138. DoCreateLink(IShellLink * pshlink, const TCHAR *ptszLink, const TCHAR *ptszSrc)
  139. {
  140. HRESULT hr;
  141. IPersistFile *pPersistFile = NULL;
  142. __try
  143. {
  144. DWORD dwWritten;
  145. BYTE rgb[ CB_LINK_CLIENT_MAX ];
  146. ULONG cbPersist = 0;
  147. memset( rgb, 0, sizeof(rgb) );
  148. hr = pshlink->QueryInterface( IID_IPersistFile, (void**) &pPersistFile );
  149. if( FAILED(hr) )
  150. {
  151. TrkLog((TRKDBG_ERROR, TEXT("Couldn't QI IShellLink for IPersistFile") ));
  152. TrkRaiseException( hr );
  153. }
  154. hr = pshlink->SetPath( ptszSrc );
  155. _tprintf( TEXT("IShellLink::SetPath returned %08X (%s)\n"),
  156. hr, 0==hr ? TEXT("no error") : GetErrorString(hr));
  157. if( S_OK != hr )
  158. {
  159. TrkRaiseException( hr );
  160. }
  161. hr = pPersistFile->Save( ptszLink, TRUE );
  162. if( FAILED(hr) )
  163. {
  164. TrkLog((TRKDBG_ERROR, TEXT("Couldn't persist IShellLink") ));
  165. TrkRaiseException( hr );
  166. }
  167. pPersistFile->SaveCompleted( ptszLink );
  168. RELEASE_INTERFACE( pPersistFile );
  169. }
  170. __except( BreakOnDebuggableException() )
  171. {
  172. RELEASE_INTERFACE( pPersistFile );
  173. }
  174. }
  175. TCHAR *
  176. GetRestrict(DWORD r)
  177. {
  178. static TCHAR tszError[256];
  179. tszError[0] = 0;
  180. if (r == TRK_MEND_DEFAULT)
  181. {
  182. _tcscpy(tszError, TEXT("TRK_MEND_DEFAULT "));
  183. }
  184. if (r & TRK_MEND_DONT_USE_LOG)
  185. {
  186. _tcscat(tszError, TEXT("TRK_MEND_DONT_USE_LOG "));
  187. }
  188. if (r & TRK_MEND_DONT_USE_DC)
  189. {
  190. _tcscat(tszError, TEXT("TRK_MEND_DONT_USE_DC "));
  191. }
  192. if (r & TRK_MEND_SLEEP_DURING_MEND)
  193. {
  194. _tcscat(tszError, TEXT("TRK_MEND_SLEEP_DURING_SEARCH "));
  195. }
  196. if (r & TRK_MEND_DONT_SEARCH_ALL_VOLUMES)
  197. {
  198. _tcscat(tszError, TEXT("TRK_MEND_DONT_SEARCH_ALL_VOLUMES "));
  199. }
  200. if (r & TRK_MEND_DONT_USE_VOLIDS)
  201. {
  202. _tcscat(tszError, TEXT("TRK_MEND_DONT_USE_VOLIDS "));
  203. }
  204. return(tszError);
  205. }
  206. void
  207. DisplayIDs( ISLTracker *ptracker )
  208. {
  209. HRESULT hr = S_OK;
  210. CDomainRelativeObjId droidBirth, droidLast;
  211. CMachineId mcid;
  212. TCHAR tsz[ MAX_PATH ];
  213. TCHAR *ptsz = tsz;
  214. hr = ptracker->GetIDs( &droidBirth, &droidLast, &mcid );
  215. if( FAILED(hr) )
  216. {
  217. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't get IDs") ));
  218. TrkRaiseException( hr );
  219. }
  220. droidBirth.Stringize( tsz, sizeof(tsz) );
  221. _tprintf( TEXT("Birth =\t%s\n"), tsz );
  222. droidLast.Stringize( tsz, sizeof(tsz) );
  223. _tprintf( TEXT("Last =\t%s\n"), tsz );
  224. ptsz = tsz;
  225. mcid.Stringize(ptsz);
  226. _tprintf( TEXT("Machine =\t%s\n"), tsz );
  227. }
  228. void
  229. DoResolveLink(IShellLink * pshlink, const TCHAR * ptszLink, DWORD r, DWORD dwSLR, DWORD grfExtra )
  230. {
  231. IPersistFile * pPersistFile = NULL;
  232. ISLTracker * ptracker = NULL;
  233. __try
  234. {
  235. DWORD dwRead;
  236. HRESULT hr;
  237. WCHAR wszPath[MAX_PATH+1];
  238. ULONG cbPath = sizeof(wszPath);
  239. WIN32_FIND_DATA fd;
  240. hr = pshlink->QueryInterface( IID_IPersistFile, (void**) &pPersistFile );
  241. if( FAILED(hr) )
  242. {
  243. TrkLog((TRKDBG_ERROR, TEXT("Couldn't QI for IPersistFile")));
  244. TrkRaiseException( hr );
  245. }
  246. hr = pPersistFile->Load( ptszLink, STGM_SHARE_EXCLUSIVE | STGM_READWRITE );
  247. if( FAILED(hr) )
  248. {
  249. TrkLog((TRKDBG_ERROR, TEXT("Couldn't load IShellLink")));
  250. TrkRaiseException( hr );
  251. }
  252. RELEASE_INTERFACE( pPersistFile );
  253. // Track it (within 30 seconds).
  254. if( TRK_MEND_DEFAULT == r && 0 == grfExtra )
  255. {
  256. hr = pshlink->Resolve( GetDesktopWindow(), 0xfffe0000 | dwSLR | SLR_ANY_MATCH );
  257. }
  258. else
  259. {
  260. hr = pshlink->QueryInterface( IID_ISLTracker, (void**) &ptracker );
  261. if( FAILED(hr) )
  262. {
  263. TrkLog((TRKDBG_ERROR, TEXT("Couldn't QI for ISLTracker")));
  264. TrkRaiseException( hr );
  265. }
  266. if( EXTRAFLAG_SHOW_IDS & grfExtra )
  267. DisplayIDs( ptracker );
  268. hr = ptracker->Resolve( GetDesktopWindow(), 0x00100000 /*0xfffe0000*/ | dwSLR | SLR_ANY_MATCH, r );
  269. if( EXTRAFLAG_SHOW_IDS & grfExtra )
  270. DisplayIDs( ptracker );
  271. }
  272. pshlink->GetPath( wszPath, cbPath, &fd, 0 );
  273. _tprintf( TEXT("%ws %08X (%s) %s\n"),
  274. wszPath, hr, GetErrorString(hr), GetRestrict(r) );
  275. RELEASE_INTERFACE( ptracker );
  276. }
  277. __except( BreakOnDebuggableException() )
  278. {
  279. RELEASE_INTERFACE( pPersistFile );
  280. RELEASE_INTERFACE( ptracker );
  281. }
  282. }
  283. void
  284. SignalLockVolume()
  285. {
  286. HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("LOCK_VOLUMES"));
  287. if (hEvent != NULL)
  288. {
  289. SetEvent(hEvent);
  290. CloseHandle(hEvent);
  291. }
  292. else
  293. {
  294. TrkLog((TRKDBG_ERROR, TEXT("Couldn't open LOCK_VOLUMES event %d\n"), GetLastError()));
  295. }
  296. }
  297. void
  298. DoTestWksSvcUp(TCHAR * ptszMachine)
  299. {
  300. CRpcClientBinding rc;
  301. CMachineId mcid(ptszMachine);
  302. BOOL fCalledMachine = FALSE;
  303. __try
  304. {
  305. rc.RcInitialize(mcid);
  306. if (E_NOTIMPL == LnkRestartDcSynchronization(rc))
  307. fCalledMachine = TRUE;
  308. }
  309. __except(EXCEPTION_EXECUTE_HANDLER)
  310. {
  311. }
  312. TrkLog((TRKDBG_ERROR,
  313. TEXT("%successfully called machine %s\n"),
  314. fCalledMachine ? TEXT("S") : TEXT("Uns"),
  315. ptszMachine));
  316. }
  317. typedef BOOL (WINAPI *PFNMoveFileWithProgress)( LPCWSTR lpExistingFileName,
  318. LPCWSTR lpNewFileName,
  319. LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
  320. LPVOID lpData OPTIONAL,
  321. DWORD dwFlags
  322. );
  323. #ifndef MOVEFILE_FAIL_IF_NOT_TRACKABLE
  324. #define MOVEFILE_FAIL_IF_NOT_TRACKABLE 0x00000020
  325. #endif
  326. #ifndef UNICODE
  327. #error Unicode required for wszFullPath
  328. #endif
  329. EXTERN_C void __cdecl _tmain(int argc, TCHAR **argv)
  330. {
  331. BOOL fError = FALSE;
  332. HRESULT hr;
  333. CMachineId mcid(MCID_LOCAL);
  334. int ArgC = argc;
  335. TCHAR ** ArgV = argv;
  336. DWORD r = TRK_MEND_DEFAULT;
  337. DWORD grfExtra = 0;
  338. DWORD dwSLR = 0; // SLR_ flags
  339. IShellLink *pshlink = NULL;
  340. WCHAR wszFullPath[ MAX_PATH + 1 ];
  341. DWORD dwMoveFlags = MOVEFILE_FAIL_IF_NOT_TRACKABLE |
  342. MOVEFILE_COPY_ALLOWED |
  343. MOVEFILE_REPLACE_EXISTING;
  344. TrkDebugCreate( TRK_DBG_FLAGS_WRITE_TO_DBG | TRK_DBG_FLAGS_WRITE_TO_STDOUT, "TLink" );
  345. CoInitialize( NULL );
  346. hr = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLink, (void**)&pshlink );
  347. if( FAILED(hr) )
  348. {
  349. printf( "Couldn't get an IShellLink (%08x)\n", hr );
  350. goto Exit;
  351. }
  352. ArgC--;
  353. ArgV++;
  354. if (ArgC == 0)
  355. {
  356. fError = TRUE;
  357. }
  358. while (!fError && ArgC > 0)
  359. {
  360. fError = TRUE;
  361. if (ArgV[0][0] == TEXT('-') || ArgV[0][0] == TEXT('/'))
  362. {
  363. switch (ArgV[0][1])
  364. {
  365. case TEXT('a'):
  366. case TEXT('A'):
  367. fError = FALSE;
  368. ArgC --;
  369. ArgV ++;
  370. AttackDC();
  371. break;
  372. case TEXT('e'):
  373. case TEXT('E'):
  374. fError = FALSE;
  375. ArgC --;
  376. ArgV ++;
  377. EnumObjects();
  378. break;
  379. case TEXT('v'):
  380. case TEXT('V'):
  381. fError = FALSE;
  382. ArgC --;
  383. ArgV ++;
  384. SignalLockVolume();
  385. break;
  386. case TEXT('m'):
  387. case TEXT('M'):
  388. if (ArgC >= 3)
  389. {
  390. PFNMoveFileWithProgress pfnMoveFileWithProgress = NULL;
  391. HMODULE hmodKernel32;
  392. for( int i = 2; ArgV[0][i] != TEXT('\0'); i++ )
  393. {
  394. switch(ArgV[0][i])
  395. {
  396. case TEXT('f'):
  397. case TEXT('F'):
  398. dwMoveFlags &= ~ MOVEFILE_FAIL_IF_NOT_TRACKABLE;
  399. break;
  400. case TEXT('n'):
  401. case TEXT('N'):
  402. dwMoveFlags &= ~ MOVEFILE_COPY_ALLOWED;
  403. break;
  404. case TEXT('o'):
  405. case TEXT('O'):
  406. dwMoveFlags &= ~ MOVEFILE_REPLACE_EXISTING;
  407. break;
  408. default:
  409. _tprintf( TEXT("Bad Move switch: %c\n"), ArgV[0][i] );
  410. goto Exit;
  411. } // switch
  412. } // for
  413. hmodKernel32 = GetModuleHandle( TEXT("kernel32.dll") );
  414. if( NULL == hmodKernel32 )
  415. {
  416. TrkLog((TRKDBG_ERROR, TEXT("Failed GetModuleHeader for kernel32.dll") ));
  417. TrkRaiseLastError( );
  418. }
  419. pfnMoveFileWithProgress = (PFNMoveFileWithProgress)
  420. GetProcAddress( hmodKernel32, "MoveFileWithProgressW" );
  421. if( NULL == pfnMoveFileWithProgress )
  422. {
  423. TrkLog((TRKDBG_ERROR, TEXT("Couldn't get MoveFileWithProgress export")));
  424. TrkRaiseLastError( );
  425. }
  426. if( !pfnMoveFileWithProgress( ArgV[1], ArgV[2], NULL, NULL, dwMoveFlags ))
  427. {
  428. _tprintf( TEXT("Failed MoveFileWithProgress (%lu)\n"), GetLastError() );
  429. }
  430. ArgC -= 3;
  431. ArgV += 3;
  432. fError = FALSE;
  433. }
  434. break;
  435. case TEXT('c'):
  436. case TEXT('C'):
  437. if (ArgC >= 3)
  438. {
  439. if( MAX_PATH < RtlGetFullPathName_U( ArgV[2], sizeof(wszFullPath), wszFullPath, NULL ))
  440. {
  441. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't get full path name") ));
  442. TrkRaiseWin32Error( ERROR_BAD_PATHNAME );
  443. }
  444. DoCreateLink( pshlink, ArgV[1], wszFullPath );
  445. ArgC -= 3;
  446. ArgV += 3;
  447. fError = FALSE;
  448. }
  449. break;
  450. case TEXT('r'):
  451. case TEXT('R'):
  452. if (ArgC >= 2)
  453. {
  454. for( int i = 2; ArgV[0][i] != TEXT('\0'); i++ )
  455. {
  456. switch(ArgV[0][i])
  457. {
  458. case TEXT('l'):
  459. case TEXT('L'):
  460. r |= TRK_MEND_DONT_USE_LOG;
  461. break;
  462. case TEXT('d'):
  463. case TEXT('D'):
  464. r |= TRK_MEND_DONT_USE_DC;
  465. break;
  466. case TEXT('i'):
  467. case TEXT('I'):
  468. r |= TRK_MEND_DONT_USE_VOLIDS;
  469. break;
  470. case TEXT('m'):
  471. case TEXT('M'):
  472. r |= TRK_MEND_DONT_SEARCH_ALL_VOLUMES;
  473. break;
  474. case TEXT('s'):
  475. case TEXT('S'):
  476. dwSLR |= SLR_NOSEARCH;
  477. break;
  478. case TEXT('t'):
  479. case TEXT('T'):
  480. dwSLR |= SLR_NOTRACK;
  481. break;
  482. case TEXT('u'):
  483. case TEXT('U'):
  484. dwSLR |= SLR_NO_UI;
  485. break;
  486. case TEXT('x'):
  487. case TEXT('X'):
  488. grfExtra |= EXTRAFLAG_SHOW_IDS;
  489. break;
  490. case TEXT('z'):
  491. case TEXT('Z'):
  492. r |= TRK_MEND_SLEEP_DURING_MEND;
  493. break;
  494. default:
  495. _tprintf( TEXT("Bad Resolve switch: %c\n"), ArgV[0][i] );
  496. goto Exit;
  497. } // switch
  498. } // for
  499. DoResolveLink( pshlink, ArgV[1], r, dwSLR, grfExtra );
  500. ArgC -= 2;
  501. ArgV += 2;
  502. fError = FALSE;
  503. }
  504. break;
  505. case TEXT('t'):
  506. case TEXT('T'):
  507. if (ArgC >= 2)
  508. {
  509. DoTestWksSvcUp( ArgV[1] );
  510. ArgC -= 2;
  511. ArgV += 2;
  512. fError = FALSE;
  513. }
  514. break;
  515. default:
  516. break;
  517. }
  518. }
  519. }
  520. Exit:
  521. if (fError)
  522. {
  523. printf("Usage: \n");
  524. printf(" Operation Params\n");
  525. printf(" --------- ------\n");
  526. printf(" AttackDC -a\n");
  527. printf(" MoveFileWP -m<opts> <src> <dst>\n");
  528. printf(" where <opts> may use: -f = NO fail if not trackable flag\n");
  529. printf(" -n = NO copy-allowed flag\n");
  530. printf(" -o = NO overwrite existing flag\n");
  531. printf(" CreateLink -c <link> <src>\n");
  532. printf(" EnumObjects -e\n");
  533. printf(" SignalLockVolume -v\n");
  534. printf(" ResolveLink -r<opts> <link>\n");
  535. printf(" where <opts> may use: -l = don't use log\n");
  536. printf(" -d = don't use dc\n");
  537. printf(" -i = don't use volids\n");
  538. printf(" -m = don't scan all volumes on a machine\n");
  539. printf(" -s = no search (SLR_NOSEARCH)\n");
  540. printf(" -t = no track (SLR_NOTRACK)\n");
  541. printf(" -x = show before/after droids\n");
  542. printf(" -u = no UI (SLR_NOUI)\n");
  543. printf(" -z = sleep in CTrkWksSvc::Mend\n");
  544. printf("E.g.:\n");
  545. printf(" tlink -c l1 t1\n");
  546. printf(" tlink -mf t1 t1a\n");
  547. printf(" tlink -r l1\n");
  548. printf(" tlink -rd l1\n");
  549. }
  550. RELEASE_INTERFACE( pshlink );
  551. return;
  552. }