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.

2739 lines
72 KiB

  1. /************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. bitsext.cpp
  5. Abstract :
  6. Main snapin code.
  7. Author :
  8. Revision History :
  9. ***********************************************************************/
  10. #include "precomp.h"
  11. bool CPropSheetExtension::s_bStaticInitialized = false;
  12. UINT CPropSheetExtension::s_cfDisplayName;
  13. UINT CPropSheetExtension::s_cfSnapInCLSID;
  14. UINT CPropSheetExtension::s_cfNodeType;
  15. UINT CPropSheetExtension::s_cfSnapInMetapath;
  16. UINT CPropSheetExtension::s_cfSnapInMachineName;
  17. const UINT CPropSheetExtension::s_MaxUploadUnits[] =
  18. {
  19. IDS_BYTES,
  20. IDS_KILOBYTES,
  21. IDS_MEGABYTES,
  22. IDS_GIGABYTES,
  23. IDS_TERABYTES
  24. };
  25. const UINT CPropSheetExtension::s_NumberOfMaxUploadUnits =
  26. sizeof(CPropSheetExtension::s_MaxUploadUnits)/
  27. sizeof(*CPropSheetExtension::s_MaxUploadUnits);
  28. const UINT64 CPropSheetExtension::s_MaxUploadUnitsScales[] =
  29. {
  30. 1,
  31. 1024,
  32. 1048576,
  33. 1073741824,
  34. 1099511627776
  35. };
  36. const UINT CPropSheetExtension::s_NumberOfMaxUploadUnitsScales =
  37. sizeof(CPropSheetExtension::s_MaxUploadUnitsScales)/
  38. sizeof(*CPropSheetExtension::s_MaxUploadUnitsScales);
  39. const UINT64 CPropSheetExtension::s_MaxUploadLimits[] =
  40. {
  41. 18446744073709551615, //bytes
  42. 18014398509481983, //kilobytes
  43. 17592186044415, //megabytes
  44. 17179869183, //gigabytes
  45. 16777215 //terabytes
  46. };
  47. const UINT CPropSheetExtension::s_NumberOfMaxUploadLimits=
  48. sizeof(CPropSheetExtension::s_MaxUploadLimits)/
  49. sizeof(*CPropSheetExtension::s_MaxUploadLimits);
  50. const UINT CPropSheetExtension::s_TimeoutUnits[] =
  51. {
  52. IDS_SECONDS,
  53. IDS_MINUTES,
  54. IDS_HOURS,
  55. IDS_DAYS
  56. };
  57. const UINT CPropSheetExtension::s_NumberOfTimeoutUnits =
  58. sizeof(CPropSheetExtension::s_TimeoutUnits)/
  59. sizeof(*CPropSheetExtension::s_TimeoutUnits);
  60. const DWORD CPropSheetExtension::s_TimeoutUnitsScales[] =
  61. {
  62. 1,
  63. 60,
  64. 60*60,
  65. 24*60*60
  66. };
  67. const UINT CPropSheetExtension::s_NumberOfTimeoutUnitsScales =
  68. sizeof(CPropSheetExtension::s_TimeoutUnitsScales)/
  69. sizeof(*CPropSheetExtension::s_TimeoutUnitsScales);
  70. const UINT64 CPropSheetExtension::s_TimeoutLimits[] =
  71. {
  72. 4294967295, // seconds
  73. 71582788, // minutes
  74. 1193046, // hours
  75. 49710 // days
  76. };
  77. const UINT CPropSheetExtension::s_NumberOfTimeoutLimits =
  78. sizeof(CPropSheetExtension::s_TimeoutLimits)/
  79. sizeof(*CPropSheetExtension::s_TimeoutLimits);
  80. const UINT CPropSheetExtension::s_NotificationTypes[] =
  81. {
  82. IDS_BYREF_POST_NOTIFICATION,
  83. IDS_BYVAL_POST_NOTIFICATION
  84. };
  85. const UINT CPropSheetExtension::s_NumberOfNotificationTypes =
  86. sizeof(CPropSheetExtension::s_NotificationTypes)/
  87. sizeof(*CPropSheetExtension::s_NotificationTypes);
  88. HRESULT CPropSheetExtension::InitializeStatic()
  89. {
  90. if ( s_bStaticInitialized )
  91. return S_OK;
  92. if ( !( s_cfDisplayName = RegisterClipboardFormat(L"CCF_DISPLAY_NAME") ) ||
  93. !( s_cfNodeType = RegisterClipboardFormat(L"CCF_NODETYPE") ) ||
  94. !( s_cfSnapInCLSID = RegisterClipboardFormat(L"CCF_SNAPIN_CLASSID") ) ||
  95. !( s_cfSnapInMetapath = RegisterClipboardFormat(L"ISM_SNAPIN_META_PATH") ) ||
  96. !( s_cfSnapInMachineName = RegisterClipboardFormat(L"ISM_SNAPIN_MACHINE_NAME") ) )
  97. return HRESULT_FROM_WIN32( GetLastError() );
  98. s_bStaticInitialized = true;
  99. return S_OK;
  100. }
  101. CPropSheetExtension::InheritedValues::InheritedValues() :
  102. MaxUploadSize(0),
  103. SessionTimeout(0),
  104. NotificationType( BITS_NOTIFICATION_TYPE_NONE ),
  105. NotificationURL( NULL ),
  106. HostId( NULL ),
  107. FallbackTimeout( 0 )
  108. {
  109. }
  110. CPropSheetExtension::InheritedValues::~InheritedValues()
  111. {
  112. delete NotificationURL;
  113. delete HostId;
  114. }
  115. CPropSheetExtension::CPropSheetExtension() :
  116. m_cref(1),
  117. m_MetabasePath( NULL ),
  118. m_MetabaseParent( NULL ),
  119. m_ComputerName( NULL ),
  120. m_UNCComputerName( NULL ),
  121. m_IISAdminBase( NULL ),
  122. m_IBITSSetup( NULL ),
  123. m_PropertyMan( NULL ),
  124. m_hwnd( NULL ),
  125. m_SettingsChanged( false ),
  126. m_EnabledSettingChanged( false ),
  127. m_CleanupInProgress( false ),
  128. m_CleanupCursor( NULL ),
  129. m_CleanupMinWaitTimerFired( false )
  130. {
  131. OBJECT_CREATED
  132. }
  133. CPropSheetExtension::~CPropSheetExtension()
  134. {
  135. CloseCleanupItems(); // Close m_TaskSched and m_CleanupTask
  136. delete m_MetabasePath;
  137. delete m_MetabaseParent;
  138. delete m_ComputerName;
  139. delete m_UNCComputerName;
  140. if ( m_IBITSSetup )
  141. m_IBITSSetup->Release();
  142. if ( m_IISAdminBase )
  143. m_IISAdminBase->Release();
  144. delete m_PropertyMan;
  145. OBJECT_DESTROYED
  146. }
  147. ///////////////////////
  148. // IUnknown implementation
  149. ///////////////////////
  150. STDMETHODIMP CPropSheetExtension::QueryInterface(REFIID riid, LPVOID *ppv)
  151. {
  152. if (!ppv)
  153. return E_FAIL;
  154. *ppv = NULL;
  155. if (IsEqualIID(riid, IID_IUnknown))
  156. *ppv = static_cast<IExtendPropertySheet *>(this);
  157. else if (IsEqualIID(riid, IID_IExtendPropertySheet))
  158. *ppv = static_cast<IExtendPropertySheet *>(this);
  159. if (*ppv)
  160. {
  161. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  162. return S_OK;
  163. }
  164. return E_NOINTERFACE;
  165. }
  166. STDMETHODIMP_(ULONG) CPropSheetExtension::AddRef()
  167. {
  168. return InterlockedIncrement((LONG *)&m_cref);
  169. }
  170. STDMETHODIMP_(ULONG) CPropSheetExtension::Release()
  171. {
  172. if (InterlockedDecrement((LONG *)&m_cref) == 0)
  173. {
  174. // we need to decrement our object count in the DLL
  175. delete this;
  176. return 0;
  177. }
  178. return m_cref;
  179. }
  180. HRESULT
  181. CPropSheetExtension::ExtractData(
  182. IDataObject* piDataObject,
  183. CLIPFORMAT cfClipFormat,
  184. BYTE* pbData,
  185. DWORD cbData )
  186. {
  187. HRESULT hr = S_OK;
  188. FORMATETC formatetc = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  189. STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL};
  190. stgmedium.hGlobal = ::GlobalAlloc(GPTR, cbData);
  191. do // false loop
  192. {
  193. if (NULL == stgmedium.hGlobal)
  194. {
  195. hr = E_OUTOFMEMORY;
  196. break;
  197. }
  198. hr = piDataObject->GetDataHere( &formatetc, &stgmedium );
  199. if ( FAILED(hr) )
  200. {
  201. break;
  202. }
  203. BYTE* pbNewData = reinterpret_cast<BYTE*>(stgmedium.hGlobal);
  204. if (NULL == pbNewData)
  205. {
  206. hr = E_UNEXPECTED;
  207. break;
  208. }
  209. ::memcpy( pbData, pbNewData, cbData );
  210. } while (FALSE); // false loop
  211. if (NULL != stgmedium.hGlobal)
  212. {
  213. ::GlobalFree(stgmedium.hGlobal);
  214. }
  215. return hr;
  216. }
  217. HRESULT
  218. CPropSheetExtension::ExtractSnapInString( IDataObject * piDataObject,
  219. WCHAR * & String,
  220. UINT Format )
  221. {
  222. if ( String )
  223. return S_OK;
  224. FORMATETC formatetc = {(CLIPFORMAT)Format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  225. STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL };
  226. WCHAR* pRetData = NULL;
  227. try
  228. {
  229. stgmedium.hGlobal = GlobalAlloc( GMEM_MOVEABLE, 0 );
  230. if ( !stgmedium.hGlobal )
  231. throw ComError( E_OUTOFMEMORY );
  232. THROW_COMERROR( piDataObject->GetDataHere(&formatetc, &stgmedium) );
  233. pRetData = (WCHAR*)GlobalLock( stgmedium.hGlobal );
  234. SIZE_T StringLength = wcslen( pRetData ) + 1;
  235. String = new WCHAR[ StringLength ];
  236. StringCchCopyW( String, StringLength, pRetData );
  237. GlobalUnlock( pRetData );
  238. pRetData = NULL;
  239. ReleaseStgMedium( &stgmedium );
  240. return S_OK;
  241. }
  242. catch( ComError Error )
  243. {
  244. if ( pRetData )
  245. GlobalUnlock( pRetData );
  246. ReleaseStgMedium( &stgmedium );
  247. return Error.m_Hr;
  248. }
  249. }
  250. HRESULT
  251. CPropSheetExtension::ExtractSnapInGUID(
  252. IDataObject * piDataObject,
  253. GUID & Guid,
  254. UINT Format )
  255. {
  256. HRESULT Hr = S_OK;
  257. FORMATETC formatetc = {(CLIPFORMAT)Format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  258. STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL };
  259. stgmedium.hGlobal = GlobalAlloc( GMEM_MOVEABLE, 0 );
  260. if ( !stgmedium.hGlobal )
  261. return E_OUTOFMEMORY;
  262. Hr = piDataObject->GetDataHere(&formatetc, &stgmedium);
  263. if (FAILED(Hr))
  264. {
  265. ReleaseStgMedium(&stgmedium);
  266. return Hr;
  267. }
  268. GUID * pRetData = (GUID*)GlobalLock( stgmedium.hGlobal );
  269. Guid = *pRetData;
  270. GlobalUnlock( pRetData );
  271. ReleaseStgMedium( &stgmedium );
  272. return S_OK;
  273. }
  274. void
  275. CPropSheetExtension::AddComboBoxItems(
  276. UINT Combo,
  277. const UINT *Items,
  278. UINT NumberOfItems )
  279. {
  280. HWND hwndBox = GetDlgItem( m_hwnd, Combo );
  281. SendMessage( hwndBox, CB_RESETCONTENT, 0, 0 );
  282. for( unsigned int i = 0; i < NumberOfItems; i++ )
  283. {
  284. WCHAR ItemText[MAX_PATH];
  285. LoadString( g_hinst, Items[i], ItemText, MAX_PATH-1 );
  286. SendMessage( hwndBox, CB_ADDSTRING, 0, (LPARAM)ItemText );
  287. }
  288. }
  289. void
  290. CPropSheetExtension::UpdateMaxUploadGroupState(
  291. bool IsEnabled )
  292. {
  293. EnableWindow( GetDlgItem( m_hwnd, IDC_CHECK_LIMIT_MAX_UPLOAD ), IsEnabled );
  294. bool SubgroupEnabled = IsEnabled && ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_LIMIT_MAX_UPLOAD ) );
  295. EnableWindow( GetDlgItem( m_hwnd, IDC_EDIT_MAX_UPLOAD ), SubgroupEnabled );
  296. EnableWindow( GetDlgItem( m_hwnd, IDC_COMBO_MAX_UPLOAD_UNITS ), SubgroupEnabled );
  297. }
  298. void
  299. CPropSheetExtension::UpdateTimeoutGroupState(
  300. bool IsEnabled )
  301. {
  302. EnableWindow( GetDlgItem( m_hwnd, IDC_DELETE_FILES ), IsEnabled );
  303. bool SubgroupEnabled = IsEnabled && ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_DELETE_FILES ) );
  304. EnableWindow( GetDlgItem( m_hwnd, IDC_EDIT_SESSION_TIMEOUT ), SubgroupEnabled );
  305. EnableWindow( GetDlgItem( m_hwnd, IDC_COMBO_SESSION_TIMEOUT_UNITS ), SubgroupEnabled );
  306. }
  307. void
  308. CPropSheetExtension::UpdateNotificationsGroupState(
  309. bool IsEnabled )
  310. {
  311. EnableWindow( GetDlgItem( m_hwnd, IDC_CHECK_ENABLE_NOTIFICATIONS ), IsEnabled );
  312. bool SubgroupEnabled = IsEnabled && ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_ENABLE_NOTIFICATIONS ) );
  313. EnableWindow( GetDlgItem( m_hwnd, IDC_STATIC_NOTIFICATION_TYPE ), SubgroupEnabled );
  314. EnableWindow( GetDlgItem( m_hwnd, IDC_COMBO_NOTIFICATION_TYPE ), SubgroupEnabled );
  315. EnableWindow( GetDlgItem( m_hwnd, IDC_STATIC_NOTIFICATION_URL ), SubgroupEnabled );
  316. EnableWindow( GetDlgItem( m_hwnd, IDC_EDIT_NOTIFICATION_URL ), SubgroupEnabled );
  317. }
  318. void
  319. CPropSheetExtension::UpdateServerFarmFallbackGroupState(
  320. bool IsEnabled )
  321. {
  322. EnableWindow( GetDlgItem( m_hwnd, IDC_CHECK_FALLBACK_TIMEOUT ), IsEnabled );
  323. bool SubgroupEnabled = IsEnabled && ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_FALLBACK_TIMEOUT ) );
  324. EnableWindow( GetDlgItem( m_hwnd, IDC_EDIT_FALLBACK_TIMEOUT ), SubgroupEnabled );
  325. EnableWindow( GetDlgItem( m_hwnd, IDC_COMBO_FALLBACK_TIMEOUT_UNITS ), SubgroupEnabled );
  326. }
  327. void
  328. CPropSheetExtension::UpdateServerFarmGroupState(
  329. bool IsEnabled )
  330. {
  331. EnableWindow( GetDlgItem( m_hwnd, IDC_ENABLE_SERVER_FARM ), IsEnabled );
  332. bool SubgroupEnabled = IsEnabled && ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_ENABLE_SERVER_FARM ) );
  333. EnableWindow( GetDlgItem( m_hwnd, IDC_STATIC_RECONNECT ), SubgroupEnabled );
  334. EnableWindow( GetDlgItem( m_hwnd, IDC_EDIT_HOSTID ), SubgroupEnabled );
  335. UpdateServerFarmFallbackGroupState( SubgroupEnabled );
  336. }
  337. void
  338. CPropSheetExtension::UpdateConfigGroupState(
  339. bool IsEnabled )
  340. {
  341. EnableWindow( GetDlgItem( m_hwnd, IDC_RADIO_USE_INHERITED_CONFIG ), IsEnabled );
  342. EnableWindow( GetDlgItem( m_hwnd, IDC_RADIO_USE_CUSTOM_CONFIG ), IsEnabled );
  343. bool UseCustomConfig = false;
  344. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_RADIO_USE_CUSTOM_CONFIG ) )
  345. UseCustomConfig = true;
  346. bool SubgroupEnabled = IsEnabled && UseCustomConfig;
  347. EnableWindow( GetDlgItem( m_hwnd, IDC_STATIC_CUSTOM_CONFIG ), SubgroupEnabled );
  348. UpdateMaxUploadGroupState( SubgroupEnabled );
  349. UpdateTimeoutGroupState( SubgroupEnabled );
  350. UpdateServerFarmGroupState( SubgroupEnabled );
  351. UpdateNotificationsGroupState( SubgroupEnabled );
  352. }
  353. void
  354. CPropSheetExtension::UpdateUploadGroupState()
  355. {
  356. EnableWindow( GetDlgItem( m_hwnd, IDC_CHECK_BITS_UPLOAD ), true );
  357. bool IsUploadEnabled = ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_BITS_UPLOAD ) );
  358. UpdateConfigGroupState( IsUploadEnabled );
  359. }
  360. void
  361. CPropSheetExtension::UpdateCleanupState()
  362. {
  363. bool IsEnabled = ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_BITS_UPLOAD ) );
  364. HRESULT Hr;
  365. if ( IsEnabled )
  366. {
  367. if ( !m_TaskSched.Get() )
  368. {
  369. try
  370. {
  371. ConnectToTaskScheduler( m_UNCComputerName, &m_TaskSched );
  372. }
  373. catch( ComError Error)
  374. {
  375. Hr = Error.m_Hr;
  376. DisplayError( IDS_CANT_CONNECT_TO_TASKSCHED, Hr );
  377. IsEnabled = false;
  378. goto setstate;
  379. }
  380. }
  381. if ( !m_CleanupTask.Get() )
  382. {
  383. WCHAR KeyPath[ 255 ];
  384. DWORD BufferDataLength;
  385. METADATA_RECORD mdr;
  386. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  387. mdr.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  388. mdr.dwMDUserType = ALL_METADATA;
  389. mdr.dwMDDataType = STRING_METADATA;
  390. mdr.pbMDData = (PBYTE)KeyPath;
  391. mdr.dwMDDataLen = sizeof(KeyPath);
  392. mdr.dwMDDataTag = 0;
  393. Hr = m_IISAdminBase->GetData(
  394. METADATA_MASTER_ROOT_HANDLE,
  395. m_MetabasePath,
  396. &mdr,
  397. &BufferDataLength );
  398. if ( FAILED( Hr ) )
  399. {
  400. DisplayError( IDS_CANT_CONNECT_TO_TASKSCHED, Hr );
  401. IsEnabled = false;
  402. goto setstate;
  403. }
  404. try
  405. {
  406. FindWorkItemForVDIR(
  407. m_TaskSched,
  408. KeyPath,
  409. &m_CleanupTask,
  410. NULL );
  411. }
  412. catch( ComError Error )
  413. {
  414. DisplayError( IDS_CANT_CONNECT_TO_TASKSCHED, Hr );
  415. IsEnabled = false;
  416. goto setstate;
  417. }
  418. }
  419. }
  420. setstate:
  421. if ( !IsEnabled )
  422. CloseCleanupItems();
  423. EnableWindow( GetDlgItem( m_hwnd, IDC_BUTTON_SCHEDULE_CLEANUP ), IsEnabled );
  424. EnableWindow( GetDlgItem( m_hwnd, IDC_BUTTON_CLEANUP_NOW ), IsEnabled );
  425. }
  426. void
  427. CPropSheetExtension::CloseCleanupItems()
  428. {
  429. m_TaskSched.Clear();
  430. m_CleanupTask.Clear();
  431. }
  432. void
  433. CPropSheetExtension::ScheduleCleanup()
  434. {
  435. //
  436. // Since the task scheduler caches most of the information,
  437. // its necessary to close the task item and reopen it to refresh it.
  438. // Do that now.
  439. //
  440. if ( m_CleanupTask.Get() )
  441. {
  442. m_CleanupTask.Clear();
  443. UpdateCleanupState();
  444. }
  445. if ( !m_CleanupTask.Get() )
  446. return;
  447. HRESULT Hr;
  448. IProvideTaskPage *PropTaskPage = NULL;
  449. const int NumberOfPages = 2;
  450. TASKPAGE PageTypes[2] = { TASKPAGE_SCHEDULE, TASKPAGE_SETTINGS };
  451. HPROPSHEETPAGE Pages[2] = { NULL, NULL };
  452. Hr = m_CleanupTask->QueryInterface(
  453. __uuidof(*PropTaskPage),
  454. (void **)&PropTaskPage );
  455. if ( FAILED( Hr ) )
  456. goto error;
  457. for( int i = 0; i < NumberOfPages; i++ )
  458. {
  459. Hr = PropTaskPage->GetPage( PageTypes[i], TRUE, Pages + i );
  460. if ( FAILED( Hr ) )
  461. goto error;
  462. }
  463. PropTaskPage->Release();
  464. PropTaskPage = NULL;
  465. //
  466. // Build TITLE for property page.
  467. //
  468. WCHAR TitleFormat[ MAX_PATH ];
  469. WCHAR Title[ METADATA_MAX_NAME_LEN + MAX_PATH ];
  470. const WCHAR *VDirName;
  471. // Find last component of the metabase path.
  472. // It should be the virtual directory name.
  473. for ( VDirName = m_MetabasePath + wcslen( m_MetabasePath );
  474. VDirName != m_MetabasePath && L'/' != *VDirName && L'\\' != *VDirName;
  475. VDirName-- );
  476. if ( VDirName != m_MetabasePath )
  477. VDirName++;
  478. LoadString( g_hinst, IDS_WORK_ITEM_PROPERTY_PAGE_TITLE, TitleFormat, MAX_PATH-1 );
  479. DWORD FormatResult =
  480. FormatMessage(
  481. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  482. (LPCVOID)TitleFormat,
  483. 0,
  484. 0,
  485. (LPTSTR)Title,
  486. ( sizeof(Title) / sizeof(*Title) ) - 1,
  487. (va_list*)&VDirName );
  488. if ( !FormatResult )
  489. {
  490. Hr = HRESULT_FROM_WIN32( GetLastError() );
  491. goto error;
  492. }
  493. PROPSHEETHEADER psh;
  494. memset( &psh, 0, sizeof( psh ) );
  495. psh.dwSize = sizeof(PROPSHEETHEADER);
  496. psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW;
  497. psh.phpage = Pages;
  498. psh.nPages = NumberOfPages;
  499. psh.hwndParent = GetParent( m_hwnd );
  500. psh.pszCaption = Title;
  501. INT_PTR Result = PropertySheet(&psh);
  502. if ( -1 == Result )
  503. {
  504. Hr = HRESULT_FROM_WIN32( GetLastError() );
  505. goto error;
  506. }
  507. return;
  508. error:
  509. for( int i = 0; i < NumberOfPages; i++ )
  510. {
  511. DestroyPropertySheetPage( Pages[i] );
  512. }
  513. if ( PropTaskPage )
  514. PropTaskPage->Release();
  515. DisplayError( IDS_CANT_START_CLEANUP_SCHEDULE, Hr );
  516. return;
  517. }
  518. void
  519. CPropSheetExtension::CleanupNow()
  520. {
  521. HRESULT Hr;
  522. HRESULT Status;
  523. if (m_CleanupInProgress)
  524. {
  525. return;
  526. }
  527. //
  528. // Get the current status for the cleanup task.
  529. //
  530. Hr = m_CleanupTask->GetStatus( &Status );
  531. if (FAILED(Hr))
  532. {
  533. goto error;
  534. }
  535. //
  536. // See how recently the cleanup task has run.
  537. //
  538. SYSTEMTIME MostRecentRunTime;
  539. memset(&MostRecentRunTime,0,sizeof(MostRecentRunTime));
  540. Hr = m_CleanupTask->GetMostRecentRunTime( &MostRecentRunTime );
  541. if ( FAILED(Hr) )
  542. {
  543. goto error;
  544. }
  545. if (Hr == SCHED_S_TASK_HAS_NOT_RUN)
  546. {
  547. // Job Has never been run
  548. memset( &m_PrevCleanupStartTime, 0, sizeof(m_PrevCleanupStartTime) );
  549. }
  550. else
  551. {
  552. if ( !SystemTimeToFileTime( &MostRecentRunTime, &m_PrevCleanupStartTime ) )
  553. {
  554. Hr = HRESULT_FROM_WIN32( GetLastError() );
  555. goto error;
  556. }
  557. }
  558. if (Status != SCHED_S_TASK_RUNNING)
  559. {
  560. Hr = m_CleanupTask->Run();
  561. if ( FAILED(Hr) )
  562. {
  563. goto error;
  564. }
  565. }
  566. m_CleanupMinWaitTimerFired = false;
  567. if ( !SetTimer(m_hwnd, s_CleanupMinWaitTimerID, s_CleanupMinWaitTimerInterval, NULL) )
  568. {
  569. Hr = HRESULT_FROM_WIN32( GetLastError() );
  570. goto error;
  571. }
  572. if ( !SetTimer(m_hwnd, s_CleanupPollTimerID, s_CleanupMinWaitTimerInterval, NULL) )
  573. {
  574. Hr = HRESULT_FROM_WIN32( GetLastError() );
  575. goto error;
  576. }
  577. m_CleanupInProgress = true;
  578. m_CleanupCursor = LoadCursor( NULL, (LPWSTR)IDC_WAIT );
  579. SetCursor( m_CleanupCursor );
  580. return;
  581. error:
  582. KillTimer( m_hwnd, s_CleanupMinWaitTimerID );
  583. KillTimer( m_hwnd, s_CleanupPollTimerID );
  584. SetCursor( (HCURSOR)GetClassLongPtr( m_hwnd, GCLP_HCURSOR ) );
  585. DisplayError( IDS_CANT_START_CLEANUP, Hr );
  586. }
  587. void
  588. CPropSheetExtension::CleanupTimer( UINT TimerID )
  589. {
  590. HRESULT Hr;
  591. if ( s_CleanupMinWaitTimerID != TimerID &&
  592. s_CleanupPollTimerID != TimerID )
  593. {
  594. return;
  595. }
  596. if ( s_CleanupMinWaitTimerID )
  597. {
  598. m_CleanupMinWaitTimerFired = true;
  599. KillTimer( m_hwnd, s_CleanupMinWaitTimerID );
  600. }
  601. if ( !m_CleanupMinWaitTimerFired )
  602. {
  603. return; // keep cursor active for minimum time period
  604. }
  605. //
  606. // Since the task scheduler caches most of the information,
  607. // its necessary to close the task item and reopen it to refresh it.
  608. // Do that now.
  609. //
  610. if ( m_CleanupTask.Get() )
  611. {
  612. m_CleanupTask.Clear();
  613. UpdateCleanupState();
  614. }
  615. if ( !m_CleanupTask.Get() )
  616. {
  617. // shut down the polling
  618. KillTimer( m_hwnd, s_CleanupPollTimerID );
  619. SetCursor( (HCURSOR)GetClassLongPtr( m_hwnd, GCLP_HCURSOR ) );
  620. m_CleanupInProgress = false;
  621. return;
  622. }
  623. HRESULT Status;
  624. if ( FAILED( m_CleanupTask->GetStatus( &Status ) ) )
  625. {
  626. return;
  627. }
  628. if ( Status == SCHED_S_TASK_RUNNING )
  629. {
  630. return; // Not done yet, keep checking
  631. }
  632. DWORD ExitCode;
  633. Hr = m_CleanupTask->GetExitCode( &ExitCode );
  634. if ( Hr == SCHED_S_TASK_HAS_NOT_RUN )
  635. {
  636. return; // The task probably hasn't run yet
  637. }
  638. if ( FAILED(Hr) )
  639. {
  640. // If this API fails it returns the error
  641. // that MSTASK received when starting the job.
  642. KillTimer( m_hwnd, s_CleanupPollTimerID );
  643. SetCursor( (HCURSOR)GetClassLongPtr( m_hwnd, GCLP_HCURSOR ) );
  644. m_CleanupInProgress = false;
  645. DisplayError( IDS_CANT_START_CLEANUP, Hr );
  646. return;
  647. }
  648. SYSTEMTIME MostRecentRunTime;
  649. if ( FAILED( m_CleanupTask->GetMostRecentRunTime( &MostRecentRunTime ) ) )
  650. return;
  651. FILETIME MostRecentRunTimeAsFileTime;
  652. if ( !SystemTimeToFileTime(&MostRecentRunTime, &MostRecentRunTimeAsFileTime ) )
  653. return;
  654. if ( CompareFileTime( &MostRecentRunTimeAsFileTime, &m_PrevCleanupStartTime ) < 0 )
  655. return; // task may not have scheduled yet, keep checking
  656. //
  657. // At this point we know the following:
  658. // 1. The cursor was help in the wait state for the minimum time
  659. // 2. The task is not running
  660. // 3. The task started sometime after our time mark
  661. //
  662. // So, cleanup timers and revert back to the original icon
  663. //
  664. KillTimer( m_hwnd, s_CleanupPollTimerID );
  665. SetCursor( (HCURSOR)GetClassLongPtr( m_hwnd, GCLP_HCURSOR ) );
  666. m_CleanupInProgress = false;
  667. }
  668. bool
  669. CPropSheetExtension::DisplayWarning(
  670. UINT StringId )
  671. {
  672. WCHAR ErrorString[ MAX_PATH * 2 ];
  673. WCHAR BITSSettings[ MAX_PATH ];
  674. LoadString( g_hinst, StringId, ErrorString, MAX_PATH*2-1 );
  675. LoadString( g_hinst, IDS_BITS_EXT, BITSSettings, MAX_PATH-1 );
  676. return ( IDOK == MessageBox( m_hwnd, ErrorString, BITSSettings, MB_OKCANCEL | MB_ICONWARNING ) );
  677. }
  678. void
  679. CPropSheetExtension::DisplayError(
  680. UINT StringId )
  681. {
  682. WCHAR ErrorString[ MAX_PATH * 2 ];
  683. WCHAR BITSSettings[ MAX_PATH ];
  684. LoadString( g_hinst, StringId, ErrorString, MAX_PATH*2-1 );
  685. LoadString( g_hinst, IDS_BITS_EXT, BITSSettings, MAX_PATH-1 );
  686. MessageBox( m_hwnd, ErrorString, BITSSettings, MB_OK | MB_ICONWARNING ) ;
  687. }
  688. void
  689. CPropSheetExtension::DisplayError(
  690. UINT StringId,
  691. HRESULT Hr )
  692. {
  693. WCHAR ErrorString[ MAX_PATH * 2 ];
  694. WCHAR BITSSettings[ MAX_PATH ];
  695. LoadString( g_hinst, StringId, ErrorString, MAX_PATH*2-1 );
  696. LoadString( g_hinst, IDS_BITS_EXT, BITSSettings, MAX_PATH-1 );
  697. WCHAR * SystemMessage = NULL;
  698. DWORD ReturnValue =
  699. FormatMessage(
  700. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  701. FORMAT_MESSAGE_FROM_SYSTEM |
  702. FORMAT_MESSAGE_IGNORE_INSERTS,
  703. NULL,
  704. (DWORD)Hr,
  705. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  706. (LPTSTR) &SystemMessage,
  707. 0,
  708. NULL
  709. );
  710. if ( !ReturnValue )
  711. MessageBox( m_hwnd, ErrorString, BITSSettings, MB_OK | MB_ICONWARNING );
  712. else
  713. {
  714. WCHAR CombinedErrorString[ MAX_PATH * 4 ];
  715. StringCchPrintfW(
  716. CombinedErrorString,
  717. ARRAY_ELEMENTS( CombinedErrorString ),
  718. L"%s\r\n\r\n%s",
  719. ErrorString,
  720. SystemMessage );
  721. MessageBox( m_hwnd, CombinedErrorString, BITSSettings, MB_OK | MB_ICONWARNING );
  722. LocalFree( SystemMessage );
  723. }
  724. }
  725. bool
  726. CPropSheetExtension::GetDlgItemTextAsInteger(
  727. UINT Id,
  728. UINT MaxString,
  729. UINT64 & Value )
  730. {
  731. WCHAR *DlgString = NULL;
  732. WCHAR *FoldedBuffer = NULL;
  733. WCHAR *p = NULL;
  734. Value = 0;
  735. try
  736. {
  737. DlgString = new WCHAR[ MaxString + 1 ];
  738. GetDlgItemText( m_hwnd, Id, DlgString, MaxString );
  739. if ( L'\0' == *DlgString )
  740. throw ComError( E_FAIL );;
  741. int CharsRequired =
  742. FoldString(
  743. MAP_FOLDDIGITS,
  744. DlgString,
  745. -1,
  746. NULL,
  747. 0 );
  748. if ( !CharsRequired )
  749. throw ComError( E_FAIL );
  750. FoldedBuffer = new WCHAR[ CharsRequired + 1 ];
  751. CharsRequired =
  752. FoldString(
  753. MAP_FOLDDIGITS,
  754. DlgString,
  755. -1,
  756. FoldedBuffer,
  757. CharsRequired );
  758. if ( !CharsRequired )
  759. ComError( E_FAIL );
  760. p = FoldedBuffer;
  761. // accumulate value
  762. while(L'\0' != *p )
  763. {
  764. UINT64 ExtendedValue = Value * 10;
  765. if ( ExtendedValue / 10 != Value )
  766. throw ComError( E_FAIL );
  767. Value = ExtendedValue;
  768. if ( *p < L'0' || *p > L'9' )
  769. throw ComError( E_FAIL );
  770. UINT64 ValueToAdd = *p - L'0';
  771. if ( 0xFFFFFFFFFFFFFFFF - ValueToAdd < Value )
  772. throw ComError( E_FAIL ); //overflow
  773. Value += ValueToAdd;
  774. p++;
  775. }
  776. delete[] DlgString;
  777. delete[] FoldedBuffer;
  778. return true;
  779. }
  780. catch( ComError Error )
  781. {
  782. delete[] DlgString;
  783. delete[] p;
  784. return false;
  785. }
  786. }
  787. void
  788. CPropSheetExtension::SetDlgItemTextAsInteger(
  789. UINT Id,
  790. UINT64 Value )
  791. {
  792. WCHAR RawString[ 25 ]; // 18446744073709551615
  793. WCHAR *p = RawString + 25 - 1;
  794. *p-- = L'\0';
  795. if ( !Value )
  796. {
  797. *p = L'0';
  798. }
  799. else
  800. {
  801. do
  802. {
  803. UINT64 Remainder = Value % 10;
  804. Value = Value / 10;
  805. *p-- = ( L'0' + (WCHAR)Remainder );
  806. } while( Value );
  807. p++;
  808. }
  809. NUMBERFMT Format;
  810. memset( &Format, 0, sizeof(Format) );
  811. Format.lpDecimalSep = L"";
  812. Format.lpThousandSep = L"";
  813. int CharsRequired =
  814. GetNumberFormat(
  815. NULL,
  816. 0,
  817. p,
  818. &Format,
  819. NULL,
  820. 0 );
  821. if ( !CharsRequired )
  822. return;
  823. WCHAR *ConvertedString = NULL;
  824. try
  825. {
  826. ConvertedString = new WCHAR[ CharsRequired ];
  827. }
  828. catch( ComError Error )
  829. {
  830. return;
  831. }
  832. CharsRequired =
  833. GetNumberFormat(
  834. NULL,
  835. 0,
  836. p,
  837. &Format,
  838. ConvertedString,
  839. CharsRequired );
  840. if ( CharsRequired )
  841. SetDlgItemText( m_hwnd, Id, ConvertedString );
  842. delete[] ConvertedString;
  843. }
  844. bool
  845. CPropSheetExtension::ValidateValues( )
  846. {
  847. // Validate the maximum upload
  848. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_LIMIT_MAX_UPLOAD ) )
  849. {
  850. LRESULT MaxUploadUnit = SendDlgItemMessage( m_hwnd, IDC_COMBO_MAX_UPLOAD_UNITS, CB_GETCURSEL, 0, 0 );
  851. UINT64 MaxUpload;
  852. if (!GetDlgItemTextAsInteger( IDC_EDIT_MAX_UPLOAD, MAX_PATH, MaxUpload ) ||
  853. MaxUpload > s_MaxUploadLimits[MaxUploadUnit] )
  854. {
  855. DisplayError( IDS_MAX_UPLOAD_INVALID );
  856. return false;
  857. }
  858. }
  859. // Validate the session timeout
  860. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_DELETE_FILES ) )
  861. {
  862. LRESULT SessionTimeoutUnit =
  863. SendDlgItemMessage( m_hwnd, IDC_COMBO_SESSION_TIMEOUT_UNITS, CB_GETCURSEL, 0, 0 );
  864. UINT64 SessionTimeout;
  865. if ( !GetDlgItemTextAsInteger( IDC_EDIT_SESSION_TIMEOUT, MAX_PATH, SessionTimeout ) ||
  866. SessionTimeout > s_TimeoutLimits[SessionTimeoutUnit] )
  867. {
  868. DisplayError( IDS_SESSION_TIMEOUT_INVALID );
  869. return false;
  870. }
  871. }
  872. // Validate the server farm settings
  873. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_ENABLE_SERVER_FARM ) )
  874. {
  875. LRESULT HostIdLength =
  876. SendDlgItemMessage( m_hwnd, IDC_EDIT_HOSTID, WM_GETTEXTLENGTH, 0, 0 );
  877. if ( !HostIdLength )
  878. {
  879. DisplayError( IDS_HOST_ID_INVALID );
  880. return false;
  881. }
  882. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_FALLBACK_TIMEOUT ) )
  883. {
  884. LRESULT FallbackTimeoutUnit =
  885. SendDlgItemMessage( m_hwnd, IDC_COMBO_FALLBACK_TIMEOUT_UNITS, CB_GETCURSEL, 0, 0 );
  886. UINT64 FallbackTimeout;
  887. if ( !GetDlgItemTextAsInteger( IDC_EDIT_FALLBACK_TIMEOUT, MAX_PATH, FallbackTimeout ) ||
  888. FallbackTimeout > s_TimeoutLimits[ FallbackTimeoutUnit ] )
  889. {
  890. DisplayError( IDS_FALLBACK_TIMEOUT_INVALID );
  891. return false;
  892. }
  893. }
  894. }
  895. // Validate the notification settings
  896. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_ENABLE_NOTIFICATIONS ) )
  897. {
  898. LRESULT NotificationURLLength =
  899. SendDlgItemMessage( m_hwnd, IDC_EDIT_NOTIFICATION_URL, WM_GETTEXTLENGTH, 0, 0 );
  900. if ( !NotificationURLLength )
  901. {
  902. DisplayError( IDS_NOTIFICATION_URL_INVALID );
  903. return false;
  904. }
  905. }
  906. return WarnAboutAccessFlags();
  907. }
  908. bool
  909. CPropSheetExtension::WarnAboutAccessFlags()
  910. {
  911. if ( m_EnabledSettingChanged &&
  912. ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_BITS_UPLOAD ) ) )
  913. {
  914. HRESULT Hr = S_OK;
  915. DWORD BufferRequired = 0;
  916. DWORD AccessFlags = 0;
  917. METADATA_RECORD mdr;
  918. mdr.dwMDIdentifier = MD_ACCESS_PERM;
  919. mdr.dwMDAttributes = METADATA_INHERIT;
  920. mdr.dwMDUserType = ALL_METADATA;
  921. mdr.dwMDDataType = DWORD_METADATA;
  922. mdr.pbMDData = (unsigned char*)&AccessFlags;
  923. mdr.dwMDDataLen = sizeof( AccessFlags );
  924. mdr.dwMDDataTag = 0;
  925. Hr = m_IISAdminBase->GetData(
  926. METADATA_MASTER_ROOT_HANDLE,
  927. m_MetabasePath,
  928. &mdr,
  929. &BufferRequired );
  930. if ( FAILED( Hr ) )
  931. {
  932. DisplayError( IDS_CANT_ACCESS_METABASE, Hr );
  933. return false;
  934. }
  935. if ( AccessFlags & ( MD_ACCESS_EXECUTE | MD_ACCESS_SCRIPT ) )
  936. {
  937. return DisplayWarning( IDS_ACCESS_PERMISSION_WARNING );
  938. }
  939. }
  940. return true;
  941. }
  942. HRESULT
  943. CPropSheetExtension::LoadInheritedDWORD(
  944. METADATA_HANDLE mdHandle,
  945. WCHAR * pKeyName,
  946. DWORD PropId,
  947. DWORD * pReturn )
  948. {
  949. METADATA_RECORD mdr;
  950. DWORD BufferRequired;
  951. HRESULT Hr;
  952. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( PropId );
  953. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_PARTIAL_PATH;
  954. mdr.dwMDUserType = ALL_METADATA;
  955. mdr.dwMDDataType = DWORD_METADATA;
  956. mdr.pbMDData = (PBYTE)pReturn;
  957. mdr.dwMDDataLen = sizeof(*pReturn);
  958. mdr.dwMDDataTag = 0;
  959. Hr = m_IISAdminBase->GetData(
  960. mdHandle,
  961. pKeyName,
  962. &mdr,
  963. &BufferRequired );
  964. return Hr;
  965. }
  966. HRESULT
  967. CPropSheetExtension::LoadInheritedString(
  968. METADATA_HANDLE mdHandle,
  969. WCHAR * pKeyName,
  970. DWORD PropId,
  971. WCHAR ** pReturn )
  972. {
  973. *pReturn = NULL;
  974. METADATA_RECORD mdr;
  975. DWORD BufferRequired;
  976. HRESULT Hr;
  977. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( PropId );
  978. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_PARTIAL_PATH;
  979. mdr.dwMDUserType = ALL_METADATA;
  980. mdr.dwMDDataType = STRING_METADATA;
  981. mdr.pbMDData = (PBYTE)NULL;
  982. mdr.dwMDDataLen = 0;
  983. mdr.dwMDDataTag = 0;
  984. Hr = m_IISAdminBase->GetData(
  985. mdHandle,
  986. pKeyName,
  987. &mdr,
  988. &BufferRequired );
  989. if ( FAILED( Hr ) && HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr )
  990. return Hr;
  991. try
  992. {
  993. *pReturn = new WCHAR[ BufferRequired ];
  994. }
  995. catch( ComError Error )
  996. {
  997. Error.m_Hr;
  998. }
  999. mdr.dwMDDataLen = BufferRequired;
  1000. mdr.pbMDData = (BYTE*)*pReturn;
  1001. Hr = m_IISAdminBase->GetData(
  1002. mdHandle,
  1003. pKeyName,
  1004. &mdr,
  1005. &BufferRequired );
  1006. if ( FAILED( Hr ) )
  1007. {
  1008. delete *pReturn;
  1009. *pReturn = NULL;
  1010. return Hr;
  1011. }
  1012. return Hr;
  1013. }
  1014. void
  1015. CPropSheetExtension::LoadInheritedValues()
  1016. {
  1017. HRESULT Hr;
  1018. METADATA_RECORD mdr;
  1019. METADATA_HANDLE mdHandle = NULL;
  1020. DWORD BufferRequired;
  1021. m_InheritedValues.NotificationURL = NULL;
  1022. m_InheritedValues.HostId = NULL;
  1023. //
  1024. // A huge trick is used here to obtain the inherited properties.
  1025. // The idea is to take a key which probably doesn't exit at the same
  1026. // level as the key for the virtual directory. A guid looks
  1027. // like a good key name to use that probably doesn't exist.
  1028. //
  1029. GUID guid;
  1030. WCHAR unusedkey[50];
  1031. CoCreateGuid( &guid );
  1032. StringFromGUID2( guid, unusedkey, 49 );
  1033. Hr = m_IISAdminBase->OpenKey(
  1034. METADATA_MASTER_ROOT_HANDLE,
  1035. m_MetabaseParent,
  1036. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1037. METABASE_OPEN_KEY_TIMEOUT,
  1038. &mdHandle );
  1039. if ( FAILED( Hr ) )
  1040. goto error;
  1041. // Load the maximum upload size
  1042. {
  1043. WCHAR *MaximumUploadSize = NULL;
  1044. if ( FAILED(
  1045. Hr = LoadInheritedString(
  1046. mdHandle,
  1047. unusedkey,
  1048. MD_BITS_MAX_FILESIZE,
  1049. &MaximumUploadSize ) ) )
  1050. goto error;
  1051. if ( wcscmp( MaximumUploadSize, MD_BITS_UNLIMITED_MAX_FILESIZE) == 0 )
  1052. m_InheritedValues.MaxUploadSize = MD_BITS_UNLIMITED_MAX_FILESIZE_AS_INT64;
  1053. else
  1054. if ( 1 != swscanf( MaximumUploadSize, L"%I64u", &m_InheritedValues.MaxUploadSize ) )
  1055. {
  1056. delete MaximumUploadSize;
  1057. MaximumUploadSize = NULL;
  1058. goto error;
  1059. }
  1060. delete MaximumUploadSize;
  1061. }
  1062. // Load the session timeout
  1063. if ( FAILED(
  1064. Hr = LoadInheritedDWORD(
  1065. mdHandle,
  1066. unusedkey,
  1067. MD_BITS_NO_PROGRESS_TIMEOUT,
  1068. &m_InheritedValues.SessionTimeout ) ) )
  1069. goto error;
  1070. // Load the notification settings
  1071. if ( FAILED(
  1072. Hr = LoadInheritedDWORD(
  1073. mdHandle,
  1074. unusedkey,
  1075. MD_BITS_NOTIFICATION_URL_TYPE,
  1076. (DWORD*)&m_InheritedValues.NotificationType ) ) )
  1077. goto error;
  1078. if ( FAILED(
  1079. Hr = LoadInheritedString(
  1080. mdHandle,
  1081. unusedkey,
  1082. MD_BITS_NOTIFICATION_URL,
  1083. &m_InheritedValues.NotificationURL ) ) )
  1084. goto error;
  1085. // Load the web farm settings
  1086. if ( FAILED(
  1087. Hr = LoadInheritedString(
  1088. mdHandle,
  1089. unusedkey,
  1090. MD_BITS_HOSTID,
  1091. &m_InheritedValues.HostId ) ) )
  1092. goto error;
  1093. if ( FAILED(
  1094. Hr = LoadInheritedDWORD(
  1095. mdHandle,
  1096. unusedkey,
  1097. MD_BITS_HOSTID_FALLBACK_TIMEOUT,
  1098. (DWORD*)&m_InheritedValues.FallbackTimeout ) ) )
  1099. goto error;
  1100. m_IISAdminBase->CloseKey( mdHandle );
  1101. mdHandle = NULL;
  1102. return;
  1103. error:
  1104. if ( mdHandle )
  1105. m_IISAdminBase->CloseKey( mdHandle );
  1106. // use default values
  1107. m_InheritedValues.MaxUploadSize = MD_DEFAULT_BITS_MAX_FILESIZE_AS_INT64;
  1108. m_InheritedValues.SessionTimeout = MD_DEFAULT_NO_PROGESS_TIMEOUT;
  1109. m_InheritedValues.NotificationType = MD_DEFAULT_BITS_NOTIFICATION_URL_TYPE;
  1110. delete m_InheritedValues.NotificationURL;
  1111. m_InheritedValues.NotificationURL = NULL;
  1112. delete m_InheritedValues.HostId;
  1113. m_InheritedValues.HostId = NULL;
  1114. DisplayError( IDS_CANT_LOAD_INHERITED_VALUES, Hr );
  1115. }
  1116. void
  1117. CPropSheetExtension::LoadMaxUploadValue( UINT64 MaxValue )
  1118. {
  1119. if ( MaxValue == MD_BITS_UNLIMITED_MAX_FILESIZE_AS_INT64 )
  1120. {
  1121. SendDlgItemMessage(m_hwnd, IDC_COMBO_MAX_UPLOAD_UNITS, CB_SETCURSEL, 0, 0 );
  1122. SetDlgItemText( m_hwnd, IDC_EDIT_MAX_UPLOAD, L"" );
  1123. CheckDlgButton( m_hwnd, IDC_CHECK_LIMIT_MAX_UPLOAD, BST_UNCHECKED );
  1124. return;
  1125. }
  1126. int Scale = s_NumberOfMaxUploadUnitsScales-1;
  1127. while ( MaxValue % s_MaxUploadUnitsScales[Scale] )
  1128. Scale--;
  1129. SendDlgItemMessage(m_hwnd, IDC_COMBO_MAX_UPLOAD_UNITS, CB_SETCURSEL, Scale, 0 );
  1130. SetDlgItemTextAsInteger( IDC_EDIT_MAX_UPLOAD, MaxValue / s_MaxUploadUnitsScales[Scale] );
  1131. CheckDlgButton( m_hwnd, IDC_CHECK_LIMIT_MAX_UPLOAD, BST_CHECKED );
  1132. }
  1133. void
  1134. CPropSheetExtension::LoadTimeoutValue(
  1135. DWORD CheckId,
  1136. DWORD EditId,
  1137. DWORD UnitId,
  1138. DWORD Value )
  1139. {
  1140. if ( MD_BITS_NO_TIMEOUT == Value )
  1141. {
  1142. SendDlgItemMessage( m_hwnd, UnitId, CB_SETCURSEL, 0, 0 );
  1143. SetDlgItemText( m_hwnd, EditId, L"");
  1144. CheckDlgButton( m_hwnd, CheckId, BST_UNCHECKED );
  1145. return;
  1146. }
  1147. int Scale = s_NumberOfTimeoutUnitsScales-1;
  1148. while ( Value % s_TimeoutUnitsScales[Scale] )
  1149. Scale--;
  1150. SendDlgItemMessage( m_hwnd, UnitId, CB_SETCURSEL, Scale, 0 );
  1151. SetDlgItemTextAsInteger( EditId,
  1152. Value / s_TimeoutUnitsScales[Scale] );
  1153. CheckDlgButton( m_hwnd, CheckId, BST_CHECKED );
  1154. }
  1155. void
  1156. CPropSheetExtension::LoadTimeoutValue( DWORD SessionTimeout )
  1157. {
  1158. LoadTimeoutValue(
  1159. IDC_DELETE_FILES, // check id
  1160. IDC_EDIT_SESSION_TIMEOUT, // edit id
  1161. IDC_COMBO_SESSION_TIMEOUT_UNITS, // unit id
  1162. SessionTimeout );
  1163. }
  1164. void
  1165. CPropSheetExtension::LoadNotificationValues(
  1166. BITS_SERVER_NOTIFICATION_TYPE NotificationType,
  1167. WCHAR *NotificationURL )
  1168. {
  1169. if ( BITS_NOTIFICATION_TYPE_NONE == NotificationType )
  1170. {
  1171. SetDlgItemText( m_hwnd, IDC_EDIT_NOTIFICATION_URL, L"" );
  1172. SendDlgItemMessage( m_hwnd, IDC_COMBO_NOTIFICATION_TYPE, CB_SETCURSEL, 0, 0 );
  1173. CheckDlgButton( m_hwnd, IDC_CHECK_ENABLE_NOTIFICATIONS, BST_UNCHECKED );
  1174. return;
  1175. }
  1176. SendDlgItemMessage( m_hwnd, IDC_COMBO_NOTIFICATION_TYPE, CB_SETCURSEL,
  1177. (WPARAM)NotificationType - BITS_NOTIFICATION_TYPE_POST_BYREF, 0 );
  1178. SetDlgItemText( m_hwnd, IDC_EDIT_NOTIFICATION_URL, NotificationURL );
  1179. CheckDlgButton( m_hwnd, IDC_CHECK_ENABLE_NOTIFICATIONS, BST_CHECKED );
  1180. }
  1181. void
  1182. CPropSheetExtension::LoadServerFarmSettings(
  1183. WCHAR *HostId,
  1184. DWORD FallbackTimeout )
  1185. {
  1186. if ( !HostId || !*HostId )
  1187. {
  1188. SetDlgItemText( m_hwnd, IDC_EDIT_HOSTID, L"" );
  1189. CheckDlgButton( m_hwnd, IDC_ENABLE_SERVER_FARM, BST_UNCHECKED );
  1190. LoadTimeoutValue(
  1191. IDC_CHECK_FALLBACK_TIMEOUT,
  1192. IDC_EDIT_FALLBACK_TIMEOUT,
  1193. IDC_COMBO_FALLBACK_TIMEOUT_UNITS,
  1194. FallbackTimeout );
  1195. return;
  1196. }
  1197. SetDlgItemText( m_hwnd, IDC_EDIT_HOSTID, HostId );
  1198. CheckDlgButton( m_hwnd, IDC_ENABLE_SERVER_FARM, BST_CHECKED );
  1199. LoadTimeoutValue(
  1200. IDC_CHECK_FALLBACK_TIMEOUT,
  1201. IDC_EDIT_FALLBACK_TIMEOUT,
  1202. IDC_COMBO_FALLBACK_TIMEOUT_UNITS,
  1203. FallbackTimeout );
  1204. }
  1205. void
  1206. CPropSheetExtension::LoadValues( )
  1207. {
  1208. HRESULT Hr = S_OK;
  1209. HRESULT LastError = S_OK;
  1210. BOOL IsBitsEnabled = FALSE;
  1211. m_SettingsChanged = m_EnabledSettingChanged = false;
  1212. try
  1213. {
  1214. IsBITSEnabledOnVDir(
  1215. m_PropertyMan,
  1216. m_IISAdminBase,
  1217. m_MetabasePath,
  1218. &IsBitsEnabled );
  1219. }
  1220. catch( ComError Error )
  1221. {
  1222. Hr = Error.m_Hr;
  1223. }
  1224. if ( IsBitsEnabled )
  1225. CheckDlgButton( m_hwnd, IDC_CHECK_BITS_UPLOAD, BST_CHECKED );
  1226. else
  1227. CheckDlgButton( m_hwnd, IDC_CHECK_BITS_UPLOAD, BST_UNCHECKED );
  1228. if ( FAILED(Hr) )
  1229. LastError = Hr;
  1230. bool AllDefaults = true;
  1231. METADATA_RECORD mdr;
  1232. DWORD BufferRequired;
  1233. // Load the maximum upload size
  1234. WCHAR MaximumUploadSize[MAX_PATH];
  1235. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_MAX_FILESIZE );
  1236. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_ISINHERITED;
  1237. mdr.dwMDUserType = ALL_METADATA;
  1238. mdr.dwMDDataType = STRING_METADATA;
  1239. mdr.pbMDData = (PBYTE)MaximumUploadSize;
  1240. mdr.dwMDDataLen = sizeof(MaximumUploadSize);
  1241. mdr.dwMDDataTag = 0;
  1242. Hr = m_IISAdminBase->GetData(
  1243. METADATA_MASTER_ROOT_HANDLE,
  1244. m_MetabasePath,
  1245. &mdr,
  1246. &BufferRequired );
  1247. if ( FAILED( Hr ) )
  1248. {
  1249. LastError = Hr;
  1250. LoadMaxUploadValue( m_InheritedValues.MaxUploadSize );
  1251. }
  1252. else
  1253. {
  1254. UINT64 MaximumUploadSizeInt;
  1255. if ( 1 != swscanf( MaximumUploadSize, L"%I64u", &MaximumUploadSizeInt ) )
  1256. {
  1257. LastError = Hr;
  1258. LoadMaxUploadValue( m_InheritedValues.MaxUploadSize );
  1259. }
  1260. else
  1261. {
  1262. if ( !( mdr.dwMDAttributes & METADATA_ISINHERITED ) )
  1263. AllDefaults = false;
  1264. LoadMaxUploadValue( MaximumUploadSizeInt );
  1265. }
  1266. }
  1267. // Load the session timeout
  1268. DWORD SessionTimeout = m_InheritedValues.SessionTimeout;
  1269. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_NO_PROGRESS_TIMEOUT );
  1270. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_ISINHERITED;
  1271. mdr.dwMDUserType = ALL_METADATA;
  1272. mdr.dwMDDataType = DWORD_METADATA;
  1273. mdr.pbMDData = (PBYTE)&SessionTimeout;
  1274. mdr.dwMDDataLen = sizeof(SessionTimeout);
  1275. mdr.dwMDDataTag = 0;
  1276. Hr = m_IISAdminBase->GetData(
  1277. METADATA_MASTER_ROOT_HANDLE,
  1278. m_MetabasePath,
  1279. &mdr,
  1280. &BufferRequired );
  1281. if ( FAILED( Hr ) )
  1282. {
  1283. LastError = Hr;
  1284. LoadTimeoutValue( m_InheritedValues.SessionTimeout );
  1285. }
  1286. else
  1287. {
  1288. if ( !( mdr.dwMDAttributes & METADATA_ISINHERITED ) )
  1289. AllDefaults = false;
  1290. LoadTimeoutValue( SessionTimeout );
  1291. }
  1292. // Load the notification settings
  1293. DWORD NotificationType;
  1294. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_NOTIFICATION_URL_TYPE );
  1295. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_ISINHERITED;
  1296. mdr.dwMDUserType = ALL_METADATA;
  1297. mdr.dwMDDataType = DWORD_METADATA;
  1298. mdr.pbMDData = (PBYTE)&NotificationType;
  1299. mdr.dwMDDataLen = sizeof(NotificationType);
  1300. mdr.dwMDDataTag = 0;
  1301. Hr = m_IISAdminBase->GetData(
  1302. METADATA_MASTER_ROOT_HANDLE,
  1303. m_MetabasePath,
  1304. &mdr,
  1305. &BufferRequired );
  1306. if ( FAILED( Hr ) )
  1307. {
  1308. LastError = Hr;
  1309. LoadNotificationValues( m_InheritedValues.NotificationType, m_InheritedValues.NotificationURL );
  1310. }
  1311. else
  1312. {
  1313. if ( !( mdr.dwMDAttributes & METADATA_ISINHERITED ) )
  1314. AllDefaults = false;
  1315. if ( BITS_NOTIFICATION_TYPE_NONE == NotificationType )
  1316. LoadNotificationValues( BITS_NOTIFICATION_TYPE_NONE, L"" );
  1317. else
  1318. {
  1319. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_NOTIFICATION_URL );
  1320. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_ISINHERITED;
  1321. mdr.dwMDUserType = ALL_METADATA;
  1322. mdr.dwMDDataType = STRING_METADATA;
  1323. mdr.pbMDData = (PBYTE)NULL;
  1324. mdr.dwMDDataLen = 0;
  1325. mdr.dwMDDataTag = 0;
  1326. Hr = m_IISAdminBase->GetData(
  1327. METADATA_MASTER_ROOT_HANDLE,
  1328. m_MetabasePath,
  1329. &mdr,
  1330. &BufferRequired );
  1331. if ( FAILED( Hr ) && HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr )
  1332. {
  1333. LastError = Hr;
  1334. LoadNotificationValues( (BITS_SERVER_NOTIFICATION_TYPE)NotificationType, L"" );
  1335. }
  1336. else
  1337. {
  1338. BYTE *URL = NULL;
  1339. try
  1340. {
  1341. URL = new BYTE[ BufferRequired ];
  1342. }
  1343. catch( ComError Error )
  1344. {
  1345. Hr = Error.m_Hr;
  1346. }
  1347. mdr.dwMDDataLen = BufferRequired;
  1348. mdr.pbMDData = URL;
  1349. if ( BufferRequired )
  1350. {
  1351. Hr = m_IISAdminBase->GetData(
  1352. METADATA_MASTER_ROOT_HANDLE,
  1353. m_MetabasePath,
  1354. &mdr,
  1355. &BufferRequired );
  1356. }
  1357. if ( FAILED( Hr ) )
  1358. {
  1359. LastError = Hr;
  1360. LoadNotificationValues( (BITS_SERVER_NOTIFICATION_TYPE)NotificationType, L"" );
  1361. }
  1362. else
  1363. {
  1364. if ( !( mdr.dwMDAttributes & METADATA_ISINHERITED ) )
  1365. AllDefaults = false;
  1366. LoadNotificationValues( (BITS_SERVER_NOTIFICATION_TYPE)NotificationType, (WCHAR*)URL );
  1367. }
  1368. delete[] URL;
  1369. }
  1370. }
  1371. }
  1372. // Load the HostId
  1373. {
  1374. WCHAR *HostIdString = m_InheritedValues.HostId;
  1375. DWORD FallbackTimeout = m_InheritedValues.FallbackTimeout;
  1376. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_HOSTID_FALLBACK_TIMEOUT );
  1377. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_ISINHERITED;
  1378. mdr.dwMDUserType = ALL_METADATA;
  1379. mdr.dwMDDataType = DWORD_METADATA;
  1380. mdr.pbMDData = (PBYTE)&FallbackTimeout;
  1381. mdr.dwMDDataLen = sizeof( FallbackTimeout );
  1382. mdr.dwMDDataTag = 0;
  1383. Hr = m_IISAdminBase->GetData(
  1384. METADATA_MASTER_ROOT_HANDLE,
  1385. m_MetabasePath,
  1386. &mdr,
  1387. &BufferRequired );
  1388. if ( FAILED( Hr ) )
  1389. FallbackTimeout = m_InheritedValues.FallbackTimeout;
  1390. else
  1391. {
  1392. if ( !( mdr.dwMDAttributes & METADATA_ISINHERITED ) )
  1393. AllDefaults = false;
  1394. }
  1395. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( MD_BITS_HOSTID );
  1396. mdr.dwMDAttributes = METADATA_INHERIT | METADATA_ISINHERITED;
  1397. mdr.dwMDUserType = ALL_METADATA;
  1398. mdr.dwMDDataType = STRING_METADATA;
  1399. mdr.pbMDData = (PBYTE)NULL;
  1400. mdr.dwMDDataLen = 0;
  1401. mdr.dwMDDataTag = 0;
  1402. Hr = m_IISAdminBase->GetData(
  1403. METADATA_MASTER_ROOT_HANDLE,
  1404. m_MetabasePath,
  1405. &mdr,
  1406. &BufferRequired );
  1407. BYTE *HostId = NULL;
  1408. if ( SUCCEEDED( Hr ) || ( Hr == HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) ) )
  1409. {
  1410. try
  1411. {
  1412. HostId = new BYTE[ BufferRequired ];
  1413. mdr.dwMDDataLen = BufferRequired;
  1414. mdr.pbMDData = HostId;
  1415. Hr = m_IISAdminBase->GetData(
  1416. METADATA_MASTER_ROOT_HANDLE,
  1417. m_MetabasePath,
  1418. &mdr,
  1419. &BufferRequired );
  1420. }
  1421. catch( ComError Error )
  1422. {
  1423. Hr = Error.m_Hr;
  1424. }
  1425. if ( SUCCEEDED( Hr ) )
  1426. {
  1427. if ( !( mdr.dwMDAttributes & METADATA_ISINHERITED ) )
  1428. AllDefaults = false;
  1429. HostIdString = (WCHAR*)HostId;
  1430. }
  1431. }
  1432. LoadServerFarmSettings( HostIdString, FallbackTimeout );
  1433. delete[] HostId;
  1434. }
  1435. CheckDlgButton( m_hwnd, IDC_CHECK_BITS_UPLOAD, IsBitsEnabled ? BST_CHECKED : BST_UNCHECKED );
  1436. CheckRadioButton( m_hwnd, IDC_RADIO_USE_INHERITED_CONFIG, IDC_RADIO_USE_CUSTOM_CONFIG,
  1437. AllDefaults ? IDC_RADIO_USE_INHERITED_CONFIG : IDC_RADIO_USE_CUSTOM_CONFIG );
  1438. UpdateUploadGroupState( );
  1439. if ( FAILED( LastError ) )
  1440. DisplayError( IDS_CANT_LOAD_VALUES, LastError );
  1441. UpdateCleanupState( );
  1442. }
  1443. HRESULT
  1444. CPropSheetExtension::SaveMetadataString(
  1445. METADATA_HANDLE mdHandle,
  1446. DWORD PropId,
  1447. WCHAR *Value )
  1448. {
  1449. METADATA_RECORD mdr;
  1450. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( PropId );
  1451. mdr.dwMDAttributes = METADATA_INHERIT;
  1452. mdr.dwMDUserType = m_PropertyMan->GetPropertyUserType( PropId );
  1453. mdr.dwMDDataType = STRING_METADATA;
  1454. mdr.pbMDData = (PBYTE)Value;
  1455. mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( Value ) + 1 );
  1456. mdr.dwMDDataTag = 0;
  1457. HRESULT Hr = m_IISAdminBase->SetData(
  1458. mdHandle,
  1459. NULL,
  1460. &mdr );
  1461. return Hr;
  1462. }
  1463. HRESULT
  1464. CPropSheetExtension::SaveMetadataDWORD(
  1465. METADATA_HANDLE mdHandle,
  1466. DWORD PropId,
  1467. DWORD Value )
  1468. {
  1469. METADATA_RECORD mdr;
  1470. mdr.dwMDIdentifier = m_PropertyMan->GetPropertyMetabaseID( PropId );
  1471. mdr.dwMDAttributes = METADATA_INHERIT;
  1472. mdr.dwMDUserType = m_PropertyMan->GetPropertyUserType( PropId );
  1473. mdr.dwMDDataType = DWORD_METADATA;
  1474. mdr.pbMDData = (PBYTE)&Value;
  1475. mdr.dwMDDataLen = sizeof(DWORD);
  1476. mdr.dwMDDataTag = 0;
  1477. HRESULT Hr = m_IISAdminBase->SetData(
  1478. mdHandle,
  1479. NULL,
  1480. &mdr );
  1481. return Hr;
  1482. }
  1483. void
  1484. CPropSheetExtension::MergeError(
  1485. HRESULT Hr,
  1486. HRESULT * LastHr )
  1487. {
  1488. if ( FAILED( Hr ) )
  1489. *LastHr = Hr;
  1490. }
  1491. HRESULT
  1492. CPropSheetExtension::SaveSimpleString(
  1493. METADATA_HANDLE mdHandle,
  1494. DWORD PropId,
  1495. DWORD EditId )
  1496. {
  1497. LRESULT StringLength =
  1498. SendDlgItemMessage( m_hwnd, EditId, WM_GETTEXTLENGTH, 0, 0 );
  1499. WCHAR *String;
  1500. try
  1501. {
  1502. String = new WCHAR[ StringLength + 1 ];
  1503. }
  1504. catch( ComError Error )
  1505. {
  1506. return Error.m_Hr;
  1507. }
  1508. GetDlgItemText( m_hwnd, EditId, String, (DWORD)(StringLength + 1));
  1509. HRESULT Hr =
  1510. SaveMetadataString(
  1511. mdHandle,
  1512. PropId,
  1513. String );
  1514. delete[] String;
  1515. return Hr;
  1516. }
  1517. HRESULT
  1518. CPropSheetExtension::SaveTimeoutValue(
  1519. METADATA_HANDLE mdHandle,
  1520. DWORD PropId,
  1521. DWORD CheckId,
  1522. DWORD EditId,
  1523. DWORD UnitId )
  1524. {
  1525. if ( BST_UNCHECKED == IsDlgButtonChecked( m_hwnd, CheckId ) )
  1526. {
  1527. return
  1528. SaveMetadataDWORD(
  1529. mdHandle,
  1530. PropId,
  1531. MD_BITS_NO_TIMEOUT );
  1532. }
  1533. LRESULT TimeoutUnitsSelect =
  1534. SendDlgItemMessage( m_hwnd, UnitId, CB_GETCURSEL, 0, 0 );
  1535. UINT64 Timeout64;
  1536. GetDlgItemTextAsInteger( EditId, MAX_PATH, Timeout64 );
  1537. Timeout64 *= s_TimeoutUnitsScales[ TimeoutUnitsSelect ];
  1538. DWORD Timeout = (DWORD)Timeout64;
  1539. return
  1540. SaveMetadataDWORD(
  1541. mdHandle,
  1542. PropId,
  1543. Timeout );
  1544. }
  1545. void
  1546. CPropSheetExtension::SetValues( )
  1547. {
  1548. HRESULT Hr;
  1549. HRESULT LastError = S_OK;
  1550. METADATA_HANDLE mdHandle = NULL;
  1551. if ( m_EnabledSettingChanged )
  1552. {
  1553. UINT BitsUploadButton = IsDlgButtonChecked( m_hwnd, IDC_CHECK_BITS_UPLOAD );
  1554. if ( BST_CHECKED == BitsUploadButton )
  1555. {
  1556. Hr = m_IBITSSetup->EnableBITSUploads();
  1557. }
  1558. else
  1559. {
  1560. Hr = m_IBITSSetup->DisableBITSUploads();
  1561. }
  1562. if ( FAILED( Hr ) )
  1563. {
  1564. LastError = Hr;
  1565. goto error;
  1566. }
  1567. }
  1568. Hr = m_IISAdminBase->OpenKey(
  1569. METADATA_MASTER_ROOT_HANDLE,
  1570. m_MetabasePath,
  1571. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1572. METABASE_OPEN_KEY_TIMEOUT,
  1573. &mdHandle );
  1574. if ( FAILED( Hr ) )
  1575. {
  1576. LastError = Hr;
  1577. goto error;
  1578. }
  1579. if ( BST_CHECKED == IsDlgButtonChecked( m_hwnd, IDC_RADIO_USE_INHERITED_CONFIG ) )
  1580. {
  1581. // delete all the configuration properties
  1582. DWORD IdsToDelete[] =
  1583. {
  1584. MD_BITS_MAX_FILESIZE,
  1585. MD_BITS_NO_PROGRESS_TIMEOUT,
  1586. MD_BITS_NOTIFICATION_URL_TYPE,
  1587. MD_BITS_NOTIFICATION_URL,
  1588. MD_BITS_HOSTID,
  1589. MD_BITS_HOSTID_FALLBACK_TIMEOUT
  1590. };
  1591. for ( DWORD i=0; i < ( sizeof(IdsToDelete) / sizeof(*IdsToDelete) ); i++ )
  1592. {
  1593. Hr = m_IISAdminBase->DeleteData(
  1594. mdHandle,
  1595. NULL,
  1596. m_PropertyMan->GetPropertyMetabaseID( IdsToDelete[i] ),
  1597. ALL_METADATA );
  1598. if ( FAILED( Hr ) && Hr != HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) &&
  1599. Hr != MD_ERROR_DATA_NOT_FOUND )
  1600. LastError = Hr;
  1601. }
  1602. }
  1603. else
  1604. {
  1605. {
  1606. // save the maximum upload size
  1607. WCHAR MaxUploadSizeString[ MAX_PATH ];
  1608. LRESULT MaxUploadUnitsSelect =
  1609. SendDlgItemMessage( m_hwnd, IDC_COMBO_MAX_UPLOAD_UNITS, CB_GETCURSEL, 0, 0 );
  1610. if ( BST_UNCHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_LIMIT_MAX_UPLOAD ) )
  1611. {
  1612. StringCchCopyW( MaxUploadSizeString, MAX_PATH, MD_BITS_UNLIMITED_MAX_FILESIZE );
  1613. }
  1614. else
  1615. {
  1616. UINT64 MaxUploadSize;
  1617. GetDlgItemTextAsInteger( IDC_EDIT_MAX_UPLOAD, MAX_PATH, MaxUploadSize );
  1618. MaxUploadSize *= s_MaxUploadUnitsScales[ MaxUploadUnitsSelect ];
  1619. StringCchPrintfW( MaxUploadSizeString, MAX_PATH, L"%I64u", MaxUploadSize );
  1620. }
  1621. MergeError(
  1622. SaveMetadataString(
  1623. mdHandle,
  1624. MD_BITS_MAX_FILESIZE,
  1625. MaxUploadSizeString ), &LastError );
  1626. }
  1627. MergeError(
  1628. SaveTimeoutValue(
  1629. mdHandle,
  1630. MD_BITS_NO_PROGRESS_TIMEOUT,
  1631. IDC_DELETE_FILES,
  1632. IDC_EDIT_SESSION_TIMEOUT,
  1633. IDC_COMBO_SESSION_TIMEOUT_UNITS ), &LastError );
  1634. // Save the notification settings
  1635. if ( BST_UNCHECKED == IsDlgButtonChecked( m_hwnd, IDC_CHECK_ENABLE_NOTIFICATIONS ) )
  1636. {
  1637. MergeError(
  1638. SaveMetadataDWORD(
  1639. mdHandle,
  1640. MD_BITS_NOTIFICATION_URL_TYPE,
  1641. BITS_NOTIFICATION_TYPE_NONE ), &LastError );
  1642. MergeError(
  1643. SaveMetadataString(
  1644. mdHandle,
  1645. MD_BITS_NOTIFICATION_URL,
  1646. L"" ), &LastError );
  1647. }
  1648. else
  1649. {
  1650. LRESULT NotificationTypeSelect =
  1651. SendDlgItemMessage( m_hwnd, IDC_COMBO_NOTIFICATION_TYPE, CB_GETCURSEL, 0, 0 );
  1652. BITS_SERVER_NOTIFICATION_TYPE NotificationType =
  1653. (BITS_SERVER_NOTIFICATION_TYPE)( NotificationTypeSelect + BITS_NOTIFICATION_TYPE_POST_BYREF );
  1654. MergeError(
  1655. SaveMetadataDWORD(
  1656. mdHandle,
  1657. MD_BITS_NOTIFICATION_URL_TYPE,
  1658. NotificationType ), &LastError );
  1659. MergeError(
  1660. SaveSimpleString(
  1661. mdHandle,
  1662. MD_BITS_NOTIFICATION_URL,
  1663. IDC_EDIT_NOTIFICATION_URL ), &LastError );
  1664. }
  1665. // Save the webfarm settings
  1666. if ( BST_UNCHECKED == IsDlgButtonChecked( m_hwnd, IDC_ENABLE_SERVER_FARM ) )
  1667. {
  1668. MergeError(
  1669. SaveMetadataString(
  1670. mdHandle,
  1671. MD_BITS_HOSTID,
  1672. L"" ), &LastError );
  1673. MergeError(
  1674. SaveMetadataDWORD(
  1675. mdHandle,
  1676. MD_BITS_HOSTID_FALLBACK_TIMEOUT,
  1677. MD_BITS_NO_TIMEOUT ), &LastError );
  1678. }
  1679. else
  1680. {
  1681. MergeError(
  1682. SaveSimpleString(
  1683. mdHandle,
  1684. MD_BITS_HOSTID,
  1685. IDC_EDIT_HOSTID ), &LastError );
  1686. MergeError(
  1687. SaveTimeoutValue(
  1688. mdHandle,
  1689. MD_BITS_HOSTID_FALLBACK_TIMEOUT,
  1690. IDC_CHECK_FALLBACK_TIMEOUT,
  1691. IDC_EDIT_FALLBACK_TIMEOUT,
  1692. IDC_COMBO_FALLBACK_TIMEOUT_UNITS ), &LastError );
  1693. }
  1694. }
  1695. error:
  1696. if ( mdHandle )
  1697. m_IISAdminBase->CloseKey( mdHandle );
  1698. mdHandle = NULL;
  1699. if ( FAILED( LastError ) )
  1700. DisplayError( IDS_CANT_SAVE_VALUES, LastError );
  1701. }
  1702. void CPropSheetExtension::DisplayHelp( )
  1703. {
  1704. WCHAR HelpTopic[MAX_PATH];
  1705. LoadString( g_hinst, IDS_HELPFILE, HelpTopic, MAX_PATH-1);
  1706. HtmlHelp( NULL,
  1707. HelpTopic,
  1708. HH_DISPLAY_TOPIC,
  1709. 0 );
  1710. }
  1711. INT_PTR CPropSheetExtension::DialogProc(
  1712. UINT uMsg, // message
  1713. WPARAM wParam, // first message parameter
  1714. LPARAM lParam // second message parameter
  1715. )
  1716. {
  1717. switch (uMsg) {
  1718. case WM_SETCURSOR:
  1719. if ( m_CleanupInProgress )
  1720. {
  1721. // set the cursor for this dialog and its children.
  1722. SetCursor( m_CleanupCursor );
  1723. SetWindowLongPtr( m_hwnd, DWLP_MSGRESULT, TRUE );
  1724. return TRUE;
  1725. }
  1726. break;
  1727. case WM_TIMER:
  1728. CleanupTimer( (UINT)wParam );
  1729. return TRUE;
  1730. case WM_INITDIALOG:
  1731. SendDlgItemMessage( m_hwnd, IDC_EDIT_SESSION_DIRECTORY, EM_LIMITTEXT, MAX_PATH-1, 0 );
  1732. AddComboBoxItems( IDC_COMBO_MAX_UPLOAD_UNITS,
  1733. &s_MaxUploadUnits[0], s_NumberOfMaxUploadUnits );
  1734. AddComboBoxItems( IDC_COMBO_SESSION_TIMEOUT_UNITS,
  1735. &s_TimeoutUnits[0], s_NumberOfTimeoutUnits );
  1736. AddComboBoxItems( IDC_COMBO_NOTIFICATION_TYPE,
  1737. &s_NotificationTypes[0], s_NumberOfNotificationTypes );
  1738. AddComboBoxItems( IDC_COMBO_FALLBACK_TIMEOUT_UNITS,
  1739. &s_TimeoutUnits[0], s_NumberOfTimeoutUnits );
  1740. LoadInheritedValues();
  1741. LoadValues( );
  1742. break;
  1743. case WM_COMMAND:
  1744. if ( HIWORD(wParam) == EN_CHANGE ||
  1745. HIWORD(wParam) == CBN_SELCHANGE )
  1746. {
  1747. m_SettingsChanged = true;
  1748. SendMessage(GetParent(m_hwnd), PSM_CHANGED, (WPARAM)m_hwnd, 0);
  1749. }
  1750. else if ( HIWORD(wParam) == BN_CLICKED )
  1751. {
  1752. WORD ButtonID = LOWORD(wParam);
  1753. if ( IDC_BUTTON_SCHEDULE_CLEANUP != ButtonID &&
  1754. IDC_BUTTON_CLEANUP_NOW != ButtonID )
  1755. {
  1756. m_SettingsChanged = true;
  1757. SendMessage(GetParent(m_hwnd), PSM_CHANGED, (WPARAM)m_hwnd, 0);
  1758. }
  1759. switch( LOWORD(wParam) )
  1760. {
  1761. case IDC_CHECK_BITS_UPLOAD:
  1762. m_EnabledSettingChanged = true;
  1763. UpdateUploadGroupState( );
  1764. break;
  1765. case IDC_RADIO_USE_INHERITED_CONFIG:
  1766. LoadMaxUploadValue( m_InheritedValues.MaxUploadSize );
  1767. LoadTimeoutValue( m_InheritedValues.SessionTimeout );
  1768. LoadServerFarmSettings( m_InheritedValues.HostId, m_InheritedValues.FallbackTimeout );
  1769. LoadNotificationValues( m_InheritedValues.NotificationType,
  1770. m_InheritedValues.NotificationURL );
  1771. // Intentional fallthrough
  1772. case IDC_RADIO_USE_CUSTOM_CONFIG:
  1773. UpdateConfigGroupState( true );
  1774. break;
  1775. case IDC_CHECK_LIMIT_MAX_UPLOAD:
  1776. UpdateMaxUploadGroupState( true );
  1777. break;
  1778. case IDC_DELETE_FILES:
  1779. UpdateTimeoutGroupState( true );
  1780. break;
  1781. case IDC_CHECK_ENABLE_NOTIFICATIONS:
  1782. UpdateNotificationsGroupState( true );
  1783. break;
  1784. case IDC_ENABLE_SERVER_FARM:
  1785. UpdateServerFarmGroupState( true );
  1786. break;
  1787. case IDC_CHECK_FALLBACK_TIMEOUT:
  1788. UpdateServerFarmFallbackGroupState( true );
  1789. break;
  1790. case IDC_BUTTON_SCHEDULE_CLEANUP:
  1791. ScheduleCleanup();
  1792. break;
  1793. case IDC_BUTTON_CLEANUP_NOW:
  1794. CleanupNow();
  1795. break;
  1796. }
  1797. }
  1798. break;
  1799. case WM_DESTROY:
  1800. // we don't free the notify handle for property sheets
  1801. // MMCFreeNotifyHandle(pThis->m_ppHandle);
  1802. break;
  1803. case WM_NOTIFY:
  1804. switch (((NMHDR *) lParam)->code)
  1805. {
  1806. case PSN_KILLACTIVE:
  1807. SetWindowLongPtr( m_hwnd, DWLP_MSGRESULT, !ValidateValues( ) );
  1808. return TRUE;
  1809. case PSN_APPLY:
  1810. // don't notify the primary snap-in that Apply
  1811. // has been hit...
  1812. // MMCPropertyChangeNotify(pThis->m_ppHandle, (long)pThis);
  1813. if ( m_SettingsChanged )
  1814. {
  1815. CloseCleanupItems();
  1816. SetValues( );
  1817. UpdateCleanupState( );
  1818. // all changes are flushed now
  1819. m_SettingsChanged = m_EnabledSettingChanged = false;
  1820. }
  1821. SetWindowLongPtr( m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR );
  1822. return TRUE;
  1823. case PSN_HELP:
  1824. DisplayHelp( );
  1825. return TRUE;
  1826. }
  1827. break;
  1828. case WM_HELP:
  1829. DisplayHelp( );
  1830. return TRUE;
  1831. }
  1832. return FALSE;
  1833. }
  1834. HRESULT
  1835. CPropSheetExtension::ComputeMetabaseParent()
  1836. {
  1837. //
  1838. // Hack the metabase path to get the key parent
  1839. //
  1840. SIZE_T MetabaseParentSize = wcslen( m_MetabasePath ) + 1;
  1841. try
  1842. {
  1843. m_MetabaseParent = new WCHAR[ MetabaseParentSize ];
  1844. }
  1845. catch( ComError Error )
  1846. {
  1847. return Error.m_Hr;
  1848. }
  1849. StringCchCopy( m_MetabaseParent, MetabaseParentSize, m_MetabasePath );
  1850. {
  1851. WCHAR *p = m_MetabaseParent + wcslen( m_MetabaseParent );
  1852. while( ( L'/' != *p ) && ( p != m_MetabaseParent ) )
  1853. p--;
  1854. *p = L'\0';
  1855. }
  1856. return S_OK;
  1857. }
  1858. HRESULT
  1859. CPropSheetExtension::ComputeUNCComputerName()
  1860. {
  1861. //
  1862. //
  1863. // The task scheduler expects the name of the computer to have
  1864. // double slashes in front of it just like UNC names. Do the
  1865. // conversion here.
  1866. //
  1867. SIZE_T ComputerNameSize = wcslen( m_ComputerName );
  1868. try
  1869. {
  1870. m_UNCComputerName = new WCHAR[ ComputerNameSize + 3 ]; // add
  1871. }
  1872. catch( ComError Error )
  1873. {
  1874. return Error.m_Hr;
  1875. }
  1876. WCHAR *StringDest;
  1877. if ( L'\\' == m_ComputerName[0] )
  1878. {
  1879. if ( L'\\' == m_ComputerName[1] )
  1880. {
  1881. // No slashes are needed
  1882. StringDest = m_UNCComputerName;
  1883. }
  1884. else
  1885. {
  1886. // need one slash
  1887. m_UNCComputerName[0] = L'\\';
  1888. StringDest = m_UNCComputerName + 1;
  1889. }
  1890. }
  1891. else
  1892. {
  1893. // need two slashes
  1894. m_UNCComputerName[0] = m_UNCComputerName[1] = L'\\';
  1895. StringDest = m_UNCComputerName + 2;
  1896. }
  1897. memcpy( StringDest, m_ComputerName, ( ComputerNameSize + 1 ) * sizeof( WCHAR ) );
  1898. return S_OK;
  1899. }
  1900. HRESULT
  1901. CPropSheetExtension::OpenSetupInterface()
  1902. {
  1903. HRESULT Hr;
  1904. WCHAR *ADSIPath = NULL;
  1905. WCHAR *ConvertedMetabasePath = m_MetabasePath;
  1906. try
  1907. {
  1908. if ( _wcsnicmp( m_MetabasePath, L"/LM/", wcslen(L"/LM/") ) == 0 ||
  1909. _wcsnicmp( m_MetabasePath, L"LM/", wcslen(L"LM/" ) ) == 0 )
  1910. {
  1911. //
  1912. // Only do the fixup if we're not managing the local computer
  1913. //
  1914. WCHAR ComputerName[ MAX_COMPUTERNAME_LENGTH + 1 ];
  1915. DWORD BufferLength = MAX_COMPUTERNAME_LENGTH + 1;
  1916. if ( !GetComputerName( ComputerName, &BufferLength ) )
  1917. return HRESULT_FROM_WIN32( GetLastError() );
  1918. if ( _wcsicmp( m_ComputerName, ComputerName ) != 0 )
  1919. {
  1920. SIZE_T ConvertedPathSize = wcslen( m_ComputerName ) + wcslen( m_MetabasePath ) + 1;
  1921. try
  1922. {
  1923. ConvertedMetabasePath = new WCHAR[ ConvertedPathSize ];
  1924. }
  1925. catch( ComError Error )
  1926. {
  1927. return Error.m_Hr;
  1928. }
  1929. StringCchCopyW( ConvertedMetabasePath, ConvertedPathSize, L"/" );
  1930. StringCchCatW( ConvertedMetabasePath, ConvertedPathSize, m_ComputerName );
  1931. size_t MetabaseOffset =
  1932. m_MetabasePath[0] == L'/' ?
  1933. wcslen(L"/LM") : wcslen( L"LM" );
  1934. StringCchCatW( ConvertedMetabasePath, ConvertedPathSize, m_MetabasePath + MetabaseOffset );
  1935. }
  1936. }
  1937. ADSIPath = CSimplePropertyReader::ConvertObjectPathToADSI( ConvertedMetabasePath );
  1938. THROW_COMERROR( ADsGetObject( ADSIPath, __uuidof(*m_IBITSSetup), (void**)&m_IBITSSetup ) );
  1939. if ( ConvertedMetabasePath != m_MetabasePath)
  1940. delete[] ConvertedMetabasePath;
  1941. ConvertedMetabasePath = NULL;
  1942. delete ADSIPath;
  1943. ADSIPath = NULL;
  1944. }
  1945. catch( ComError Error )
  1946. {
  1947. delete ADSIPath;
  1948. if ( ConvertedMetabasePath != m_MetabasePath )
  1949. delete[] ConvertedMetabasePath;
  1950. return Error.m_Hr;
  1951. }
  1952. return S_OK;
  1953. }
  1954. ///////////////////////////////
  1955. // Interface IExtendPropertySheet
  1956. ///////////////////////////////
  1957. HRESULT CPropSheetExtension::CreatePropertyPages(
  1958. /* [in] */ LPPROPERTYSHEETCALLBACK lpProvider,
  1959. /* [in] */ LONG_PTR handle,
  1960. /* [in] */ LPDATAOBJECT lpIDataObject)
  1961. {
  1962. HRESULT Hr = E_FAIL;
  1963. Hr = ExtractSnapInString( (IDataObject*)lpIDataObject, m_MetabasePath, s_cfSnapInMetapath );
  1964. if ( FAILED(Hr) )
  1965. return Hr;
  1966. Hr = ExtractSnapInString( (IDataObject*)lpIDataObject, m_ComputerName, s_cfSnapInMachineName );
  1967. if ( FAILED(Hr) )
  1968. return Hr;
  1969. Hr = ComputeUNCComputerName();
  1970. if ( FAILED(Hr) )
  1971. return Hr;
  1972. Hr = ExtractSnapInGUID( (IDataObject*)lpIDataObject, m_NodeGuid, s_cfNodeType );
  1973. if ( FAILED(Hr) )
  1974. return Hr;
  1975. Hr = ComputeMetabaseParent();
  1976. if ( FAILED(Hr) )
  1977. return Hr;
  1978. Hr = OpenSetupInterface();
  1979. if ( FAILED(Hr) )
  1980. return Hr;
  1981. if ( !m_IISAdminBase )
  1982. {
  1983. COSERVERINFO coinfo;
  1984. coinfo.dwReserved1 = 0;
  1985. coinfo.dwReserved2 = 0;
  1986. coinfo.pAuthInfo = NULL;
  1987. coinfo.pwszName = m_ComputerName;
  1988. GUID guid = __uuidof( IMSAdminBase );
  1989. MULTI_QI mqi;
  1990. mqi.hr = S_OK;
  1991. mqi.pIID = &guid;
  1992. mqi.pItf = NULL;
  1993. Hr =
  1994. CoCreateInstanceEx(
  1995. GETAdminBaseCLSID(TRUE),
  1996. NULL,
  1997. CLSCTX_SERVER,
  1998. &coinfo,
  1999. 1,
  2000. &mqi );
  2001. if ( FAILED( Hr ) )
  2002. return Hr;
  2003. if ( FAILED( mqi.hr ) )
  2004. return mqi.hr;
  2005. m_IISAdminBase = (IMSAdminBase*)mqi.pItf;
  2006. }
  2007. METADATA_RECORD mdr;
  2008. DWORD BufferRequired;
  2009. memset( &mdr, 0, sizeof(mdr) );
  2010. mdr.dwMDIdentifier = MD_KEY_TYPE;
  2011. mdr.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  2012. mdr.dwMDUserType = ALL_METADATA;
  2013. mdr.dwMDDataType = ALL_METADATA;
  2014. mdr.dwMDDataLen = sizeof(m_NodeTypeName);
  2015. mdr.pbMDData = (PBYTE) m_NodeTypeName;
  2016. Hr = m_IISAdminBase->GetData(
  2017. METADATA_MASTER_ROOT_HANDLE,
  2018. m_MetabasePath,
  2019. &mdr,
  2020. &BufferRequired );
  2021. // Out of buffer isn't really an error, its just that the
  2022. // node type is bigger then what we are looking for.
  2023. if ( Hr == HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) )
  2024. return S_FALSE;
  2025. if ( FAILED(Hr) )
  2026. return Hr;
  2027. // Do not display pages for nodes that are not virtual directories
  2028. if ( 0 != wcscmp( L"IIsWebVirtualDir", m_NodeTypeName ) )
  2029. return S_FALSE;
  2030. // Create property manager
  2031. try
  2032. {
  2033. m_PropertyMan = new PropertyIDManager();
  2034. }
  2035. catch( ComError Error )
  2036. {
  2037. return Error.m_Hr;
  2038. }
  2039. Hr = m_PropertyMan->LoadPropertyInfo( m_ComputerName );
  2040. if ( FAILED( Hr ) )
  2041. return Hr;
  2042. PROPSHEETPAGE psp;
  2043. HPROPSHEETPAGE hPage = NULL;
  2044. // we don't cache this handle like in a primary snap-in
  2045. // the handle value here is always 0
  2046. // m_ppHandle = handle;
  2047. memset( &psp, 0, sizeof(psp) );
  2048. psp.dwSize = sizeof(PROPSHEETPAGE);
  2049. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_HASHELP;
  2050. psp.hInstance = g_hinst;
  2051. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_LARGE);
  2052. psp.pfnDlgProc = DialogProcExternal;
  2053. psp.lParam = reinterpret_cast<LPARAM>(this);
  2054. psp.pszTitle = MAKEINTRESOURCE(IDS_BITS_EXT);
  2055. hPage = CreatePropertySheetPage(&psp);
  2056. _ASSERT(hPage);
  2057. Hr = lpProvider->AddPage(hPage);
  2058. return Hr;
  2059. }
  2060. HRESULT CPropSheetExtension::QueryPagesFor(
  2061. /* [in] */ LPDATAOBJECT lpDataObject)
  2062. {
  2063. return S_OK;
  2064. }
  2065. void * _cdecl ::operator new( size_t Size )
  2066. {
  2067. void * NewMemory = HeapAlloc( GetProcessHeap(), 0, Size );
  2068. if (!NewMemory )
  2069. throw ComError( E_OUTOFMEMORY );
  2070. return NewMemory;
  2071. }
  2072. void _cdecl ::operator delete( void *Memory )
  2073. {
  2074. if ( !Memory )
  2075. return;
  2076. HeapFree( GetProcessHeap(), 0, Memory );
  2077. }