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.

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