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.

951 lines
24 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. datetime.cpp
  5. Abstract:
  6. This file implements the date & time page.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 1-Dec-1997
  11. --*/
  12. #include "ntoc.h"
  13. #pragma hdrstop
  14. #define MYDEBUG 0
  15. #define TIMER_ID 1
  16. #define OPEN_TLEN 450 /* < half second */
  17. #define TZNAME_SIZE 128
  18. #define TZDISPLAYZ 128
  19. #define REGKEY_TIMEZONES L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
  20. #define REGVAL_TZ_DISPLAY L"Display"
  21. #define REGVAL_TZ_STD L"Std"
  22. #define REGVAL_TZ_DAYLIGHT L"Dlt"
  23. #define REGVAL_TZ_TZI L"TZI"
  24. #define REGVAL_TZ_INDEX L"Index"
  25. #define REGVAL_TZ_INDEXMAP L"IndexMapping"
  26. #define REGKEY_TIMEZONE_INFO L"System\\CurrentControlSet\\Control\\TimeZoneInformation"
  27. #define REGVAL_TZNOAUTOTIME L"DisableAutoDaylightTimeSet"
  28. typedef struct tagTZINFO
  29. {
  30. LIST_ENTRY ListEntry;
  31. WCHAR szDisplayName[TZDISPLAYZ];
  32. WCHAR szStandardName[TZNAME_SIZE];
  33. WCHAR szDaylightName[TZNAME_SIZE];
  34. int ReferenceIndex;
  35. LONG Bias;
  36. LONG StandardBias;
  37. LONG DaylightBias;
  38. SYSTEMTIME StandardDate;
  39. SYSTEMTIME DaylightDate;
  40. } TZINFO, *PTZINFO;
  41. LIST_ENTRY ZoneList;
  42. SYSTEMTIME SelectedTime;
  43. SYSTEMTIME SelectedDate;
  44. BOOL ChangeTime;
  45. BOOL ChangeDate;
  46. PTZINFO CurrZone;
  47. BOOL AllowAutoDST;
  48. INT gUnattenedTimeZone = -1;
  49. BOOL DateTimeBadUnattend;
  50. HWND ghWnd; // global copy of the handle to the wizard page. This
  51. // is required by DateTimeCommitChanges during an
  52. // unattended installation.
  53. BOOL
  54. ReadZoneData(
  55. PTZINFO zone,
  56. HKEY key,
  57. LPCWSTR keyname
  58. )
  59. {
  60. WCHAR mapinfo[16];
  61. DWORD len;
  62. len = sizeof(zone->szDisplayName);
  63. if (RegQueryValueEx( key,
  64. REGVAL_TZ_DISPLAY,
  65. 0,
  66. NULL,
  67. (LPBYTE)zone->szDisplayName,
  68. &len ) != ERROR_SUCCESS)
  69. {
  70. return (FALSE);
  71. }
  72. //
  73. // Under NT, the keyname is the "Standard" name. Values stored
  74. // under the keyname contain the other strings and binary info
  75. // related to the time zone. Every time zone must have a standard
  76. // name, therefore, we save registry space by using the Standard
  77. // name as the subkey name under the "Time Zones" key.
  78. //
  79. len = sizeof(zone->szStandardName);
  80. if (RegQueryValueEx( key,
  81. REGVAL_TZ_STD,
  82. 0,
  83. NULL,
  84. (LPBYTE)zone->szStandardName,
  85. &len ) != ERROR_SUCCESS)
  86. {
  87. //
  88. // Use keyname if can't get StandardName value.
  89. //
  90. lstrcpyn( zone->szStandardName,
  91. keyname,
  92. sizeof(zone->szStandardName) );
  93. }
  94. len = sizeof(zone->szDaylightName);
  95. if (RegQueryValueEx( key,
  96. REGVAL_TZ_DAYLIGHT,
  97. 0,
  98. NULL,
  99. (LPBYTE)zone->szDaylightName,
  100. &len ) != ERROR_SUCCESS)
  101. {
  102. return (FALSE);
  103. }
  104. len = sizeof(zone->ReferenceIndex);
  105. if (RegQueryValueEx( key,
  106. REGVAL_TZ_INDEX,
  107. 0,
  108. NULL,
  109. (LPBYTE)&zone->ReferenceIndex,
  110. &len ) != ERROR_SUCCESS)
  111. {
  112. return (FALSE);
  113. }
  114. len = sizeof(zone->Bias) +
  115. sizeof(zone->StandardBias) +
  116. sizeof(zone->DaylightBias) +
  117. sizeof(zone->StandardDate) +
  118. sizeof(zone->DaylightDate);
  119. if (RegQueryValueEx( key,
  120. REGVAL_TZ_TZI,
  121. 0,
  122. NULL,
  123. (LPBYTE)&zone->Bias,
  124. &len ) != ERROR_SUCCESS)
  125. {
  126. return (FALSE);
  127. }
  128. return (TRUE);
  129. }
  130. #if MYDEBUG
  131. void
  132. PrintZones(
  133. void
  134. )
  135. {
  136. PLIST_ENTRY NextZone;
  137. PTZINFO zone;
  138. NextZone = ZoneList.Flink;
  139. if (NextZone) {
  140. DebugPrint(( L"----------------- time zone list -------------------------------------\n" ));
  141. while (NextZone != &ZoneList) {
  142. zone = CONTAINING_RECORD( NextZone, TZINFO, ListEntry );
  143. NextZone = zone->ListEntry.Flink;
  144. DebugPrint(( L"%03d %s", zone->ReferenceIndex, zone->szDisplayName ));
  145. }
  146. }
  147. }
  148. #endif
  149. void
  150. AddZoneToList(
  151. PTZINFO zone
  152. )
  153. {
  154. PLIST_ENTRY NextZone;
  155. PTZINFO ThisZone;
  156. if (IsListEmpty( &ZoneList )) {
  157. InsertHeadList( &ZoneList, &zone->ListEntry );
  158. return;
  159. }
  160. NextZone = ZoneList.Flink;
  161. while (NextZone != &ZoneList)
  162. {
  163. ThisZone = CONTAINING_RECORD( NextZone, TZINFO, ListEntry );
  164. NextZone = ThisZone->ListEntry.Flink;
  165. if (ThisZone->ReferenceIndex > zone->ReferenceIndex) {
  166. InsertTailList( &ThisZone->ListEntry, &zone->ListEntry );
  167. return;
  168. }
  169. }
  170. InsertTailList( &ZoneList, &zone->ListEntry );
  171. }
  172. int
  173. BuildTimeZoneList(
  174. void
  175. )
  176. {
  177. HKEY key = NULL;
  178. int count = -1;
  179. InitializeListHead( &ZoneList );
  180. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_TIMEZONES, &key ) == ERROR_SUCCESS)
  181. {
  182. WCHAR name[TZNAME_SIZE];
  183. PTZINFO zone = NULL;
  184. int i;
  185. count = 0;
  186. for (i = 0; RegEnumKey( key, i, name, TZNAME_SIZE ) == ERROR_SUCCESS; i++)
  187. {
  188. HKEY subkey = NULL;
  189. if (!zone &&
  190. ((zone = (PTZINFO)LocalAlloc(LPTR, sizeof(TZINFO))) == NULL))
  191. {
  192. break;
  193. }
  194. if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS)
  195. {
  196. //
  197. // Each sub key name under the Time Zones key is the
  198. // "Standard" name for the Time Zone.
  199. //
  200. lstrcpyn(zone->szStandardName, name, TZNAME_SIZE);
  201. if (ReadZoneData(zone, subkey, name))
  202. {
  203. AddZoneToList(zone);
  204. zone = NULL;
  205. count++;
  206. }
  207. RegCloseKey(subkey);
  208. }
  209. }
  210. RegCloseKey(key);
  211. }
  212. return count;
  213. }
  214. void
  215. DateTimeInit(
  216. void
  217. )
  218. {
  219. DWORD d;
  220. BuildTimeZoneList();
  221. #if MYDEBUG
  222. PrintZones();
  223. #endif
  224. if ((SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) == 0) {
  225. return;
  226. }
  227. HINF InfHandle = SetupInitComponent.HelperRoutines.GetInfHandle(
  228. INFINDEX_UNATTENDED,
  229. SetupInitComponent.HelperRoutines.OcManagerContext
  230. );
  231. if (InfHandle == NULL) {
  232. DateTimeBadUnattend = TRUE;
  233. return;
  234. }
  235. INFCONTEXT InfLine;
  236. if (!SetupFindFirstLine(InfHandle, L"GuiUnattended", L"TimeZone", &InfLine )) {
  237. DateTimeBadUnattend = TRUE;
  238. return;
  239. }
  240. if (SetupGetIntField( &InfLine, 1, (PINT)&d )) {
  241. gUnattenedTimeZone = (INT) d;
  242. } else {
  243. DateTimeBadUnattend = TRUE;
  244. }
  245. }
  246. void
  247. SetAllowLocalTimeChange(
  248. BOOL fAllow
  249. )
  250. {
  251. HKEY key = NULL;
  252. if (fAllow)
  253. {
  254. //
  255. // Remove the disallow flag from the registry if it exists.
  256. //
  257. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_TIMEZONE_INFO, &key ) == ERROR_SUCCESS)
  258. {
  259. RegDeleteValue(key, REGVAL_TZNOAUTOTIME);
  260. }
  261. }
  262. else
  263. {
  264. //
  265. // Add/set the nonzero disallow flag.
  266. //
  267. if (RegCreateKey( HKEY_LOCAL_MACHINE, REGKEY_TIMEZONE_INFO, &key ) == ERROR_SUCCESS)
  268. {
  269. DWORD value = 1;
  270. RegSetValueEx( key,
  271. REGVAL_TZNOAUTOTIME,
  272. 0,
  273. REG_DWORD,
  274. (LPBYTE)&value,
  275. sizeof(value) );
  276. }
  277. }
  278. if (key)
  279. {
  280. RegCloseKey(key);
  281. }
  282. }
  283. BOOL
  284. GetAllowLocalTimeChange(
  285. void
  286. )
  287. {
  288. //
  289. // Assume allowed until we see a disallow flag.
  290. //
  291. BOOL result = TRUE;
  292. HKEY key;
  293. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_TIMEZONE_INFO, &key ) == ERROR_SUCCESS)
  294. {
  295. //
  296. // Assume no disallow flag until we see one.
  297. //
  298. DWORD value = 0;
  299. DWORD len = sizeof(value);
  300. DWORD type;
  301. if ((RegQueryValueEx( key,
  302. REGVAL_TZNOAUTOTIME,
  303. NULL,
  304. &type,
  305. (LPBYTE)&value,
  306. &len ) == ERROR_SUCCESS) &&
  307. ((type == REG_DWORD) || (type == REG_BINARY)) &&
  308. (len == sizeof(value)) && value)
  309. {
  310. //
  311. // Okay, we have a nonzero value, it is either:
  312. //
  313. // 1) 0xFFFFFFFF
  314. // this is set in an inf file for first boot to prevent
  315. // the base from performing any cutovers during setup.
  316. //
  317. // 2) some other value
  318. // this signifies that the user actualy disabled cutovers
  319. // *return that local time changes are disabled
  320. //
  321. if (value != 0xFFFFFFFF)
  322. {
  323. result = FALSE;
  324. }
  325. }
  326. RegCloseKey(key);
  327. }
  328. return (result);
  329. }
  330. void
  331. SetTheTimezone(
  332. BOOL bAutoMagicTimeChange,
  333. PTZINFO ptzi
  334. )
  335. {
  336. TIME_ZONE_INFORMATION tzi;
  337. HCURSOR hCurOld;
  338. if (!ptzi)
  339. {
  340. return;
  341. }
  342. tzi.Bias = ptzi->Bias;
  343. if ((bAutoMagicTimeChange == 0) || (ptzi->StandardDate.wMonth == 0))
  344. {
  345. //
  346. // Standard Only.
  347. //
  348. tzi.StandardBias = ptzi->StandardBias;
  349. tzi.DaylightBias = ptzi->StandardBias;
  350. tzi.StandardDate = ptzi->StandardDate;
  351. tzi.DaylightDate = ptzi->StandardDate;
  352. lstrcpy(tzi.StandardName, ptzi->szStandardName);
  353. lstrcpy(tzi.DaylightName, ptzi->szStandardName);
  354. }
  355. else
  356. {
  357. //
  358. // Automatically adjust for Daylight Saving Time.
  359. //
  360. tzi.StandardBias = ptzi->StandardBias;
  361. tzi.DaylightBias = ptzi->DaylightBias;
  362. tzi.StandardDate = ptzi->StandardDate;
  363. tzi.DaylightDate = ptzi->DaylightDate;
  364. lstrcpy(tzi.StandardName, ptzi->szStandardName);
  365. lstrcpy(tzi.DaylightName, ptzi->szDaylightName);
  366. }
  367. SetAllowLocalTimeChange( bAutoMagicTimeChange );
  368. SetTimeZoneInformation( &tzi );
  369. }
  370. void
  371. DateTimeApplyChanges(
  372. void
  373. )
  374. {
  375. SYSTEMTIME SysTime;
  376. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) {
  377. return;
  378. }
  379. // Note that in the unattended case we will never have ChangeTime set
  380. // as the page never is used except for the timezone stuff. There is
  381. // no support to set date/time via unattend.
  382. if (ChangeTime) {
  383. SysTime.wHour = SelectedTime.wHour;
  384. SysTime.wMinute = SelectedTime.wMinute;
  385. SysTime.wSecond = SelectedTime.wSecond;
  386. SysTime.wMilliseconds = SelectedTime.wMilliseconds;
  387. } else {
  388. GetLocalTime( &SysTime );
  389. }
  390. // If this is an unattended setup the PSN_WIZNEXT never arrived so it is
  391. // necessary to check the state of ICD_DAYTIME which was set by DateTimeOnInitDialog().
  392. if ((SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) && gUnattenedTimeZone != -1) {
  393. // This is unattended.
  394. AllowAutoDST = IsDlgButtonChecked( ghWnd, IDC_DAYLIGHT ) != 0;
  395. }
  396. else
  397. {
  398. // This is NOT UNATTENDED. SelectedDate was initialized when PSN_WIZNEXT
  399. // was processed.
  400. SysTime.wYear = SelectedDate.wYear;
  401. SysTime.wMonth = SelectedDate.wMonth;
  402. SysTime.wDayOfWeek = SelectedDate.wDayOfWeek;
  403. SysTime.wDay = SelectedDate.wDay;
  404. }
  405. // Function SetLocalTime uses Time Zone information so it is IMPERATIVE that
  406. // SetTheTimezone get called before SetLocalTime.
  407. SetTheTimezone( AllowAutoDST, CurrZone );
  408. SetLocalTime( &SysTime );
  409. }
  410. void
  411. DateTimeCommitChanges(
  412. void
  413. )
  414. {
  415. return;
  416. }
  417. /////////////////////////////////////////////////////////////////////////////
  418. //++
  419. //
  420. // GetTimeZoneReferenceIndexFromRegistry
  421. //
  422. // Routine Description:
  423. // This funecion extracts the Time Zone reference index from information that
  424. // is stored in the registry.
  425. //
  426. // Arguments:
  427. // None
  428. //
  429. // Return Value:
  430. // The Time Zone reference index. If no valid reference index is deduced
  431. // this function will return zero.
  432. //
  433. // Note:
  434. // The logic performed by the following function was originally implemented in
  435. // DateTimeOnInitDialog.
  436. //
  437. //--
  438. /////////////////////////////////////////////////////////////////////////////
  439. int GetTimeZoneReferenceIndexFromRegistry( void )
  440. {
  441. int xReferenceIndex;
  442. HKEY hKey;
  443. // Attempt to open the Time Zones registry key.
  444. if ( RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_TIMEZONES, &hKey ) == ERROR_SUCCESS )
  445. {
  446. // The following call to RegQueryValueEx retrieves the size, in bytes, of
  447. // the IndexMapping registry value, in parameter "index".
  448. int xIndexMapSize;
  449. if ( RegQueryValueEx( hKey, REGVAL_TZ_INDEXMAP, 0, NULL, NULL,
  450. (LPDWORD) &xIndexMapSize ) == ERROR_SUCCESS )
  451. {
  452. // Allocate memory for the IndexMap registry value.
  453. LPWSTR wszIndexMap;
  454. wszIndexMap = (LPWSTR) LocalAlloc( LPTR, xIndexMapSize );
  455. // Was a buffer allocated successfully?
  456. if ( wszIndexMap != (LPWSTR) NULL )
  457. {
  458. // This call to RegQueryValueEx retrieves the IndexMap value into
  459. // the buffer, wszIndexMap.
  460. if ( RegQueryValueEx( hKey, REGVAL_TZ_INDEXMAP, 0, NULL,
  461. (LPBYTE) wszIndexMap,
  462. (LPDWORD) &xIndexMapSize ) == ERROR_SUCCESS )
  463. {
  464. // Get the language identifier.
  465. WCHAR wszLangStr[32];
  466. if ( GetLocaleInfo( LOCALE_USER_DEFAULT,
  467. LOCALE_ILANGUAGE, wszLangStr,
  468. sizeof( wszLangStr )/sizeof( WCHAR ) ) > 0 )
  469. {
  470. LPWSTR lang = wszLangStr;
  471. LPWSTR map = wszIndexMap;
  472. while ( *lang == L'0' ) lang++;
  473. while ( *map )
  474. {
  475. if ( _wcsicmp( lang, map ) == 0 )
  476. {
  477. while ( *map ) map++;
  478. map++;
  479. xReferenceIndex = _wtol( map );
  480. break;
  481. }
  482. while ( *map ) map++;
  483. map++;
  484. while ( *map ) map++;
  485. map++;
  486. } // end of while loop
  487. } // language identifier obtained?
  488. } // IndexMapping reg value queried?
  489. LocalFree( wszIndexMap );
  490. } // memory allocated for ImageMap reg value retrieval?
  491. else
  492. {
  493. xReferenceIndex = 0;
  494. } // memory allocated for ImageMap reg value retrieval?
  495. } // Size of ImageMap obtained?
  496. else
  497. {
  498. xReferenceIndex = 0;
  499. } // Size of ImageMap obtained?
  500. RegCloseKey( hKey );
  501. } // TimeZones reg key opened?
  502. else
  503. {
  504. xReferenceIndex = 0;
  505. } // TimeZones reg key opened?
  506. return ( xReferenceIndex );
  507. }
  508. BOOL
  509. DateTimeOnInitDialog(
  510. IN HWND hwnd,
  511. IN HWND hwndFocus,
  512. IN LPARAM lParam
  513. )
  514. {
  515. PLIST_ENTRY NextZone;
  516. PTZINFO zone;
  517. HWND combo;
  518. WCHAR LangStr[32];
  519. int DesiredZone = 0;
  520. int index;
  521. HKEY hKey;
  522. LPWSTR IndexMap;
  523. ghWnd = hwnd; // initialize the global copy of the handle to the
  524. // wizard page. ghWnd is used by DateTimeCommitChanges()
  525. // during unattended setup.
  526. SetTimer( hwnd, TIMER_ID, OPEN_TLEN, 0 );
  527. if ( (SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) && gUnattenedTimeZone != -1 )
  528. {
  529. //
  530. // We've got an unattended time zone value
  531. //
  532. // If everything were perfect DesiredZone will exactly match the ReferenceIndex
  533. // member of one of the TZINFO structures in ZoneList. Note that ZoneList was
  534. // built by BuildTimeZoneList.
  535. DesiredZone = gUnattenedTimeZone;
  536. }
  537. else
  538. {
  539. //
  540. // Base the default zone on the locale
  541. //
  542. // Extract the reference index for the desired time zone from the registry.
  543. DesiredZone = GetTimeZoneReferenceIndexFromRegistry();
  544. } // Time zone specified in unattended setup answer file?
  545. #if MYDEBUG
  546. DebugPrint(( L"DesiredZone = %03d", DesiredZone ));
  547. #endif
  548. combo = GetDlgItem( hwnd, IDC_TIMEZONE );
  549. SetWindowRedraw( combo, FALSE );
  550. PTZINFO pTimeZoneInfo = (PTZINFO) NULL;
  551. // Note that ZoneList was built by BuildTimeZoneList.
  552. NextZone = ZoneList.Flink;
  553. if ( NextZone )
  554. {
  555. // Add time zones to the combo box.
  556. while ( NextZone != &ZoneList )
  557. {
  558. zone = CONTAINING_RECORD( NextZone, TZINFO, ListEntry );
  559. NextZone = zone->ListEntry.Flink;
  560. index = ComboBox_AddString( combo, zone->szDisplayName );
  561. #if MYDEBUG
  562. DebugPrint(( L"%03d,%03d %s", index, zone->ReferenceIndex, zone->szDisplayName ));
  563. #endif
  564. if ( index < 0 )
  565. {
  566. break;
  567. }
  568. ComboBox_SetItemData( combo, index, (LPARAM)zone );
  569. if ( DesiredZone == zone->ReferenceIndex )
  570. {
  571. pTimeZoneInfo = zone;
  572. #if MYDEBUG
  573. DebugPrint(( L" Found DesiredZone" ));
  574. #endif
  575. }
  576. } // end of while loop
  577. }
  578. // Was a time zone that matched DesiredZone identified?
  579. if ( pTimeZoneInfo != (PTZINFO) NULL )
  580. {
  581. // Set the GLOBAL Time Zone Info structure pointer.
  582. CurrZone = pTimeZoneInfo;
  583. }
  584. else
  585. {
  586. // The fact that pTimeZoneInfo remained unchanged from its' initialized state
  587. // means that DesiredZone is not meaningfull.
  588. // Was DesiredZone obtained from the unattended setup answer file?
  589. if ( gUnattenedTimeZone != -1 )
  590. {
  591. // DesiredZone was obtained from the answer file. Since it is not meaningfull,
  592. // attempt to deduce it from registry information. Deducing DesiredZone from
  593. // information in the registry is the default action for ATTENDED setup.
  594. DesiredZone = GetTimeZoneReferenceIndexFromRegistry();
  595. } // Was DesiredZone obtained from the answer file?
  596. // Is DesiredZone meaningfull now?
  597. if ( DesiredZone != 0 )
  598. {
  599. // Scan the list of Time Zones for one that matches DesiredZone.
  600. NextZone = ZoneList.Flink;
  601. if ( NextZone )
  602. {
  603. while ( NextZone != &ZoneList )
  604. {
  605. zone = CONTAINING_RECORD( NextZone, TZINFO, ListEntry );
  606. NextZone = zone->ListEntry.Flink;
  607. #if MYDEBUG
  608. DebugPrint(( L"%03d,%03d %s", index, zone->ReferenceIndex, zone->szDisplayName ));
  609. #endif
  610. if ( DesiredZone == zone->ReferenceIndex )
  611. {
  612. pTimeZoneInfo = zone;
  613. }
  614. } // end of while loop
  615. } // Is NextZone legal?
  616. } // Is DesiredZone meaningfull now?
  617. // Was a time zone that matched DesiredZone identified?
  618. Assert( pTimeZoneInfo != (PTZINFO) NULL );
  619. if ( pTimeZoneInfo != (PTZINFO) NULL )
  620. {
  621. // Set the GLOBAL Time Zone Info structure pointer.
  622. CurrZone = pTimeZoneInfo;
  623. }
  624. else
  625. {
  626. // Use the first Time Zone in the list as a default.
  627. CurrZone = CONTAINING_RECORD( ZoneList.Flink, TZINFO, ListEntry );
  628. #if MYDEBUG
  629. DebugPrint(( L"Couldn't find default timzone" ));
  630. #endif
  631. } // Was a time zone that matched DesiredZone identified?
  632. } // Was a time zone that matched DesiredZone identified?
  633. index = ComboBox_FindString( combo, 0, CurrZone->szDisplayName );
  634. if ( index == CB_ERR )
  635. {
  636. index = 0;
  637. }
  638. ComboBox_SetCurSel( combo, index );
  639. EnableWindow( GetDlgItem( hwnd, IDC_DAYLIGHT ), CurrZone->StandardDate.wMonth != 0 );
  640. CheckDlgButton( hwnd, IDC_DAYLIGHT, GetAllowLocalTimeChange() );
  641. SetWindowRedraw(combo, TRUE);
  642. return FALSE;
  643. }
  644. BOOL
  645. DateTimeOnCommand(
  646. IN HWND hwnd,
  647. IN DWORD NotifyCode,
  648. IN DWORD ControlId,
  649. IN HWND hwndControl
  650. )
  651. {
  652. if (NotifyCode == CBN_SELCHANGE && ControlId == IDC_TIMEZONE) {
  653. CurrZone = (PTZINFO) ComboBox_GetItemData( hwndControl, ComboBox_GetCurSel( hwndControl ) );
  654. EnableWindow( GetDlgItem( hwnd, IDC_DAYLIGHT ), CurrZone->StandardDate.wMonth != 0 );
  655. if (CurrZone->StandardDate.wMonth != 0) {
  656. CheckDlgButton( hwnd, IDC_DAYLIGHT, TRUE );
  657. } else {
  658. CheckDlgButton( hwnd, IDC_DAYLIGHT, FALSE );
  659. }
  660. return FALSE;
  661. }
  662. return TRUE;
  663. }
  664. BOOL
  665. DateTimeOnNotify(
  666. IN HWND hwnd,
  667. IN WPARAM ControlId,
  668. IN LPNMHDR pnmh
  669. )
  670. {
  671. switch( pnmh->code ) {
  672. case PSN_SETACTIVE:
  673. if (SetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) {
  674. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 );
  675. return TRUE;
  676. }
  677. if ((SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) && DateTimeBadUnattend) {
  678. // No unattend value for time date in the unattend case.
  679. // make sure the wizard is shown.
  680. // note: When we get out here, only the next button is enabled.
  681. SetupInitComponent.HelperRoutines.ShowHideWizardPage(
  682. SetupInitComponent.HelperRoutines.OcManagerContext,
  683. TRUE);
  684. return FALSE;
  685. }
  686. if ((SetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) && gUnattenedTimeZone != -1) {
  687. //
  688. // we're in unattend mode
  689. //
  690. DateTimeApplyChanges();
  691. SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 );
  692. return TRUE;
  693. }
  694. // If we get here the user needs has click next or back.
  695. // Make sure the wizard page is showing.
  696. // For Whistler GUI mode we try to hide wizard pages and show a background
  697. // billboard if there is only a progress bar.
  698. //
  699. SetupInitComponent.HelperRoutines.ShowHideWizardPage(
  700. SetupInitComponent.HelperRoutines.OcManagerContext,
  701. TRUE);
  702. PropSheet_SetWizButtons(GetParent(hwnd), PSWIZB_BACK | PSWIZB_NEXT);
  703. break;
  704. case DTN_DATETIMECHANGE:
  705. if (ControlId == IDC_TIME_PICKER) {
  706. KillTimer( hwnd, TIMER_ID );
  707. ChangeTime = TRUE;
  708. } else if (ControlId == IDC_DATE_PICKER) {
  709. ChangeDate = TRUE;
  710. }
  711. break;
  712. case PSN_WIZNEXT:
  713. SendDlgItemMessage( hwnd, IDC_TIME_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&SelectedTime );
  714. SendDlgItemMessage( hwnd, IDC_DATE_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&SelectedDate );
  715. AllowAutoDST = IsDlgButtonChecked( hwnd, IDC_DAYLIGHT ) != 0;
  716. DateTimeApplyChanges();
  717. break;
  718. }
  719. return FALSE;
  720. }
  721. BOOL
  722. DateTimeOnTimer(
  723. IN HWND hwnd
  724. )
  725. {
  726. SYSTEMTIME CurrTime;
  727. GetLocalTime( &CurrTime );
  728. SendDlgItemMessage( hwnd, IDC_TIME_PICKER, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&CurrTime );
  729. return FALSE;
  730. }
  731. LRESULT
  732. DateTimeDlgProc(
  733. HWND hwnd,
  734. UINT message,
  735. WPARAM wParam,
  736. LPARAM lParam
  737. )
  738. {
  739. CommonWizardProc( hwnd, message, wParam, lParam, WizPageDateTime );
  740. switch( message ) {
  741. case WM_INITDIALOG:
  742. return DateTimeOnInitDialog( hwnd, (HWND)wParam, lParam );
  743. case WM_COMMAND:
  744. return DateTimeOnCommand( hwnd, HIWORD(wParam), LOWORD(wParam), (HWND)lParam );
  745. case WM_TIMER:
  746. return DateTimeOnTimer( hwnd );
  747. case WM_NOTIFY:
  748. return DateTimeOnNotify( hwnd, wParam, (LPNMHDR) lParam );
  749. }
  750. return FALSE;
  751. }