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.

647 lines
15 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. mdwriter.cxx
  5. Abstract:
  6. This file contains implementation for snapshot writer class
  7. Author:
  8. Ming Lu (MingLu) 30-Apr-2000
  9. --*/
  10. #include <dbgutil.h>
  11. #include "mdwriter.hxx"
  12. #define TIMEOUT_INTERVAL ( 2 * 60 )
  13. #define DEFAULT_SAVE_TIMEOUT 30000
  14. #define MDWRITER_EVENT_TIMEOUT 30000
  15. #define IISCOMPONENT L"IISMETABASE"
  16. #define METABASEPATH L"%windir%\\system32\\inetsrv"
  17. #define METABASENAME1 L"metabase.bin"
  18. #define METABASENAME2 L"MetaBase.XML"
  19. #define METABASENAME3 L"MBSchema.XML"
  20. #define NT_SETUP_KEY "SYSTEM\\Setup"
  21. static VSS_ID s_WRITERID =
  22. {
  23. 0x59b1f0cf, 0x90ef, 0x465f,
  24. 0x96, 0x09, 0x6c, 0xa8, 0xb2, 0x93, 0x83, 0x66
  25. };
  26. static LPCWSTR s_WRITERNAME = L"IIS Metabase Writer";
  27. BOOL g_fWriterSubscribed = FALSE;
  28. CIISVssWriter * g_pIISVssWriter = NULL;
  29. VOID CALLBACK UnlockMBProc(
  30. LPVOID pIISVssWriter,
  31. DWORD dwTimerLowValue,
  32. DWORD dwTimerHighValue
  33. );
  34. BOOL
  35. CIISVssWriter::Initialize(
  36. VOID
  37. )
  38. {
  39. HRESULT hr;
  40. hr = CVssWriter::Initialize( s_WRITERID,
  41. s_WRITERNAME,
  42. VSS_UT_SYSTEMSERVICE,
  43. VSS_ST_OTHER
  44. );
  45. if( FAILED( hr ) )
  46. {
  47. DBGPRINTF(( DBG_CONTEXT,
  48. "Error in base object Initialize(). hr = %x\n",
  49. hr ));
  50. return FALSE;
  51. }
  52. m_hTimer = CreateWaitableTimer( NULL, FALSE, NULL );
  53. if( !m_hTimer )
  54. {
  55. DBGPRINTF(( DBG_CONTEXT,
  56. "Error creating timer object. hr = %x\n",
  57. HRESULT_FROM_WIN32( GetLastError() ) ));
  58. return FALSE;
  59. }
  60. hr = CoCreateInstance( CLSID_MDCOM, NULL, CLSCTX_SERVER, IID_IMDCOM, (void**) &m_pMdObject);
  61. if( SUCCEEDED( hr ) )
  62. {
  63. hr = m_pMdObject->ComMDInitialize();
  64. if( FAILED( hr ) )
  65. {
  66. DBGPRINTF(( DBG_CONTEXT,
  67. "Error initialize MDCOM object. hr = %x\n",
  68. hr ));
  69. m_pMdObject->Release();
  70. m_pMdObject = NULL;
  71. return FALSE;
  72. }
  73. }
  74. else
  75. {
  76. DBGPRINTF(( DBG_CONTEXT,
  77. "Error creating MDCOM object. hr = %x\n",
  78. hr ));
  79. return FALSE;
  80. }
  81. return TRUE;
  82. }
  83. bool STDMETHODCALLTYPE
  84. CIISVssWriter::OnIdentify(
  85. IN IVssCreateWriterMetadata *pMetadata
  86. )
  87. {
  88. HRESULT hr;
  89. hr = pMetadata->AddComponent( VSS_CT_FILEGROUP,
  90. NULL,
  91. IISCOMPONENT,
  92. NULL,
  93. 0,
  94. 0,
  95. FALSE,
  96. FALSE,
  97. FALSE );
  98. if( FAILED( hr ) )
  99. {
  100. DBGPRINTF(( DBG_CONTEXT,
  101. "Error AddComponent(). hr = %x\n",
  102. hr ));
  103. return FALSE;
  104. }
  105. hr = pMetadata->AddFilesToFileGroup( NULL,
  106. IISCOMPONENT,
  107. METABASEPATH,
  108. METABASENAME1,
  109. FALSE,
  110. NULL );
  111. if( FAILED( hr ) )
  112. {
  113. DBGPRINTF(( DBG_CONTEXT,
  114. "Error AddFilesToFileGroup(). hr = %x\n",
  115. hr ));
  116. return FALSE;
  117. }
  118. hr = pMetadata->AddFilesToFileGroup( NULL,
  119. IISCOMPONENT,
  120. METABASEPATH,
  121. METABASENAME2,
  122. FALSE,
  123. NULL );
  124. if( FAILED( hr ) )
  125. {
  126. DBGPRINTF(( DBG_CONTEXT,
  127. "Error AddFilesToFileGroup(). hr = %x\n",
  128. hr ));
  129. return FALSE;
  130. }
  131. hr = pMetadata->AddFilesToFileGroup( NULL,
  132. IISCOMPONENT,
  133. METABASEPATH,
  134. METABASENAME3,
  135. FALSE,
  136. NULL );
  137. if( FAILED( hr ) )
  138. {
  139. DBGPRINTF(( DBG_CONTEXT,
  140. "Error AddFilesToFileGroup(). hr = %x\n",
  141. hr ));
  142. return FALSE;
  143. }
  144. hr = pMetadata->SetRestoreMethod(
  145. VSS_RME_RESTORE_AT_REBOOT, // restore method
  146. NULL, // service name
  147. NULL, // user procedure
  148. VSS_WRE_NEVER, // when to call writer restore method
  149. TRUE // reboot is required
  150. );
  151. if( FAILED( hr ) )
  152. {
  153. DBGPRINTF(( DBG_CONTEXT,
  154. "Error setting restore method. hr = %x\n",
  155. hr ));
  156. return FALSE;
  157. }
  158. return TRUE;
  159. }
  160. bool STDMETHODCALLTYPE
  161. CIISVssWriter::OnPrepareBackup(
  162. IN IVssWriterComponents *pWriterComponents
  163. )
  164. {
  165. return TRUE;
  166. }
  167. bool STDMETHODCALLTYPE
  168. CIISVssWriter::OnPrepareSnapshot(
  169. VOID
  170. )
  171. {
  172. HRESULT hr;
  173. if( IsPathAffected( METABASEPATH ) )
  174. {
  175. //
  176. // First try to lock the tree
  177. //
  178. hr = m_pMdObject->ComMDOpenMetaObjectW( METADATA_MASTER_ROOT_HANDLE,
  179. NULL,
  180. METADATA_PERMISSION_READ,
  181. DEFAULT_SAVE_TIMEOUT,
  182. &m_mdhRoot);
  183. if ( SUCCEEDED( hr ) ) {
  184. //
  185. // call metadata com api
  186. //
  187. hr = m_pMdObject->ComMDSaveData( m_mdhRoot );
  188. if( SUCCEEDED( hr ) )
  189. {
  190. hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
  191. if( SUCCEEDED ( hr ) )
  192. {
  193. return TRUE;
  194. }
  195. DBGPRINTF(( DBG_CONTEXT,
  196. "Error on unlocking the metabase. hr = %x\n",
  197. hr ));
  198. return FALSE;
  199. }
  200. DBGPRINTF(( DBG_CONTEXT,
  201. "Error on saving the metabase. hr = %x\n",
  202. hr ));
  203. m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
  204. return FALSE;
  205. }
  206. DBGPRINTF(( DBG_CONTEXT,
  207. "Error on locking down the metabase. hr = %x\n",
  208. hr ));
  209. return FALSE;
  210. }
  211. return TRUE;
  212. }
  213. bool STDMETHODCALLTYPE
  214. CIISVssWriter::OnFreeze(
  215. VOID
  216. )
  217. {
  218. HRESULT hr;
  219. if( IsPathAffected( METABASEPATH ) )
  220. {
  221. //
  222. // Lock down the metabase
  223. //
  224. hr = m_pMdObject->ComMDOpenMetaObjectW(METADATA_MASTER_ROOT_HANDLE,
  225. NULL,
  226. METADATA_PERMISSION_READ,
  227. DEFAULT_SAVE_TIMEOUT,
  228. &m_mdhRoot);
  229. if( FAILED( hr ) )
  230. {
  231. DBGPRINTF(( DBG_CONTEXT,
  232. "Error on locking down the metabase. hr = %x\n",
  233. hr ));
  234. return FALSE;
  235. }
  236. else
  237. {
  238. if( !ResetTimer( m_hTimer, TIMEOUT_INTERVAL ) )
  239. {
  240. DBGPRINTF(( DBG_CONTEXT,
  241. "Could not reset the internal timer. hr = %x\n",
  242. hr ));
  243. return FALSE;
  244. }
  245. EnterCriticalSection( &m_csMBLock );
  246. m_fMBLocked = TRUE;
  247. LeaveCriticalSection( &m_csMBLock );
  248. }
  249. }
  250. return TRUE;
  251. }
  252. bool STDMETHODCALLTYPE
  253. CIISVssWriter::OnThaw(
  254. VOID
  255. )
  256. {
  257. HRESULT hr;
  258. if( IsPathAffected( METABASEPATH ) )
  259. {
  260. EnterCriticalSection( &m_csMBLock );
  261. if( m_fMBLocked )
  262. {
  263. hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
  264. if( FAILED( hr ) )
  265. {
  266. DBGPRINTF(( DBG_CONTEXT,
  267. "Error on unlocking the metabase. hr = %x\n",
  268. hr ));
  269. LeaveCriticalSection( &m_csMBLock );
  270. return FALSE;
  271. }
  272. m_fMBLocked = FALSE;
  273. LeaveCriticalSection( &m_csMBLock );
  274. CancelWaitableTimer( m_hTimer );
  275. }
  276. else
  277. {
  278. LeaveCriticalSection( &m_csMBLock );
  279. }
  280. }
  281. return TRUE;
  282. }
  283. bool STDMETHODCALLTYPE
  284. CIISVssWriter::OnBackupComplete(
  285. IN IVssWriterComponents *pWriterComponents
  286. )
  287. {
  288. return TRUE;
  289. }
  290. bool STDMETHODCALLTYPE
  291. CIISVssWriter::OnAbort(
  292. VOID
  293. )
  294. {
  295. HRESULT hr;
  296. if( IsPathAffected( METABASEPATH ) )
  297. {
  298. EnterCriticalSection( &m_csMBLock );
  299. if( m_fMBLocked )
  300. {
  301. hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
  302. if( FAILED( hr ) )
  303. {
  304. DBGPRINTF(( DBG_CONTEXT,
  305. "Error on unlocking the metabase. hr = %x\n",
  306. hr ));
  307. LeaveCriticalSection( &m_csMBLock );
  308. return FALSE;
  309. }
  310. m_fMBLocked = FALSE;
  311. LeaveCriticalSection( &m_csMBLock );
  312. CancelWaitableTimer( m_hTimer );
  313. }
  314. else
  315. {
  316. LeaveCriticalSection( &m_csMBLock );
  317. }
  318. }
  319. return true;
  320. }
  321. VOID
  322. CIISVssWriter::UnlockMetaBase(
  323. VOID
  324. )
  325. {
  326. HRESULT hr;
  327. EnterCriticalSection( &m_csMBLock );
  328. if( m_fMBLocked )
  329. {
  330. hr = m_pMdObject->ComMDCloseMetaObject( m_mdhRoot );
  331. if( FAILED( hr ) )
  332. {
  333. DBGPRINTF(( DBG_CONTEXT,
  334. "Error on unlocking the metabase. hr = %x\n",
  335. hr ));
  336. LeaveCriticalSection( &m_csMBLock );
  337. return;
  338. }
  339. m_fMBLocked = FALSE;
  340. }
  341. LeaveCriticalSection( &m_csMBLock );
  342. }
  343. BOOL
  344. CIISVssWriter::ResetTimer(
  345. HANDLE hTimer,
  346. DWORD dwDuration
  347. )
  348. {
  349. LARGE_INTEGER li;
  350. const int nNanosecondsPersecond = 10000000;
  351. __int64 qwTimeFromNowInNanoseconds =
  352. (__int64)dwDuration * nNanosecondsPersecond;
  353. qwTimeFromNowInNanoseconds = -qwTimeFromNowInNanoseconds;
  354. li.LowPart = (DWORD) (qwTimeFromNowInNanoseconds & 0xFFFFFFFF);
  355. li.HighPart = (LONG) (qwTimeFromNowInNanoseconds >> 32);
  356. if( !SetWaitableTimer( hTimer, &li, 0, UnlockMBProc, this, FALSE ) )
  357. {
  358. return FALSE;
  359. }
  360. return TRUE;
  361. }
  362. VOID CALLBACK
  363. UnlockMBProc(
  364. LPVOID pIISVssWriter,
  365. DWORD dwTimerLowValue,
  366. DWORD dwTimerHighValue
  367. )
  368. {
  369. ( ( CIISVssWriter * )pIISVssWriter )->UnlockMetaBase();
  370. }
  371. VOID
  372. InitMDWriterThread(
  373. HANDLE hMDWriterEvent
  374. )
  375. {
  376. HKEY hKey;
  377. DWORD dwType;
  378. DWORD cbData;
  379. DWORD dwSetupInProgress = 0;
  380. DWORD dwUpgradeInProcess = 0;
  381. DBG_ASSERT( hMDWriterEvent != NULL );
  382. //
  383. // Read the setup registry key to see if we are in
  384. // setup mode. If we are, don't init IIS writer.
  385. //
  386. if ( !RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  387. NT_SETUP_KEY,
  388. 0,
  389. KEY_QUERY_VALUE,
  390. &hKey ) )
  391. {
  392. cbData = sizeof( DWORD );
  393. if( !RegQueryValueEx( hKey,
  394. "SystemSetupInProgress",
  395. NULL,
  396. &dwType,
  397. ( LPBYTE )&dwSetupInProgress,
  398. &cbData ) )
  399. {
  400. if( dwType == REG_DWORD && dwSetupInProgress != 0 )
  401. {
  402. //
  403. // We are in setup mode
  404. //
  405. RegCloseKey( hKey );
  406. goto exit;
  407. }
  408. }
  409. if( !RegQueryValueEx( hKey,
  410. "UpgradeInProgress",
  411. NULL,
  412. &dwType,
  413. ( LPBYTE )&dwUpgradeInProcess,
  414. &cbData ) )
  415. {
  416. if( dwType == REG_DWORD && dwUpgradeInProcess != 0 )
  417. {
  418. //
  419. // We are in upgrade mode
  420. //
  421. RegCloseKey( hKey );
  422. goto exit;
  423. }
  424. }
  425. RegCloseKey( hKey );
  426. }
  427. //
  428. // OK, we are not in setup mode, initialize our IIS writer
  429. //
  430. g_pIISVssWriter = new CIISVssWriter;
  431. if ( g_pIISVssWriter == NULL )
  432. {
  433. //
  434. // oh well. guess we won�t support snapshots
  435. //
  436. DBGPRINTF(( DBG_CONTEXT,
  437. "Error on creating the writer object, out of memory\n"
  438. ));
  439. goto exit;
  440. }
  441. else
  442. {
  443. //
  444. // cool, we�ve got the object now.
  445. //
  446. if( !g_pIISVssWriter->Initialize() )
  447. {
  448. DBGPRINTF(( DBG_CONTEXT,
  449. "Error on initializing the writer object\n"
  450. ));
  451. delete g_pIISVssWriter;
  452. g_pIISVssWriter = NULL;
  453. goto exit;
  454. }
  455. if( SUCCEEDED( g_pIISVssWriter->Subscribe() ) )
  456. {
  457. g_fWriterSubscribed = TRUE;
  458. }
  459. else
  460. {
  461. DBGPRINTF(( DBG_CONTEXT,
  462. "Error on subscribing the writer object\n"
  463. ));
  464. delete g_pIISVssWriter;
  465. g_pIISVssWriter = NULL;
  466. }
  467. }
  468. exit:
  469. //
  470. // Let the TerminateMDWriter know we are ready to terminate during
  471. // IISADMIN service shutdown
  472. //
  473. SetEvent( hMDWriterEvent );
  474. }
  475. HRESULT
  476. InitializeMDWriter(
  477. HANDLE hMDWriterEvent
  478. )
  479. {
  480. HRESULT hr = S_OK;
  481. HANDLE hThread = NULL;
  482. DWORD dwThreadID;
  483. DBG_ASSERT( hMDWriterEvent != NULL );
  484. hThread = CreateThread( NULL,
  485. 0,
  486. ( LPTHREAD_START_ROUTINE )InitMDWriterThread,
  487. ( PVOID )hMDWriterEvent,
  488. 0,
  489. &dwThreadID);
  490. if( hThread == NULL )
  491. {
  492. hr = HRESULT_FROM_WIN32( GetLastError() );
  493. }
  494. return hr;
  495. }
  496. VOID
  497. TerminateMDWriter(
  498. HANDLE hMDWriterEvent
  499. )
  500. {
  501. DBG_ASSERT( hMDWriterEvent != NULL );
  502. //
  503. // Only do cleanup if the hMDWriterEvent is signaled
  504. //
  505. if( WAIT_OBJECT_0 == WaitForSingleObject( hMDWriterEvent,
  506. MDWRITER_EVENT_TIMEOUT ) )
  507. {
  508. if( g_fWriterSubscribed )
  509. {
  510. DBG_ASSERT( g_pIISVssWriter );
  511. g_pIISVssWriter->Unsubscribe();
  512. }
  513. if( g_pIISVssWriter )
  514. {
  515. delete g_pIISVssWriter;
  516. g_pIISVssWriter = NULL;
  517. }
  518. }
  519. }