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.

472 lines
14 KiB

  1. #include "stdafx.h"
  2. #include "WizardSheet.h"
  3. #include "UIUtils.h"
  4. static _ATL_FUNC_INFO StateChangeInfo = { CC_STDCALL,
  5. VT_BOOL,
  6. 4,
  7. { VT_I4, VT_VARIANT, VT_VARIANT, VT_VARIANT }
  8. };
  9. CExportProgress::CExportProgress( CWizardSheet* pTheSheet ) :
  10. m_pTheSheet( pTheSheet )
  11. {
  12. m_strTitle.LoadString( IDS_TITLE_EXPORT_PROGRESS );
  13. m_strSubTitle.LoadString( IDS_SUBTITLE_EXPORT_PROGRESS );
  14. SetHeaderTitle( m_strTitle );
  15. SetHeaderSubTitle( m_strSubTitle );
  16. }
  17. BOOL CExportProgress::OnSetActive()
  18. {
  19. SetWizardButtons( 0 );
  20. ListBox_ResetContent( GetDlgItem( IDC_OPLIST ) );
  21. AddStatusText( IDC_OPS_INITENGINE );
  22. m_ProgressBar = GetDlgItem( IDC_PROGRESS );
  23. m_ProgressBar.SetPos( 0 );
  24. VERIFY( SetDlgItemText( IDC_STATUS, L"" ) );
  25. m_strExportError.Empty();
  26. m_nExportCanceled = 0;
  27. UINT nThreadID = 0;
  28. // Start the thread where the actuall export process will take place
  29. m_shThread = reinterpret_cast<HANDLE>( ::_beginthreadex( NULL,
  30. 0,
  31. CExportProgress::ThreadProc,
  32. this,
  33. 0,
  34. &nThreadID ) );
  35. return TRUE;
  36. }
  37. BOOL CExportProgress::OnQueryCancel( void )
  38. {
  39. // If Export is not in progress - allow exit
  40. if ( !m_shThread.IsValid() ) return TRUE;
  41. // Preven reentrancy ( Cancel the export when it's already cancedl )
  42. // while we wait for next event from the COM object
  43. if ( m_nExportCanceled != 0 ) return FALSE;
  44. if ( UIUtils::MessageBox( m_hWnd, IDS_MSG_CANCELEXPORT, IDS_APPTITLE, MB_YESNO | MB_ICONQUESTION ) != IDYES )
  45. {
  46. return FALSE;
  47. }
  48. // m_nExportCanceled is used by the event handler which is another thread
  49. ::InterlockedIncrement( &m_nExportCanceled );
  50. // Set the status text
  51. CString str;
  52. VERIFY( str.LoadString( IDS_PRG_EXPORTCANCELED ) );
  53. SetDlgItemText( IDC_STATUS, str );
  54. HANDLE hThread = m_shThread.get();
  55. do
  56. {
  57. DWORD dwWaitRes = ::MsgWaitForMultipleObjects( 1, &hThread, FALSE, INFINITE, QS_ALLEVENTS );
  58. if ( dwWaitRes == ( WAIT_OBJECT_0 + 1 ) )
  59. {
  60. // MSG
  61. MSG msg;
  62. ::GetMessage( &msg, NULL, 0, 0 );
  63. ::TranslateMessage( &msg );
  64. ::DispatchMessage( &msg );
  65. }
  66. else
  67. {
  68. break;
  69. }
  70. }while( true );
  71. return TRUE;
  72. }
  73. unsigned __stdcall CExportProgress::ThreadProc( void* pCtx )
  74. {
  75. CExportProgress* pThis = reinterpret_cast<CExportProgress*>( pCtx );
  76. pThis->SetCompleteStat();
  77. pThis->AddStatusText( IDS_OPS_CONFIGENGINE );
  78. HRESULT hr = ::CoInitialize( NULL );
  79. IExportPackagePtr spExport;
  80. LONG nSiteOpt = 0;
  81. LONG nPkgOpt = 0;
  82. LONG nSiteID = static_cast<LONG>( pThis->m_pTheSheet->m_pageSelectSite.m_dwSiteID );
  83. bool bAdvised = false; // Is connected to the event source
  84. pThis->GetOptions( /*r*/nSiteOpt, /*r*/nPkgOpt );
  85. if ( SUCCEEDED( hr ) )
  86. {
  87. hr = spExport.CreateInstance( CLSID_ExportPackage );
  88. if ( FAILED( hr ) )
  89. {
  90. VERIFY( pThis->m_strExportError.LoadString( IDS_E_NOENGINE ) );
  91. }
  92. }
  93. if ( SUCCEEDED( hr ) )
  94. {
  95. hr = spExport->AddSite( nSiteID, nSiteOpt );
  96. }
  97. // Add the post processing stuff if any
  98. if ( pThis->m_pTheSheet->m_pagePkgCfg.m_bPostProcess )
  99. {
  100. const TStringList& Files = pThis->m_pTheSheet->m_pagePostProcess.m_Files;
  101. const CPostProcessAdd::TCmdList& Cmds = pThis->m_pTheSheet->m_pagePostProcess.m_Commands;
  102. CComBSTR bstr;
  103. // Add the files
  104. for ( TStringList::const_iterator it = Files.begin();
  105. SUCCEEDED( hr ) && ( it != Files.end() );
  106. ++it )
  107. {
  108. bstr = it->c_str();
  109. if ( NULL == bstr.m_str ) hr = E_OUTOFMEMORY;
  110. if ( SUCCEEDED( hr ) )
  111. {
  112. hr = spExport->PostProcessAddFile( nSiteID, bstr );
  113. }
  114. }
  115. // Add the commands
  116. for ( CPostProcessAdd::TCmdList::const_iterator it = Cmds.begin();
  117. SUCCEEDED( hr ) && ( it != Cmds.end() );
  118. ++it )
  119. {
  120. bstr = it->strText;
  121. if ( NULL == bstr.m_str ) hr = E_OUTOFMEMORY;
  122. if ( SUCCEEDED( hr ) )
  123. {
  124. hr = spExport->PostProcessAddCommand( nSiteID,
  125. bstr,
  126. it->dwTimeout,
  127. it->bIgnoreErrors ? VARIANT_TRUE : VARIANT_FALSE );
  128. }
  129. }
  130. }
  131. // Advise to the state events
  132. if ( SUCCEEDED( hr ) )
  133. {
  134. hr = pThis->DispEventAdvise( spExport.GetInterfacePtr() );
  135. bAdvised = SUCCEEDED( hr );
  136. }
  137. // Create the package
  138. if ( SUCCEEDED( hr ) )
  139. {
  140. CComBSTR bstrPkgName( pThis->m_pTheSheet->m_pagePkgCfg.m_strFilename );
  141. CComBSTR bstrPwd( pThis->m_pTheSheet->m_pagePkgCfg.m_strPassword );
  142. CComBSTR bstrComment( pThis->m_pTheSheet->m_pagePkgCfg.m_strComment );
  143. if ( ( NULL == bstrPkgName.m_str ) ||
  144. ( NULL == bstrComment.m_str ) ||
  145. ( NULL == bstrPwd.m_str ) )
  146. {
  147. hr = E_OUTOFMEMORY;
  148. }
  149. if ( SUCCEEDED( hr ) )
  150. {
  151. hr = spExport->WritePackage( bstrPkgName, bstrPwd, nPkgOpt, bstrComment );
  152. }
  153. }
  154. // Get the error
  155. if ( pThis->m_strExportError.IsEmpty() && FAILED( hr ) )
  156. {
  157. CComBSTR bstrText( L"Unknown Error" );;
  158. IErrorInfoPtr spInfo;
  159. VERIFY( SUCCEEDED( ::GetErrorInfo( 0, &spInfo ) ) );
  160. if ( spInfo != NULL )
  161. {
  162. VERIFY( SUCCEEDED( spInfo->GetDescription( &bstrText ) ) );
  163. }
  164. pThis->m_strExportError = bstrText;
  165. }
  166. // Disconnect from the event source
  167. if ( bAdvised )
  168. {
  169. VERIFY( SUCCEEDED( pThis->DispEventUnadvise( spExport.GetInterfacePtr() ) ) );
  170. }
  171. spExport = NULL;
  172. ::CoUninitialize();
  173. // Notify the dialog that the export is complete
  174. VERIFY( ::PostMessage( pThis->m_hWnd, MSG_COMPLETE, hr, 0 ) );
  175. return 0;
  176. }
  177. void CExportProgress::AddStatusText( UINT nID, LPCWSTR wszText /*= NULL*/, DWORD dw1 /*= 0*/, DWORD dw2 /*= 0*/ )
  178. {
  179. CString str;
  180. str.Format( nID, wszText, dw1, dw2 );
  181. ListBox_InsertString( GetDlgItem( IDC_OPLIST ), -1, str );
  182. }
  183. void CExportProgress::SetCompleteStat()
  184. {
  185. CListBox LB( GetDlgItem( IDC_OPLIST ) );
  186. int iLast = LB.GetCount() - 1;
  187. _ASSERT( iLast >= 0 );
  188. CString strCurrent;
  189. LB.GetText( iLast, strCurrent );
  190. strCurrent += L"OK";
  191. LB.InsertString( iLast, strCurrent );
  192. LB.DeleteString( iLast + 1 );
  193. }
  194. void CExportProgress::GetOptions( LONG& rnSiteOpt, LONG& rnPkgOpt )
  195. {
  196. rnSiteOpt = asDefault;
  197. rnPkgOpt = wpkgDefault;
  198. if ( !m_pTheSheet->m_pageSelectSite.m_bExportACLs )
  199. {
  200. rnSiteOpt |= asNoContentACLs;
  201. }
  202. if ( !m_pTheSheet->m_pageSelectSite.m_bExportContent )
  203. {
  204. rnSiteOpt |= asNoContent;
  205. }
  206. if ( !m_pTheSheet->m_pageSelectSite.m_bExportCert )
  207. {
  208. rnSiteOpt |= asNoCertificates;
  209. }
  210. if ( m_pTheSheet->m_pagePkgCfg.m_bCompress )
  211. {
  212. rnPkgOpt |= wpkgCompress;
  213. }
  214. if ( m_pTheSheet->m_pagePkgCfg.m_bEncrypt )
  215. {
  216. rnPkgOpt |= wpkgEncrypt;
  217. }
  218. }
  219. /*
  220. This is the event handler that will be fired for status notifications by the COM Object
  221. Note that this will execute in different thread then the Wizard code
  222. */
  223. VARIANT_BOOL __stdcall CExportProgress::OnStateChange( IN enExportState State,
  224. IN VARIANT vntArg1,
  225. IN VARIANT vntArg2,
  226. IN VARIANT vntArg3 )
  227. {
  228. static enExportState CurrentState = estInitializing;
  229. WCHAR wszPath[ MAX_PATH ];
  230. CString strStatus;
  231. bool bNewState = ( State != CurrentState );
  232. // This is the progress range which each state can use
  233. const int anStatePrgRange[ estStateCount ] = { 10, // estInitializing
  234. 10, // estSiteBegin
  235. 10, // estExportingConfig
  236. 10, // estExportingCertificate
  237. 10, // estAnalyzingContent
  238. 1000, // estExportingContent
  239. 100, // estExportingPostImport
  240. 10, // estExportingFrontPage
  241. 10 }; // estFinalizing
  242. // This is the initial progress position for each state
  243. static int anStatePrgFirst[ estStateCount ];
  244. // If the user canceled the export - notify the COM object that we want to terminate the export
  245. if ( m_nExportCanceled != 0 )
  246. {
  247. return VARIANT_FALSE;
  248. }
  249. // We can receive a particular state more then once
  250. // But when we moove to the next state we need to update the status list box
  251. if ( bNewState )
  252. {
  253. // End the old state in the LB
  254. SetCompleteStat();
  255. CurrentState = State;
  256. // Set the progress to the initial pos for this state
  257. m_ProgressBar.SetPos( anStatePrgFirst[ State ] );
  258. }
  259. switch( State )
  260. {
  261. case estInitializing:
  262. // Adjust the progress bar
  263. anStatePrgFirst[ 0 ] = 1;
  264. for ( int i = 1; i < estStateCount; ++i )
  265. {
  266. anStatePrgFirst[ i ] = anStatePrgFirst[ i - 1 ] + anStatePrgRange[ i - 1 ];
  267. }
  268. m_ProgressBar.SetRange32( 0, anStatePrgFirst[ estStateCount - 1 ] + anStatePrgRange[ estStateCount - 1 ] );
  269. break;
  270. case estSiteBegin:
  271. // This is one-time notification
  272. AddStatusText( IDS_PRG_SITEBEGIN, V_BSTR( &vntArg1 ) );
  273. break;
  274. case estExportingConfig:
  275. // This is one-time notification
  276. AddStatusText( IDS_PRG_EXPORTCFG );
  277. break;
  278. case estExportingCertificate:
  279. // This is one-time notification
  280. AddStatusText( IDS_PRG_EXPORTCERT );
  281. break;
  282. case estAnalyzingContent:
  283. // This is a multiple-time event
  284. if ( bNewState )
  285. {
  286. AddStatusText( IDS_PRG_ANALYZECONTEN );
  287. }
  288. if ( V_VT( &vntArg1 ) != VT_EMPTY )
  289. {
  290. strStatus.Format( IDS_PRG_VDIR_SCAN, V_BSTR( &vntArg1 ), V_I4( &vntArg2 ), V_I4( &vntArg3 ) );
  291. VERIFY( SetDlgItemText( IDC_STATUS, strStatus ) );
  292. }
  293. break;
  294. case estExportingContent:
  295. // This is a multiple-time event
  296. if ( bNewState )
  297. {
  298. AddStatusText( IDS_PRG_EXPORTCONTENT );
  299. }
  300. VERIFY( ::PathCompactPathExW( wszPath, V_BSTR( &vntArg1 ), 70, 0 ) );
  301. strStatus.Format( IDS_PRG_STATCONTENT, wszPath );
  302. VERIFY( SetDlgItemText( IDC_STATUS, strStatus ) );
  303. m_ProgressBar.SetPos( anStatePrgFirst[ estExportingContent ] +
  304. min( V_I4( &vntArg2 ) *
  305. anStatePrgRange[ estExportingContent ] /
  306. V_I4( &vntArg3 ),
  307. anStatePrgRange[ estExportingContent ] ) );
  308. break;
  309. case estExportingPostImport:
  310. // This is a multiple-time event
  311. if ( bNewState )
  312. {
  313. AddStatusText( IDS_PRG_EXPORTPOSTPROCESS );
  314. }
  315. if ( V_VT( &vntArg3 ) != VT_EMPTY )
  316. {
  317. VERIFY( ::PathCompactPathExW( wszPath, V_BSTR( &vntArg3 ), 70, 0 ) );
  318. strStatus.Format( IDS_PRG_STATCONTENT, wszPath );
  319. VERIFY( SetDlgItemText( IDC_STATUS, strStatus ) );
  320. }
  321. else
  322. {
  323. VERIFY( SetDlgItemText( IDC_STATUS, L"" ) );
  324. }
  325. m_ProgressBar.SetPos( anStatePrgFirst[ estExportingPostImport ] +
  326. min( V_I4( &vntArg1 ) *
  327. anStatePrgRange[ estExportingPostImport ] /
  328. V_I4( &vntArg2 ),
  329. anStatePrgRange[ estExportingPostImport ] ) );
  330. break;
  331. case estFinalizing:
  332. // This is one-time notification
  333. AddStatusText( IDS_PRG_FINALIZING );
  334. break;
  335. }
  336. return VARIANT_TRUE;
  337. }
  338. LRESULT CExportProgress::OnExportComplete( UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
  339. {
  340. m_shThread.Close();
  341. if ( FAILED( wParam ) )
  342. {
  343. CString strError;
  344. CString strTitle;
  345. strError.Format( IDS_E_EXPORT, static_cast<LPCWSTR>( m_strExportError ) );
  346. strTitle.LoadString( IDS_APPTITLE );
  347. ::MessageBox( m_hWnd, strError, strTitle, MB_OK | MB_ICONSTOP );
  348. // Go to the summary page
  349. m_pTheSheet->SetActivePageByID( IDD_WPEXP_SUMMARY );
  350. }
  351. else
  352. {
  353. CString strTip;
  354. VERIFY( strTip.LoadString( IDS_TIP_PRESSNEXT ) );
  355. VERIFY( SetDlgItemText( IDC_TIP, strTip ) );
  356. SetWindowFont( GetDlgItem( IDC_TIP ), m_pTheSheet->m_fontBold.get(), TRUE );
  357. SetCompleteStat();
  358. VERIFY( SetDlgItemText( IDC_STATUS, L"" ) );
  359. SetWizardButtons( PSWIZB_NEXT );
  360. }
  361. return 0;
  362. }