Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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