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.

839 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. /////////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1998-2002
  6. //
  7. // File: SchedDlg.cpp
  8. //
  9. // Contents: Implementation of CConnectionScheduleDlg
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "stdafx.h"
  13. #include "SchedDlg.h"
  14. #include "log_gmt.h"
  15. #include "loghrapi.h"
  16. #ifdef _DEBUG
  17. //#define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. //
  22. // The schedule block has been redefined to have 1 byte for every hour.
  23. // CODEWORK These should be defined in SCHEDULE.H. JonN 2/9/98
  24. //
  25. #define INTERVAL_MASK 0x0F
  26. #define RESERVED 0xF0
  27. #define FIRST_15_MINUTES 0x01
  28. #define SECOND_15_MINUTES 0x02
  29. #define THIRD_15_MINUTES 0x04
  30. #define FOURTH_15_MINUTES 0x08
  31. const int NONE_PER_HOUR = 0;
  32. const int ONE_PER_HOUR = 33;
  33. const int TWO_PER_HOUR = 67;
  34. const int FOUR_PER_HOUR = 100;
  35. /////////////////////////////////////////////////////////////////////
  36. // ConnectionScheduleDialog ()
  37. //
  38. // Invoke a dialog to set/modify a schedule, for example
  39. // -- the logon hours for a particular user
  40. // -- the schedule for a connection
  41. //
  42. // RETURNS
  43. // Return S_OK if the user clicked on the OK button.
  44. // Return S_FALSE if the user clicked on the Cancel button.
  45. // Return E_OUTOFMEMORY if there is not enough memory.
  46. /// Return E_UNEXPECTED if an expected error occured (eg: bad parameter)
  47. //
  48. // INTERFACE NOTES
  49. // Each bit in the array represents one hour. As a result, the
  50. // expected length of the array should be (24 / 8) * 7 = 21 bytes.
  51. // For convenience, the first day of the week is Sunday and
  52. // the last day is Saturday.
  53. // Consequently, the first bit of the array represents the schedule
  54. // for Sunday during period 12 AM to 1 AM.
  55. // - If *pprgbData is NULL, then the routine will allocate
  56. // an array of 21 bytes using LocalAlloc (). The caller
  57. // is responsible of releasing the memory using LocalFree ().
  58. // - If *pprgbData is not NULL, the routine re-use the array as its
  59. // output parameter.
  60. //
  61. // HISTORY
  62. // 17-Jul-97 t-danm Creation.
  63. // 16-Sep-97 jonn Changed to UiScheduleDialog
  64. //
  65. HRESULT
  66. ConnectionScheduleDialog (
  67. HWND hwndParent, // IN: Parent's window handle
  68. BYTE ** pprgbData, // INOUT: Pointer to pointer to array of 21 bytes (one bit per hour)
  69. LPCTSTR pszTitle) // IN: Dialog title
  70. {
  71. return ConnectionScheduleDialogEx (hwndParent, pprgbData, pszTitle, 0);
  72. }
  73. // NTRAID#NTBUG9-547415-2002/02/18-artm Should catch out of memory exceptions and convert to HRESULT.
  74. HRESULT
  75. ConnectionScheduleDialogEx (
  76. HWND hwndParent, // IN: Parent's window handle
  77. BYTE ** pprgbData, // INOUT: Pointer to pointer to array of 21 bytes (one bit per hour)
  78. LPCTSTR pszTitle, // IN: Dialog title
  79. DWORD dwFlags)
  80. {
  81. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  82. // These asserts are backed up by validation code.
  83. ASSERT (::IsWindow (hwndParent));
  84. ASSERT (pprgbData);
  85. // NOTICE-NTRAID#NTBUG9-547381-2002/02/18-artm pszTitle okay to be NULL
  86. // dlg.SetTitle() robustly handles NULL.
  87. ASSERT (pszTitle);
  88. ENDORSE (NULL == *pprgbData); // TRUE => Use default logon hours (7x24)
  89. if (*pprgbData == NULL)
  90. {
  91. BYTE * pargbData; // Pointer to allocated array of bytes
  92. // FUTURE-2002/02/18-artm Use named constant instead of magic 7*24.
  93. pargbData = (BYTE *)LocalAlloc (0, 7*24); // Allocate 168 bytes
  94. if ( !pargbData )
  95. return E_OUTOFMEMORY;
  96. // Set the logon hours to be valid 24 hours a day and 7 days a week.
  97. // FUTURE-2002/02/18-artm Use named constant instead of magic 7*24.
  98. memset (OUT pargbData, -1, 7*24);
  99. *pprgbData = pargbData;
  100. }
  101. // If hwndParent passed in, create a CWnd to pass as the parent window
  102. CWnd* pWnd = 0;
  103. if ( ::IsWindow (hwndParent) )
  104. {
  105. pWnd = new CWnd;
  106. if ( pWnd )
  107. {
  108. pWnd->Attach (hwndParent);
  109. }
  110. else
  111. return E_OUTOFMEMORY;
  112. }
  113. HRESULT hr = S_OK;
  114. CConnectionScheduleDlg dlg (pWnd);
  115. dlg.SetTitle (pszTitle);
  116. dlg.SetConnectionByteArray (INOUT *pprgbData, 7*24);
  117. dlg.SetFlags (dwFlags);
  118. if (IDOK != dlg.DoModal ())
  119. hr = S_FALSE;
  120. // Delete CWnd
  121. if ( pWnd )
  122. {
  123. pWnd->Detach ();
  124. delete pWnd;
  125. }
  126. return hr;
  127. } // ConnectionScheduleDialog ()
  128. HRESULT
  129. ReplicationScheduleDialog (
  130. HWND hwndParent, // IN: Parent's window handle
  131. BYTE ** pprgbData, // INOUT: Pointer to pointer to array of 21 bytes (one bit per hour)
  132. LPCTSTR pszTitle) // IN: Dialog title
  133. {
  134. return ReplicationScheduleDialogEx (hwndParent, pprgbData, pszTitle, 0);
  135. } // ReplicationScheduleDialog ()
  136. // NTRAID#NTBUG9-547415-2002/02/18-artm Should catch out of memory exceptions and convert to HRESULT.
  137. HRESULT ReplicationScheduleDialogEx (
  138. HWND hwndParent, // parent window
  139. BYTE ** pprgbData, // pointer to pointer to array of 84 bytes
  140. LPCTSTR pszTitle, // dialog title
  141. DWORD dwFlags) // option flags
  142. {
  143. AFX_MANAGE_STATE (AfxGetStaticModuleState ());
  144. // These asserts are backed up by validation code in release build.
  145. ASSERT (::IsWindow (hwndParent));
  146. ASSERT (pprgbData);
  147. // NOTICE-NTRAID#NTBUG9-547381-2002/02/18-artm pszTitle okay to be NULL
  148. // dlg.SetTitle() robustly handles NULL.
  149. ASSERT (pszTitle);
  150. ENDORSE (NULL == *pprgbData); // TRUE => Use default logon hours (7x24)
  151. if (*pprgbData == NULL)
  152. {
  153. BYTE * pargbData; // Pointer to allocated array of bytes
  154. // FUTURE-2002/02/18-artm Use named constant instead of magic 7*24.
  155. pargbData = (BYTE *)LocalAlloc (0, 7*24); // Allocate 168 bytes
  156. if ( !pargbData )
  157. return E_OUTOFMEMORY;
  158. // FUTURE-2002/02/18-artm Use named constant instead of magic 7*24.
  159. // Set the logon hours to be valid 24 hours a day and 7 days a week.
  160. memset (OUT pargbData, -1, 7*24);
  161. *pprgbData = pargbData;
  162. }
  163. // If hwndParent passed in, create a CWnd to pass as the parent window
  164. CWnd* pWnd = 0;
  165. if ( ::IsWindow (hwndParent) )
  166. {
  167. pWnd = new CWnd;
  168. if ( pWnd )
  169. {
  170. pWnd->Attach (hwndParent);
  171. }
  172. else
  173. return E_OUTOFMEMORY;
  174. }
  175. HRESULT hr = S_OK;
  176. CReplicationScheduleDlg dlg (pWnd);
  177. dlg.SetTitle (pszTitle);
  178. dlg.SetConnectionByteArray (INOUT *pprgbData, 7*24);
  179. dlg.SetFlags (dwFlags);
  180. if (IDOK != dlg.DoModal ())
  181. hr = S_FALSE;
  182. // Delete CWnd
  183. if ( pWnd )
  184. {
  185. pWnd->Detach ();
  186. delete pWnd;
  187. }
  188. return hr;
  189. } // ReplicationScheduleDialogEx
  190. /////////////////////////////////////////////////////////////////////////////
  191. // CConnectionScheduleDlg dialog
  192. CConnectionScheduleDlg::CConnectionScheduleDlg(CWnd* pParent)
  193. : CScheduleBaseDlg(CConnectionScheduleDlg::IDD, true, pParent),
  194. m_prgbData168 (0)
  195. {
  196. EnableAutomation();
  197. //{{AFX_DATA_INIT(CConnectionScheduleDlg)
  198. // NOTE: the ClassWizard will add member initialization here
  199. //}}AFX_DATA_INIT
  200. }
  201. void CConnectionScheduleDlg::OnFinalRelease()
  202. {
  203. // When the last reference for an automation object is released
  204. // OnFinalRelease is called. The base class will automatically
  205. // deletes the object. Add additional cleanup required for your
  206. // object before calling the base class.
  207. CScheduleBaseDlg::OnFinalRelease();
  208. }
  209. void CConnectionScheduleDlg::DoDataExchange(CDataExchange* pDX)
  210. {
  211. CScheduleBaseDlg::DoDataExchange(pDX);
  212. //{{AFX_DATA_MAP(CConnectionScheduleDlg)
  213. DDX_Control(pDX, IDC_RADIO_NONE, m_buttonNone);
  214. DDX_Control(pDX, IDC_RADIO_ONE, m_buttonOne);
  215. DDX_Control(pDX, IDC_RADIO_TWO, m_buttonTwo);
  216. DDX_Control(pDX, IDC_RADIO_FOUR, m_buttonFour);
  217. //}}AFX_DATA_MAP
  218. }
  219. BEGIN_MESSAGE_MAP(CConnectionScheduleDlg, CScheduleBaseDlg)
  220. //{{AFX_MSG_MAP(CConnectionScheduleDlg)
  221. ON_BN_CLICKED(IDC_RADIO_FOUR, OnRadioFour)
  222. ON_BN_CLICKED(IDC_RADIO_NONE, OnRadioNone)
  223. ON_BN_CLICKED(IDC_RADIO_ONE, OnRadioOne)
  224. ON_BN_CLICKED(IDC_RADIO_TWO, OnRadioTwo)
  225. //}}AFX_MSG_MAP
  226. END_MESSAGE_MAP()
  227. BEGIN_DISPATCH_MAP(CConnectionScheduleDlg, CScheduleBaseDlg)
  228. //{{AFX_DISPATCH_MAP(CConnectionScheduleDlg)
  229. // NOTE - the ClassWizard will add and remove mapping macros here.
  230. //}}AFX_DISPATCH_MAP
  231. END_DISPATCH_MAP()
  232. // Note: we add support for IID_IDSScheduleDlg to support typesafe binding
  233. // from VBA. This IID must match the GUID that is attached to the
  234. // dispinterface in the .ODL file.
  235. // {701CFB36-AEF8-11D1-9864-00C04FB94F17}
  236. static const IID IID_IDSScheduleDlg =
  237. { 0x701cfb36, 0xaef8, 0x11d1, { 0x98, 0x64, 0x0, 0xc0, 0x4f, 0xb9, 0x4f, 0x17 } };
  238. BEGIN_INTERFACE_MAP(CConnectionScheduleDlg, CScheduleBaseDlg)
  239. INTERFACE_PART(CConnectionScheduleDlg, IID_IDSScheduleDlg, Dispatch)
  240. END_INTERFACE_MAP()
  241. /////////////////////////////////////////////////////////////////////////////
  242. // CConnectionScheduleDlg message handlers
  243. BOOL CConnectionScheduleDlg::OnInitDialog()
  244. {
  245. CScheduleBaseDlg::OnInitDialog();
  246. // Set up the "none" legend
  247. m_legendNone.Init (this, IDC_STATIC_LEGEND_NONE, &m_schedulematrix, NONE_PER_HOUR);
  248. // Set up the "one" legend
  249. m_legendOne.Init (this, IDC_STATIC_LEGEND_ONE, &m_schedulematrix, ONE_PER_HOUR);
  250. // Set up the "two" legend
  251. m_legendTwo.Init (this, IDC_STATIC_LEGEND_TWO, &m_schedulematrix, TWO_PER_HOUR);
  252. // Set up the "four" legend
  253. m_legendFour.Init (this, IDC_STATIC_LEGEND_FOUR, &m_schedulematrix, FOUR_PER_HOUR);
  254. if ( GetFlags () & SCHED_FLAG_READ_ONLY )
  255. {
  256. // Disable the grid settings buttons
  257. m_buttonNone.EnableWindow (FALSE);
  258. m_buttonOne.EnableWindow (FALSE);
  259. m_buttonTwo.EnableWindow (FALSE);
  260. m_buttonFour.EnableWindow (FALSE);
  261. }
  262. return TRUE; // return TRUE unless you set the focus to a control
  263. // EXCEPTION: OCX Property Pages should return FALSE
  264. }
  265. void CConnectionScheduleDlg::OnOK()
  266. {
  267. if ( m_prgbData168 )
  268. {
  269. GetByteArray (OUT m_prgbData168, m_cbArray);
  270. // Convert back the hours to GMT time.
  271. ConvertConnectionHoursToGMT (INOUT m_prgbData168, m_bAddDaylightBias);
  272. }
  273. CScheduleBaseDlg::OnOK();
  274. }
  275. void CConnectionScheduleDlg::UpdateButtons ()
  276. {
  277. UINT nHour = 0;
  278. UINT nDay = 0;
  279. UINT nNumHours = 0;
  280. UINT nNumDays = 0;
  281. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  282. // Assume in each case that all selected squares are all set one way until
  283. // proven otherwise. These are 'int' so that I can add them up afterwards
  284. // to assure that only one of the buttons will be checked.
  285. int fNoneAllSet = 1;
  286. int fOneAllSet = 1;
  287. int fTwoAllSet = 1;
  288. int fFourAllSet = 1;
  289. if (nNumHours > 0)
  290. {
  291. for (UINT iDayOfWeek = nDay; iDayOfWeek < nDay+nNumDays; iDayOfWeek++)
  292. {
  293. for (UINT iHour = nHour; iHour < nHour+nNumHours; iHour++)
  294. {
  295. switch (m_schedulematrix.GetPercentage (iHour, iDayOfWeek))
  296. {
  297. case NONE_PER_HOUR:
  298. fOneAllSet = 0;
  299. fTwoAllSet = 0;
  300. fFourAllSet = 0;
  301. break;
  302. case ONE_PER_HOUR:
  303. fNoneAllSet = 0;
  304. fTwoAllSet = 0;
  305. fFourAllSet = 0;
  306. break;
  307. case TWO_PER_HOUR:
  308. fNoneAllSet = 0;
  309. fOneAllSet = 0;
  310. fFourAllSet = 0;
  311. break;
  312. case FOUR_PER_HOUR:
  313. fNoneAllSet = 0;
  314. fOneAllSet = 0;
  315. fTwoAllSet = 0;
  316. break;
  317. default:
  318. ASSERT (0);
  319. break;
  320. }
  321. } // for
  322. } // for
  323. }
  324. else
  325. {
  326. fNoneAllSet = 0;
  327. fOneAllSet = 0;
  328. fTwoAllSet = 0;
  329. fFourAllSet = 0;
  330. }
  331. // Ensure that at most, only one of these is 'true'
  332. ASSERT ((fNoneAllSet + fOneAllSet + fTwoAllSet + fFourAllSet <= 1));
  333. m_buttonNone.SetCheck (fNoneAllSet);
  334. m_buttonOne.SetCheck (fOneAllSet);
  335. m_buttonTwo.SetCheck (fTwoAllSet);
  336. m_buttonFour.SetCheck (fFourAllSet);
  337. }
  338. void CConnectionScheduleDlg::OnRadioFour()
  339. {
  340. UINT nHour = 0;
  341. UINT nDay = 0;
  342. UINT nNumHours = 0;
  343. UINT nNumDays = 0;
  344. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  345. if (nNumHours <= 0)
  346. return; // Nothing selected
  347. m_schedulematrix.SetPercentage (FOUR_PER_HOUR, nHour, nDay, nNumHours, nNumDays);
  348. UpdateButtons ();
  349. }
  350. void CConnectionScheduleDlg::OnRadioNone()
  351. {
  352. UINT nHour = 0;
  353. UINT nDay = 0;
  354. UINT nNumHours = 0;
  355. UINT nNumDays = 0;
  356. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  357. if (nNumHours <= 0)
  358. return; // Nothing selected
  359. m_schedulematrix.SetPercentage (NONE_PER_HOUR, nHour, nDay, nNumHours, nNumDays);
  360. UpdateButtons ();
  361. }
  362. void CConnectionScheduleDlg::OnRadioOne()
  363. {
  364. UINT nHour = 0;
  365. UINT nDay = 0;
  366. UINT nNumHours = 0;
  367. UINT nNumDays = 0;
  368. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  369. if (nNumHours <= 0)
  370. return; // Nothing selected
  371. m_schedulematrix.SetPercentage (ONE_PER_HOUR, nHour, nDay, nNumHours, nNumDays);
  372. UpdateButtons ();
  373. }
  374. void CConnectionScheduleDlg::OnRadioTwo()
  375. {
  376. UINT nHour = 0;
  377. UINT nDay = 0;
  378. UINT nNumHours = 0;
  379. UINT nNumDays = 0;
  380. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  381. if (nNumHours <= 0)
  382. return; // Nothing selected
  383. m_schedulematrix.SetPercentage (TWO_PER_HOUR, nHour, nDay, nNumHours, nNumDays);
  384. UpdateButtons ();
  385. }
  386. void CConnectionScheduleDlg::InitMatrix()
  387. {
  388. if ( m_prgbData168 )
  389. {
  390. BYTE rgData[SCHEDULE_DATA_ENTRIES]; // Array of logonhours bits
  391. // Make a copy of the connection hours (in case the user click on cancel button)
  392. memcpy (OUT rgData, IN m_prgbData168, sizeof (rgData));
  393. // Convert the hours from GMT to local hours.
  394. ConvertConnectionHoursFromGMT (INOUT rgData, m_bAddDaylightBias);
  395. // Initialize the matrix
  396. InitMatrix2 (IN rgData);
  397. }
  398. }
  399. void CConnectionScheduleDlg::SetConnectionByteArray(INOUT BYTE rgbData [SCHEDULE_DATA_ENTRIES],
  400. const size_t cbArray)
  401. {
  402. // NULL m_prgbData168 is checked for where it is dereferenced; ASSERT does not need to be backed up
  403. ASSERT (rgbData);
  404. if ( !IsBadWritePtr (rgbData, cbArray) )
  405. {
  406. m_prgbData168 = rgbData;
  407. m_cbArray = cbArray;
  408. }
  409. }
  410. // This table represent the numbers of bits set in the lower nibble of the BYTE.
  411. // 0 bits -> 0
  412. // 1 bit -> 25
  413. // 2 or 3 bits -> 50
  414. // 4 bits -> 100
  415. static BYTE setConversionTable[16] =
  416. {NONE_PER_HOUR, // 0000
  417. ONE_PER_HOUR, // 0001
  418. ONE_PER_HOUR, // 0010
  419. TWO_PER_HOUR, // 0011
  420. ONE_PER_HOUR, // 0100
  421. TWO_PER_HOUR, // 0101
  422. TWO_PER_HOUR, // 0110
  423. TWO_PER_HOUR, // 0111
  424. ONE_PER_HOUR, // 1000
  425. TWO_PER_HOUR, // 1001
  426. TWO_PER_HOUR, // 1010
  427. TWO_PER_HOUR, // 1011
  428. TWO_PER_HOUR, // 1100
  429. TWO_PER_HOUR, // 1101
  430. TWO_PER_HOUR, // 1110
  431. FOUR_PER_HOUR}; // 1111
  432. UINT CConnectionScheduleDlg::GetPercentageToSet(const BYTE bData)
  433. {
  434. ASSERT ((bData & 0x0F) < 16);
  435. return setConversionTable[bData & 0x0F];
  436. }
  437. BYTE CConnectionScheduleDlg::GetMatrixPercentage(UINT nHour, UINT nDay)
  438. {
  439. BYTE byResult = 0;
  440. switch (m_schedulematrix.GetPercentage (nHour, nDay))
  441. {
  442. case NONE_PER_HOUR:
  443. // value remains 0n
  444. break;
  445. case ONE_PER_HOUR:
  446. byResult = FIRST_15_MINUTES;
  447. break;
  448. case TWO_PER_HOUR:
  449. byResult = FIRST_15_MINUTES | THIRD_15_MINUTES;
  450. break;
  451. case FOUR_PER_HOUR:
  452. byResult = FIRST_15_MINUTES | SECOND_15_MINUTES | THIRD_15_MINUTES | FOURTH_15_MINUTES;
  453. break;
  454. default:
  455. ASSERT (0);
  456. break;
  457. }
  458. return byResult;
  459. }
  460. UINT CConnectionScheduleDlg::GetExpectedArrayLength()
  461. {
  462. return SCHEDULE_DATA_ENTRIES;
  463. }
  464. // Called when WM_TIMECHANGE is received
  465. void CConnectionScheduleDlg::TimeChange()
  466. {
  467. m_buttonNone.EnableWindow (FALSE);
  468. m_buttonOne.EnableWindow (FALSE);
  469. m_buttonTwo.EnableWindow (FALSE);
  470. m_buttonFour.EnableWindow (FALSE);
  471. }
  472. /////////////////////////////////////////////////////////////////////////////
  473. // CReplicationScheduleDlg dialog
  474. CReplicationScheduleDlg::CReplicationScheduleDlg(CWnd* pParent)
  475. : CScheduleBaseDlg(CReplicationScheduleDlg::IDD, true, pParent),
  476. m_prgbData168 (0)
  477. {
  478. EnableAutomation();
  479. //{{AFX_DATA_INIT(CReplicationScheduleDlg)
  480. // NOTE: the ClassWizard will add member initialization here
  481. //}}AFX_DATA_INIT
  482. }
  483. void CReplicationScheduleDlg::OnFinalRelease()
  484. {
  485. // When the last reference for an automation object is released
  486. // OnFinalRelease is called. The base class will automatically
  487. // deletes the object. Add additional cleanup required for your
  488. // object before calling the base class.
  489. CScheduleBaseDlg::OnFinalRelease();
  490. }
  491. void CReplicationScheduleDlg::DoDataExchange(CDataExchange* pDX)
  492. {
  493. CScheduleBaseDlg::DoDataExchange(pDX);
  494. //{{AFX_DATA_MAP(CReplicationScheduleDlg)
  495. DDX_Control(pDX, IDC_RADIO_NONE, m_buttonNone);
  496. DDX_Control(pDX, IDC_RADIO_FOUR, m_buttonFour);
  497. //}}AFX_DATA_MAP
  498. }
  499. BEGIN_MESSAGE_MAP(CReplicationScheduleDlg, CScheduleBaseDlg)
  500. //{{AFX_MSG_MAP(CReplicationScheduleDlg)
  501. ON_BN_CLICKED(IDC_RADIO_FOUR, OnRadioFour)
  502. ON_BN_CLICKED(IDC_RADIO_NONE, OnRadioNone)
  503. //}}AFX_MSG_MAP
  504. END_MESSAGE_MAP()
  505. BEGIN_DISPATCH_MAP(CReplicationScheduleDlg, CScheduleBaseDlg)
  506. //{{AFX_DISPATCH_MAP(CReplicationScheduleDlg)
  507. // NOTE - the ClassWizard will add and remove mapping macros here.
  508. //}}AFX_DISPATCH_MAP
  509. END_DISPATCH_MAP()
  510. // Note: we add support for IID_IDSScheduleDlg to support typesafe binding
  511. // from VBA. This IID must match the GUID that is attached to the
  512. // dispinterface in the .ODL file.
  513. // {8DE6E2DA-7B4E-11d2-AC13-00C04F79DDCA}
  514. static const IID IID_IReplicationScheduleDlg =
  515. { 0x8de6e2da, 0x7b4e, 0x11d2, { 0xac, 0x13, 0x0, 0xc0, 0x4f, 0x79, 0xdd, 0xca } };
  516. BEGIN_INTERFACE_MAP(CReplicationScheduleDlg, CScheduleBaseDlg)
  517. INTERFACE_PART(CReplicationScheduleDlg, IID_IReplicationScheduleDlg, Dispatch)
  518. END_INTERFACE_MAP()
  519. /////////////////////////////////////////////////////////////////////////////
  520. // CReplicationScheduleDlg message handlers
  521. BOOL CReplicationScheduleDlg::OnInitDialog()
  522. {
  523. CScheduleBaseDlg::OnInitDialog();
  524. // Set up the "none" legend
  525. m_legendNone.Init (this, IDC_STATIC_LEGEND_NONE, &m_schedulematrix, NONE_PER_HOUR);
  526. // Set up the "four" legend
  527. m_legendFour.Init (this, IDC_STATIC_LEGEND_FOUR, &m_schedulematrix, FOUR_PER_HOUR);
  528. if ( GetFlags () & SCHED_FLAG_READ_ONLY )
  529. {
  530. // Disable the grid settings buttons
  531. m_buttonNone.EnableWindow (FALSE);
  532. m_buttonFour.EnableWindow (FALSE);
  533. }
  534. return TRUE; // return TRUE unless you set the focus to a control
  535. // EXCEPTION: OCX Property Pages should return FALSE
  536. }
  537. void CReplicationScheduleDlg::OnOK()
  538. {
  539. if ( m_prgbData168 )
  540. {
  541. GetByteArray (OUT m_prgbData168, m_cbArray);
  542. // Convert back the hours to GMT time.
  543. ConvertConnectionHoursToGMT (INOUT m_prgbData168, m_bAddDaylightBias);
  544. }
  545. CScheduleBaseDlg::OnOK();
  546. }
  547. void CReplicationScheduleDlg::UpdateButtons ()
  548. {
  549. UINT nHour = 0;
  550. UINT nDay = 0;
  551. UINT nNumHours = 0;
  552. UINT nNumDays = 0;
  553. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  554. // Assume in each case that all selected squares are all set one way until
  555. // proven otherwise. These are 'int' so that I can add them up afterwards
  556. // to assure that only one of the buttons will be checked.
  557. int fNoneAllSet = 1;
  558. int fFourAllSet = 1;
  559. if (nNumHours > 0)
  560. {
  561. for (UINT iDayOfWeek = nDay; iDayOfWeek < nDay+nNumDays; iDayOfWeek++)
  562. {
  563. for (UINT iHour = nHour; iHour < nHour+nNumHours; iHour++)
  564. {
  565. switch (m_schedulematrix.GetPercentage (iHour, iDayOfWeek))
  566. {
  567. case NONE_PER_HOUR:
  568. fFourAllSet = 0;
  569. break;
  570. case FOUR_PER_HOUR:
  571. fNoneAllSet = 0;
  572. break;
  573. default:
  574. ASSERT (0);
  575. break;
  576. }
  577. } // for
  578. } // for
  579. }
  580. else
  581. {
  582. fNoneAllSet = 0;
  583. }
  584. ASSERT (fNoneAllSet + fFourAllSet <= 1);
  585. m_buttonNone.SetCheck (fNoneAllSet);
  586. m_buttonFour.SetCheck (fFourAllSet);
  587. }
  588. void CReplicationScheduleDlg::OnRadioFour()
  589. {
  590. UINT nHour = 0;
  591. UINT nDay = 0;
  592. UINT nNumHours = 0;
  593. UINT nNumDays = 0;
  594. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  595. if (nNumHours <= 0)
  596. return; // Nothing selected
  597. m_schedulematrix.SetPercentage (FOUR_PER_HOUR, nHour, nDay, nNumHours, nNumDays);
  598. UpdateButtons ();
  599. }
  600. void CReplicationScheduleDlg::OnRadioNone()
  601. {
  602. UINT nHour = 0;
  603. UINT nDay = 0;
  604. UINT nNumHours = 0;
  605. UINT nNumDays = 0;
  606. m_schedulematrix.GetSel (OUT nHour, OUT nDay, OUT nNumHours, OUT nNumDays);
  607. if (nNumHours <= 0)
  608. return; // Nothing selected
  609. m_schedulematrix.SetPercentage (NONE_PER_HOUR, nHour, nDay, nNumHours, nNumDays);
  610. UpdateButtons ();
  611. }
  612. void CReplicationScheduleDlg::InitMatrix()
  613. {
  614. if ( m_prgbData168 )
  615. {
  616. BYTE rgData[SCHEDULE_DATA_ENTRIES]; // Array of logonhours bits
  617. // Make a copy of the connection hours (in case the user click on cancel button)
  618. memcpy (OUT rgData, IN m_prgbData168, sizeof (rgData));
  619. // Convert the hours from GMT to local hours.
  620. ConvertConnectionHoursFromGMT (INOUT rgData, m_bAddDaylightBias);
  621. // Initialize the matrix
  622. InitMatrix2 (IN rgData);
  623. }
  624. }
  625. void CReplicationScheduleDlg::SetConnectionByteArray(INOUT BYTE rgbData [SCHEDULE_DATA_ENTRIES], const size_t cbArray)
  626. {
  627. // Code supports NULL rgbData; ASSERT() is early bug detection.
  628. ASSERT (rgbData);
  629. if ( !IsBadWritePtr (rgbData, cbArray) )
  630. {
  631. m_prgbData168 = rgbData;
  632. m_cbArray = cbArray;
  633. }
  634. }
  635. // This table represent the numbers of bits set in the lower nibble of the BYTE.
  636. // 0 bits -> 0
  637. // 1 bit -> 25
  638. // 2 or 3 bits -> 50
  639. // 4 bits -> 100
  640. static BYTE setConversionTableForReplication[16] =
  641. {NONE_PER_HOUR, // 0000
  642. FOUR_PER_HOUR, // 0001
  643. FOUR_PER_HOUR, // 0010
  644. FOUR_PER_HOUR, // 0011
  645. FOUR_PER_HOUR, // 0100
  646. FOUR_PER_HOUR, // 0101
  647. FOUR_PER_HOUR, // 0110
  648. FOUR_PER_HOUR, // 0111
  649. FOUR_PER_HOUR, // 1000
  650. FOUR_PER_HOUR, // 1001
  651. FOUR_PER_HOUR, // 1010
  652. FOUR_PER_HOUR, // 1011
  653. FOUR_PER_HOUR, // 1100
  654. FOUR_PER_HOUR, // 1101
  655. FOUR_PER_HOUR, // 1110
  656. FOUR_PER_HOUR}; // 1111
  657. UINT CReplicationScheduleDlg::GetPercentageToSet(const BYTE bData)
  658. {
  659. ASSERT ((bData & 0x0F) < 16);
  660. return setConversionTableForReplication[bData & 0x0F];
  661. }
  662. BYTE CReplicationScheduleDlg::GetMatrixPercentage(UINT nHour, UINT nDay)
  663. {
  664. BYTE byResult = 0;
  665. switch (m_schedulematrix.GetPercentage (nHour, nDay))
  666. {
  667. case NONE_PER_HOUR:
  668. // value remains 0n
  669. break;
  670. case ONE_PER_HOUR:
  671. case TWO_PER_HOUR:
  672. case FOUR_PER_HOUR:
  673. byResult = FIRST_15_MINUTES | SECOND_15_MINUTES | THIRD_15_MINUTES | FOURTH_15_MINUTES;
  674. break;
  675. default:
  676. ASSERT (0);
  677. break;
  678. }
  679. return byResult;
  680. }
  681. UINT CReplicationScheduleDlg::GetExpectedArrayLength()
  682. {
  683. return SCHEDULE_DATA_ENTRIES;
  684. }
  685. // Called when WM_TIMECHANGE is received
  686. void CReplicationScheduleDlg::TimeChange()
  687. {
  688. m_buttonNone.EnableWindow (FALSE);
  689. m_buttonFour.EnableWindow (FALSE);
  690. }
  691. /////////////////////////////////////////////////////////////////////
  692. // Converts the connection hours from local time to GMT.
  693. void
  694. ConvertConnectionHoursToGMT (INOUT BYTE rgbData[SCHEDULE_DATA_ENTRIES], IN bool bAddDaylightBias)
  695. {
  696. // FUTURE-2002/02/18-artm Release code should check return value.
  697. VERIFY ( ::NetpRotateLogonHoursBYTE (rgbData, SCHEDULE_DATA_ENTRIES, TRUE, bAddDaylightBias) );
  698. }
  699. /////////////////////////////////////////////////////////////////////
  700. // Converts the connection hours from GMT to local time.
  701. void
  702. ConvertConnectionHoursFromGMT (INOUT BYTE rgbData[SCHEDULE_DATA_ENTRIES], IN bool bAddDaylightBias)
  703. {
  704. // FUTURE-2002/02/18-artm Release code should check return value.
  705. VERIFY ( ::NetpRotateLogonHoursBYTE (rgbData, SCHEDULE_DATA_ENTRIES, FALSE, bAddDaylightBias) );
  706. }