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.

882 lines
22 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. cleanup.cpp
  5. Abstract:
  6. This file implements the BITS server extensions cleanup worker
  7. --*/
  8. #include "precomp.h"
  9. const UINT64 NanoSec100PerSec = 10000000; //no of 100 nanosecs per second
  10. inline UINT64 FILETIMEToUINT64( const FILETIME & FileTime )
  11. {
  12. ULARGE_INTEGER LargeInteger;
  13. LargeInteger.HighPart = FileTime.dwHighDateTime;
  14. LargeInteger.LowPart = FileTime.dwLowDateTime;
  15. return LargeInteger.QuadPart;
  16. };
  17. class PollKillError : public ComError
  18. {
  19. public:
  20. PollKillError( HRESULT Hr ) :
  21. ComError( Hr )
  22. {
  23. }
  24. };
  25. class CleanupWorker
  26. {
  27. public:
  28. CleanupWorker( BOOL DeleteAll, HWND hwnd, const WCHAR* Path,
  29. const WCHAR *WorkItemName, const WCHAR *GuidString );
  30. ~CleanupWorker();
  31. void DoIt();
  32. private:
  33. BOOL m_DeleteAll;
  34. HWND m_hwnd;
  35. const WCHAR * m_Path;
  36. const WCHAR * m_WorkItemName;
  37. const WCHAR * m_GuidString;
  38. const WCHAR * m_ADSIPath;
  39. IADs * m_VDir;
  40. BSTR m_VDirPath;
  41. BSTR m_SessionDirectory;
  42. BSTR m_UNCUsername;
  43. BSTR m_UNCPassword;
  44. UINT64 m_CleanupThreshold;
  45. VARIANT m_vt;
  46. HANDLE m_FindHandle;
  47. HANDLE m_UserToken;
  48. HANDLE m_EventLog;
  49. BSTR m_BITSCleanupWorkItemKeyBSTR;
  50. BSTR m_BITSUploadEnabledBSTR;
  51. BSTR m_BITSSessionTimeoutBSTR;
  52. BSTR m_PathBSTR;
  53. BSTR m_BITSSessionDirectoryBSTR;
  54. BSTR m_UNCUserNameBSTR;
  55. BSTR m_UNCPasswordBSTR;
  56. WCHAR * BuildPath( const WCHAR * Dir, const WCHAR *Sub );
  57. BSTR GetBSTRProp( BSTR PropName );
  58. void LogonIfRequired();
  59. void PollKill();
  60. void RemoveConnectionsFromTree(
  61. const WCHAR * DirectoryPath,
  62. bool IsConnectionDirectory,
  63. const WCHAR * FileSystemPath = NULL );
  64. void RemoveConnection( const WCHAR * ConnectionDirectory, const WCHAR *FilesystemPath,
  65. const WCHAR * SessionGuid );
  66. void LogDeletedJob( const WCHAR *Path, const WCHAR *SessionGuid );
  67. void LogUnexpectedError( HRESULT Hr );
  68. void LogUnableToRemoveSession( const WCHAR *Path, const WCHAR *SessionGuid, HRESULT Hr );
  69. void LogUnableToScanDirectory( const WCHAR *Path, HRESULT Hr );
  70. };
  71. void
  72. BITSSetCurrentThreadToken(
  73. HANDLE hToken )
  74. {
  75. if ( !SetThreadToken( NULL, hToken ) )
  76. {
  77. for( unsigned int i = 0; i < 100; i ++ )
  78. {
  79. Sleep( 10 );
  80. if ( SetThreadToken( NULL, hToken ) )
  81. return;
  82. }
  83. TerminateProcess( NULL, GetLastError() );
  84. }
  85. }
  86. CleanupWorker::CleanupWorker(
  87. BOOL DeleteAll,
  88. HWND hwnd,
  89. const WCHAR* Path,
  90. const WCHAR* WorkItemName,
  91. const WCHAR* GuidString ) :
  92. m_DeleteAll( DeleteAll ),
  93. m_hwnd( hwnd ),
  94. m_Path( Path ),
  95. m_WorkItemName( WorkItemName ),
  96. m_GuidString( GuidString ),
  97. m_ADSIPath( NULL ),
  98. m_VDir( NULL ),
  99. m_VDirPath( NULL ),
  100. m_SessionDirectory( NULL ),
  101. m_CleanupThreshold( 0 ),
  102. m_UNCUsername( NULL ),
  103. m_UNCPassword( NULL ),
  104. m_UserToken( NULL ),
  105. m_EventLog( NULL ),
  106. m_BITSCleanupWorkItemKeyBSTR( NULL ),
  107. m_BITSUploadEnabledBSTR( NULL ),
  108. m_BITSSessionTimeoutBSTR( NULL ),
  109. m_PathBSTR( NULL ),
  110. m_BITSSessionDirectoryBSTR( NULL ),
  111. m_UNCUserNameBSTR( NULL ),
  112. m_UNCPasswordBSTR( NULL )
  113. {
  114. VariantInit( &m_vt );
  115. m_BITSCleanupWorkItemKeyBSTR = SysAllocString( L"BITSCleanupWorkItemKey" );
  116. m_BITSUploadEnabledBSTR = SysAllocString( L"BITSUploadEnabled" );
  117. m_BITSSessionTimeoutBSTR = SysAllocString( L"BITSSessionTimeout" );
  118. m_PathBSTR = SysAllocString( L"Path" );
  119. m_BITSSessionDirectoryBSTR = SysAllocString( L"BITSSessionDirectory" );
  120. m_UNCUserNameBSTR = SysAllocString( L"UNCUserName" );
  121. m_UNCPasswordBSTR = SysAllocString( L"UNCPassword" );
  122. if ( !m_BITSCleanupWorkItemKeyBSTR || !m_BITSUploadEnabledBSTR || !m_BITSSessionTimeoutBSTR ||
  123. !m_PathBSTR || !m_BITSSessionDirectoryBSTR || !m_UNCUserNameBSTR || !m_UNCPasswordBSTR )
  124. {
  125. SysFreeString( m_BITSCleanupWorkItemKeyBSTR );
  126. SysFreeString( m_BITSUploadEnabledBSTR );
  127. SysFreeString( m_BITSSessionTimeoutBSTR );
  128. SysFreeString( m_PathBSTR );
  129. SysFreeString( m_BITSSessionDirectoryBSTR );
  130. SysFreeString( m_UNCUserNameBSTR );
  131. SysFreeString( m_UNCPasswordBSTR );
  132. throw ComError( E_OUTOFMEMORY );
  133. }
  134. m_EventLog =
  135. RegisterEventSource(
  136. NULL, // server name
  137. EVENT_LOG_SOURCE_NAME // source name
  138. );
  139. if ( !m_EventLog )
  140. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  141. }
  142. CleanupWorker::~CleanupWorker()
  143. {
  144. if ( m_EventLog )
  145. DeregisterEventSource( m_EventLog );
  146. if ( m_UserToken )
  147. {
  148. BITSSetCurrentThreadToken( NULL );
  149. CloseHandle( m_UserToken );
  150. }
  151. delete m_ADSIPath;
  152. SysFreeString( m_VDirPath );
  153. SysFreeString( m_SessionDirectory );
  154. SysFreeString( m_UNCUsername );
  155. SysFreeString( m_UNCPassword );
  156. // Free hardcoded strings
  157. SysFreeString( m_BITSCleanupWorkItemKeyBSTR );
  158. SysFreeString( m_BITSUploadEnabledBSTR );
  159. SysFreeString( m_BITSSessionTimeoutBSTR );
  160. SysFreeString( m_PathBSTR );
  161. SysFreeString( m_BITSSessionDirectoryBSTR );
  162. SysFreeString( m_UNCUserNameBSTR );
  163. SysFreeString( m_UNCPasswordBSTR );
  164. }
  165. void
  166. CleanupWorker::RemoveConnection( const WCHAR * ConnectionDirectory, const WCHAR *FilesystemPath,
  167. const WCHAR * SessionGuid )
  168. {
  169. UINT64 LatestTime = 0;
  170. HANDLE FindHandle = INVALID_HANDLE_VALUE;
  171. WCHAR *SearchPath = NULL;
  172. WCHAR *FileName = NULL;
  173. try
  174. {
  175. SearchPath = BuildPath( ConnectionDirectory, L"*" );
  176. WIN32_FIND_DATA FindData;
  177. FindHandle =
  178. FindFirstFile(
  179. SearchPath,
  180. &FindData
  181. );
  182. if ( INVALID_HANDLE_VALUE == FindHandle )
  183. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  184. bool FoundFile = false;
  185. do
  186. {
  187. if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  188. continue;
  189. FoundFile = true;
  190. UINT64 CreationTime = FILETIMEToUINT64( FindData.ftCreationTime );
  191. UINT64 LastWriteTime = FILETIMEToUINT64( FindData.ftLastWriteTime );
  192. LatestTime = max( LatestTime, max( CreationTime, LastWriteTime ) );
  193. }
  194. while ( FindNextFile( FindHandle, &FindData ) );
  195. FindClose( FindHandle );
  196. FindHandle = INVALID_HANDLE_VALUE;
  197. FILETIME ftCurrentTime;
  198. GetSystemTimeAsFileTime( &ftCurrentTime );
  199. UINT64 CurrentTime = FILETIMEToUINT64( ftCurrentTime );
  200. if ( FoundFile &&
  201. ( 0xFFFFFFFF - LatestTime > m_CleanupThreshold ) &&
  202. ( LatestTime + m_CleanupThreshold < CurrentTime ) )
  203. {
  204. FindHandle =
  205. FindFirstFile(
  206. SearchPath,
  207. &FindData
  208. );
  209. if ( INVALID_HANDLE_VALUE == FindHandle )
  210. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  211. do
  212. {
  213. if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  214. continue;
  215. FileName = BuildPath( ConnectionDirectory, FindData.cFileName );
  216. DeleteFile( FileName );
  217. delete FileName;
  218. FileName = NULL;
  219. }
  220. while ( FindNextFile( FindHandle, &FindData ) );
  221. FindClose( FindHandle );
  222. FindHandle = INVALID_HANDLE_VALUE;
  223. }
  224. if ( !RemoveDirectory( ConnectionDirectory ) )
  225. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  226. LogDeletedJob( FilesystemPath, SessionGuid );
  227. }
  228. catch( PollKillError Error )
  229. {
  230. if ( INVALID_HANDLE_VALUE != FindHandle )
  231. FindClose( FindHandle );
  232. delete SearchPath;
  233. delete FileName;
  234. throw;
  235. }
  236. catch( ComError Error )
  237. {
  238. LogUnableToRemoveSession( FilesystemPath, SessionGuid, Error.m_Hr );
  239. }
  240. if ( INVALID_HANDLE_VALUE != FindHandle )
  241. FindClose( FindHandle );
  242. delete SearchPath;
  243. delete FileName;
  244. }
  245. void
  246. CleanupWorker::RemoveConnectionsFromTree(
  247. const WCHAR * DirectoryPath,
  248. bool IsConnectionDirectory,
  249. const WCHAR * FileSystemPath )
  250. {
  251. WCHAR *ConnectionDir = NULL;
  252. HANDLE FindHandle = INVALID_HANDLE_VALUE;
  253. WCHAR *SearchString = NULL;
  254. WCHAR *NextSearchPath = NULL;
  255. try
  256. {
  257. // Look for BITS-Sessions directory in connection tree
  258. SearchString = BuildPath( DirectoryPath, L"*" );
  259. WIN32_FIND_DATA FindData;
  260. FindHandle =
  261. FindFirstFile(
  262. SearchString,
  263. &FindData );
  264. if ( INVALID_HANDLE_VALUE == FindHandle )
  265. return;
  266. do
  267. {
  268. PollKill();
  269. if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  270. continue;
  271. if ( _wcsicmp( L".", FindData.cFileName ) == 0 )
  272. continue;
  273. if ( _wcsicmp( L"..", FindData.cFileName ) == 0 )
  274. continue;
  275. if ( IsConnectionDirectory )
  276. {
  277. GUID Guid;
  278. if (SUCCEEDED( IIDFromString( FindData.cFileName, &Guid ) ) )
  279. {
  280. NextSearchPath = BuildPath( DirectoryPath, FindData.cFileName );
  281. RemoveConnection( NextSearchPath, FileSystemPath, FindData.cFileName );
  282. delete NextSearchPath;
  283. NextSearchPath = NULL;
  284. }
  285. }
  286. else
  287. {
  288. if ( _wcsicmp( m_SessionDirectory, FindData.cFileName ) == 0 )
  289. {
  290. NextSearchPath = BuildPath( DirectoryPath, FindData.cFileName );
  291. RemoveConnectionsFromTree( NextSearchPath, true, DirectoryPath );
  292. // Mark this as the connection directory so it
  293. // will be closed after the search handles are closed.
  294. ConnectionDir = NextSearchPath;
  295. NextSearchPath = NULL;
  296. }
  297. else
  298. {
  299. // just another directory to recurse into
  300. NextSearchPath = BuildPath( DirectoryPath, FindData.cFileName );
  301. RemoveConnectionsFromTree( NextSearchPath, false );
  302. delete NextSearchPath;
  303. NextSearchPath = NULL;
  304. }
  305. }
  306. }
  307. while( FindNextFile( FindHandle, &FindData ) );
  308. if ( INVALID_HANDLE_VALUE != FindHandle )
  309. {
  310. FindClose( FindHandle );
  311. FindHandle = INVALID_HANDLE_VALUE;
  312. }
  313. delete SearchString;
  314. delete NextSearchPath;
  315. SearchString = NextSearchPath = NULL;
  316. if ( ConnectionDir )
  317. {
  318. // The attempt to remove the directory will fail if
  319. // the directory still has valid connections
  320. RemoveDirectory( ConnectionDir );
  321. delete ConnectionDir;
  322. ConnectionDir = NULL;
  323. }
  324. }
  325. catch( PollKillError Error )
  326. {
  327. if ( INVALID_HANDLE_VALUE != FindHandle )
  328. FindClose( FindHandle );
  329. delete SearchString;
  330. delete NextSearchPath;
  331. delete ConnectionDir;
  332. throw;
  333. }
  334. catch( ComError Error )
  335. {
  336. LogUnableToScanDirectory( DirectoryPath, Error.m_Hr );
  337. }
  338. if ( INVALID_HANDLE_VALUE != FindHandle )
  339. FindClose( FindHandle );
  340. delete SearchString;
  341. delete NextSearchPath;
  342. delete ConnectionDir;
  343. }
  344. void
  345. CleanupWorker::PollKill()
  346. {
  347. if ( m_hwnd )
  348. {
  349. MSG msg;
  350. while( PeekMessage(
  351. &msg,
  352. m_hwnd,
  353. 0,
  354. 0,
  355. PM_REMOVE ) )
  356. {
  357. if ( WM_QUIT == msg.message )
  358. throw PollKillError( (HRESULT)msg.wParam );
  359. TranslateMessage( &msg );
  360. DispatchMessage( &msg );
  361. }
  362. }
  363. }
  364. WCHAR *
  365. CleanupWorker::BuildPath(
  366. const WCHAR *Dir,
  367. const WCHAR *Sub )
  368. {
  369. SIZE_T DirLen = wcslen( Dir );
  370. SIZE_T SubLen = wcslen( Sub );
  371. SIZE_T MaxStringSize = DirLen + SubLen + 2; // one slash, one terminator
  372. WCHAR *RetString = new WCHAR[ MaxStringSize ];
  373. if ( !RetString )
  374. throw ComError( E_OUTOFMEMORY );
  375. memcpy( RetString, Dir, sizeof(WCHAR) * (DirLen + 1) );
  376. WCHAR *p = RetString + DirLen;
  377. if ( p != RetString && *(p - 1) != L'\\' && *(p - 1) != L'/' )
  378. *p++ = L'\\';
  379. memcpy( p, Sub, sizeof(WCHAR) * ( SubLen + 1 ) );
  380. return RetString;
  381. }
  382. BSTR
  383. CleanupWorker::GetBSTRProp( BSTR PropName )
  384. {
  385. BSTR Retval;
  386. THROW_COMERROR( m_VDir->Get( PropName, &m_vt ) );
  387. THROW_COMERROR( VariantChangeType( &m_vt, &m_vt, 0, VT_BSTR ) );
  388. Retval = m_vt.bstrVal;
  389. m_vt.bstrVal = NULL;
  390. VariantClear( &m_vt );
  391. return Retval;
  392. }
  393. void
  394. CleanupWorker::LogonIfRequired()
  395. {
  396. // Don't logon if the path isn't a UNC path
  397. // or the user name is blank
  398. if ( ((WCHAR*)m_VDirPath)[0] != L'\\' ||
  399. ((WCHAR*)m_VDirPath)[1] != L'\\' ||
  400. *(WCHAR*)m_UNCUsername == L'\0' )
  401. return; // no logon required
  402. // crack the user name into a user and domain
  403. WCHAR *UserName = (WCHAR*)m_UNCUsername;
  404. WCHAR *DomainName = NULL;
  405. WCHAR *p = UserName;
  406. while(*p != L'\0')
  407. {
  408. if(*p == L'\\')
  409. {
  410. *p = L'\0';
  411. p++;
  412. //
  413. // first part is domain
  414. // second is user.
  415. //
  416. DomainName = UserName;
  417. UserName = p;
  418. break;
  419. }
  420. p++;
  421. }
  422. if ( !LogonUser(
  423. UserName,
  424. DomainName,
  425. (WCHAR*)m_UNCPassword,
  426. LOGON32_LOGON_BATCH,
  427. LOGON32_PROVIDER_DEFAULT,
  428. &m_UserToken ) )
  429. {
  430. if ( GetLastError() == ERROR_LOGON_TYPE_NOT_GRANTED )
  431. {
  432. if ( !LogonUser(
  433. UserName,
  434. DomainName,
  435. (WCHAR*)m_UNCPassword,
  436. LOGON32_LOGON_INTERACTIVE,
  437. LOGON32_PROVIDER_DEFAULT,
  438. &m_UserToken ) )
  439. {
  440. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  441. }
  442. }
  443. }
  444. if ( !ImpersonateLoggedOnUser( m_UserToken ) )
  445. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  446. }
  447. void
  448. CleanupWorker::DoIt()
  449. {
  450. try
  451. {
  452. m_ADSIPath = ConvertObjectPathToADSI( m_Path );
  453. try
  454. {
  455. THROW_COMERROR( ADsGetObject( m_ADSIPath, __uuidof(*m_VDir), (void**)&m_VDir ) );
  456. if ( m_GuidString )
  457. {
  458. BSTR BSTRGuid = GetBSTRProp( m_BITSCleanupWorkItemKeyBSTR );
  459. int Result = wcscmp( (LPWSTR)BSTRGuid, m_GuidString );
  460. SysFreeString( BSTRGuid );
  461. if ( Result != 0 )
  462. throw ComError( E_ADS_UNKNOWN_OBJECT );
  463. }
  464. }
  465. catch( ComError Error )
  466. {
  467. if ( ( Error.m_Hr == E_ADS_UNKNOWN_OBJECT ) ||
  468. ( Error.m_Hr == HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) ) ||
  469. ( Error.m_Hr == E_ADS_PROPERTY_NOT_FOUND ) )
  470. {
  471. // Somehow the virtual directory was deleted, but the
  472. // task scheduler work item wasn't. Try to delete it now.
  473. if ( m_WorkItemName )
  474. {
  475. ITaskScheduler *TaskScheduler;
  476. if ( SUCCEEDED( ConnectToTaskScheduler( NULL, &TaskScheduler ) ) )
  477. {
  478. TaskScheduler->Delete( m_WorkItemName );
  479. TaskScheduler->Release();
  480. }
  481. }
  482. }
  483. throw;
  484. }
  485. THROW_COMERROR( m_VDir->Get( m_BITSUploadEnabledBSTR, &m_vt ) );
  486. THROW_COMERROR( VariantChangeType( &m_vt, &m_vt, 0, VT_BOOL ) );
  487. if ( !m_vt.boolVal ) // Uploads arn't enabled on this directory
  488. return;
  489. if ( !m_DeleteAll )
  490. {
  491. THROW_COMERROR( m_VDir->Get( m_BITSSessionTimeoutBSTR, &m_vt ) );
  492. THROW_COMERROR( VariantChangeType( &m_vt, &m_vt, 0, VT_BSTR ) );
  493. if ( L'-' == *m_vt.bstrVal )
  494. return; // do not run cleanup in this directory since cleanup has been disabled
  495. UINT64 CleanupSeconds;
  496. if ( 1 != swscanf( (WCHAR*)m_vt.bstrVal, L"%I64u", &CleanupSeconds ) )
  497. return;
  498. if ( CleanupSeconds > ( 0xFFFFFFFFFFFFFFFF / NanoSec100PerSec ) )
  499. m_CleanupThreshold = 0xFFFFFFFFFFFFFFFF; // overflow case
  500. else
  501. m_CleanupThreshold = CleanupSeconds * NanoSec100PerSec;
  502. }
  503. else
  504. m_CleanupThreshold = 0;
  505. m_VDirPath = GetBSTRProp( m_PathBSTR );
  506. m_SessionDirectory = GetBSTRProp( m_BITSSessionDirectoryBSTR );
  507. m_UNCUsername = GetBSTRProp( m_UNCUserNameBSTR );
  508. m_UNCPassword = GetBSTRProp( m_UNCPasswordBSTR );
  509. LogonIfRequired();
  510. RemoveConnectionsFromTree( (WCHAR*)m_VDirPath, false );
  511. }
  512. catch( PollKillError Error )
  513. {
  514. throw;
  515. }
  516. catch( ComError Error )
  517. {
  518. LogUnexpectedError( Error.m_Hr );
  519. throw;
  520. }
  521. }
  522. void
  523. CleanupWorker::LogDeletedJob(
  524. const WCHAR *Path,
  525. const WCHAR *SessionGuid )
  526. {
  527. if ( m_EventLog )
  528. {
  529. const WCHAR *Strings[] = { Path, SessionGuid };
  530. ReportEvent(
  531. m_EventLog, // handle to event log
  532. EVENTLOG_INFORMATION_TYPE, // event type
  533. BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
  534. BITSSRV_EVENTLOG_DELETED_SESSION, // event identifier
  535. NULL, // user security identifier
  536. 2, // number of strings to merge
  537. 0, // size of binary data
  538. Strings, // array of strings to merge
  539. NULL // binary data buffer
  540. );
  541. }
  542. }
  543. void
  544. CleanupWorker::LogUnableToRemoveSession(
  545. const WCHAR *Path,
  546. const WCHAR *SessionGuid,
  547. HRESULT Hr )
  548. {
  549. if ( m_EventLog )
  550. {
  551. const WCHAR *Strings[] = { Path, SessionGuid };
  552. ReportEvent(
  553. m_EventLog, // handle to event log
  554. EVENTLOG_ERROR_TYPE, // event type
  555. BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
  556. BITSSRV_EVENTLOG_CANT_REMOVE_SESSION, // event identifier
  557. NULL, // user security identifier
  558. 2, // number of strings to merge
  559. sizeof(Hr), // size of binary data
  560. Strings, // array of strings to merge
  561. &Hr // binary data buffer
  562. );
  563. }
  564. }
  565. void
  566. CleanupWorker::
  567. LogUnableToScanDirectory(
  568. const WCHAR *Path,
  569. HRESULT Hr )
  570. {
  571. if ( m_EventLog )
  572. {
  573. const WCHAR *Strings[] = { Path };
  574. ReportEvent(
  575. m_EventLog, // handle to event log
  576. EVENTLOG_ERROR_TYPE, // event type
  577. BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
  578. BITSSRV_EVENTLOG_CANT_SCAN_DIRECTORY, // event identifier
  579. NULL, // user security identifier
  580. 1, // number of strings to merge
  581. sizeof(Hr), // size of binary data
  582. Strings, // array of strings to merge
  583. &Hr // binary data buffer
  584. );
  585. }
  586. }
  587. void
  588. CleanupWorker::LogUnexpectedError(
  589. HRESULT Hr )
  590. {
  591. if ( m_EventLog )
  592. {
  593. const WCHAR *Strings[] = { m_Path };
  594. ReportEvent(
  595. m_EventLog, // handle to event log
  596. EVENTLOG_ERROR_TYPE, // event type
  597. BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
  598. BITSSRV_EVENTLOG_UNEXPECTED_ERROR, // event identifier
  599. NULL, // user security identifier
  600. 1, // number of strings to merge
  601. sizeof( Hr ), // size of binary data
  602. Strings, // array of strings to merge
  603. &Hr // binary data buffer
  604. );
  605. }
  606. }
  607. void Cleanup_RunDLLW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR lpszCmdLine, int nCmdShow )
  608. {
  609. int NumArgs;
  610. LPWSTR * CommandArgs =
  611. CommandLineToArgvW(
  612. lpszCmdLine,
  613. &NumArgs );
  614. if ( !CommandArgs )
  615. return;
  616. if ( FAILED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) )
  617. return;
  618. if ( NumArgs != 2 && NumArgs != 3 )
  619. return;
  620. LPWSTR Path = CommandArgs[0];
  621. LPWSTR WorkItemName = CommandArgs[1];
  622. LPWSTR GuidString = NumArgs == 3 ? CommandArgs[2] : NULL;
  623. try
  624. {
  625. CleanupWorker Worker( FALSE, hwndStub, Path, WorkItemName, GuidString );
  626. Worker.DoIt();
  627. }
  628. catch( ComError Error )
  629. {
  630. }
  631. CoUninitialize( );
  632. GlobalFree( CommandArgs );
  633. }
  634. void CleanupForRemoval( LPCWSTR Path )
  635. {
  636. HANDLE hToken = NULL;
  637. try
  638. {
  639. if (!OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken ) )
  640. {
  641. if ( GetLastError() != ERROR_NO_TOKEN )
  642. return;
  643. }
  644. CleanupWorker Worker( TRUE, NULL, Path, NULL, NULL );
  645. Worker.DoIt();
  646. }
  647. catch( ComError Error )
  648. {
  649. }
  650. if ( hToken )
  651. BITSSetCurrentThreadToken( hToken );
  652. }