Enable automatic adjustment of daylight savings changes.
[reactos.git] / reactos / lib / syssetup / wizard.c
index e1db58e..d5ee644 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: wizard.c,v 1.7 2004/09/24 18:51:52 ekohl Exp $
+/* $Id: wizard.c,v 1.12 2004/11/11 12:23:43 ekohl Exp $
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS system libraries
@@ -98,7 +98,7 @@ CreateTitleFont(VOID)
 }
 
 
-BOOL CALLBACK
+INT_PTR CALLBACK
 WelcomeDlgProc(HWND hwndDlg,
                UINT uMsg,
                WPARAM wParam,
@@ -164,7 +164,7 @@ WelcomeDlgProc(HWND hwndDlg,
 }
 
 
-BOOL CALLBACK
+INT_PTR CALLBACK
 OwnerPageDlgProc(HWND hwndDlg,
                  UINT uMsg,
                  WPARAM wParam,
@@ -254,7 +254,7 @@ OwnerPageDlgProc(HWND hwndDlg,
 }
 
 
-BOOL CALLBACK
+INT_PTR CALLBACK
 ComputerPageDlgProc(HWND hwndDlg,
                     UINT uMsg,
                     WPARAM wParam,
@@ -355,7 +355,100 @@ ComputerPageDlgProc(HWND hwndDlg,
 }
 
 
-BOOL CALLBACK
+static VOID
+SetKeyboardLayoutName(HWND hwnd)
+{
+#if 0
+  WCHAR szLayoutPath[256];
+  WCHAR szLocaleName[32];
+  DWORD dwLocaleSize;
+  HKEY hKey;
+
+  if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                   L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Locale",
+                   0,
+                   KEY_ALL_ACCESS,
+                   &hKey))
+    return;
+
+  dwValueSize = 16 * sizeof(WCHAR);
+  if (RegQueryValueExW(hKey,
+                      NULL,
+                      NULL,
+                      NULL,
+                      szLocaleName,
+                      &dwLocaleSize))
+    {
+      RegCloseKey(hKey);
+      return;
+    }
+
+  wcscpy(szLayoutPath,
+        L"SYSTEM\\CurrentControlSet\\Control\\KeyboardLayouts\\"
+  wcscat(szLayoutPath,
+        szLocaleName);
+
+  if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                   szLayoutPath,
+                   0,
+                   KEY_ALL_ACCESS,
+                   &hKey))
+    return;
+
+  dwValueSize = 32 * sizeof(WCHAR);
+  if (RegQueryValueExW(hKey,
+                      L"Layout Text",
+                      NULL,
+                      NULL,
+                      szLocaleName,
+                      &dwLocaleSize))
+    {
+      RegCloseKey(hKey);
+      return;
+    }
+
+  RegCloseKey(hKey);
+#endif
+}
+
+static VOID
+RunLocalePage(VOID)
+{
+  PROPSHEETPAGE psp;
+  PROPSHEETHEADER psh;
+  HMODULE hDll;
+//  TCHAR Caption[256];
+
+  hDll = LoadLibraryW(L"intl.cpl");
+
+  ZeroMemory(&psp, sizeof(PROPSHEETPAGE));
+  psp.dwSize = sizeof(PROPSHEETPAGE);
+  psp.dwFlags = PSP_DEFAULT;
+  psp.hInstance = hDll;
+  psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE);
+  psp.pfnDlgProc = GetProcAddress(hDll, "LocalePageProc");
+
+
+//  LoadString(hDll, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR));
+
+  ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
+  psh.dwSize = sizeof(PROPSHEETHEADER);
+  psh.dwFlags =  PSH_PROPSHEETPAGE; // | PSH_PROPTITLE;
+  psh.hwndParent = NULL;
+  psh.hInstance = hDll;
+//  psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON));
+//  psh.pszCaption = Caption;
+  psh.nPages = 1;
+  psh.nStartPage = 0;
+  psh.ppsp = &psp;
+
+  PropertySheet(&psh);
+
+  FreeLibrary(hDll);
+}
+
+
+INT_PTR CALLBACK
 LocalePageDlgProc(HWND hwndDlg,
                   UINT uMsg,
                   WPARAM wParam,
@@ -364,7 +457,397 @@ LocalePageDlgProc(HWND hwndDlg,
   PSETUPDATA SetupData;
 
   /* Retrieve pointer to the global setup data */
-  SetupData = (PSETUPDATA)GetWindowLong (hwndDlg, GWL_USERDATA);
+  SetupData = (PSETUPDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
+
+  switch (uMsg)
+    {
+      case WM_INITDIALOG:
+        {
+          /* Save pointer to the global setup data */
+          SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+          SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)SetupData);
+
+
+          SetKeyboardLayoutName(GetDlgItem(hwndDlg, IDC_LAYOUTTEXT));
+
+        }
+        break;
+
+      case WM_COMMAND:
+       if (HIWORD(wParam) == BN_CLICKED)
+         {
+           switch (LOWORD(wParam))
+             {
+               case IDC_CUSTOMLOCALE:
+                 {
+                   RunLocalePage();
+                 }
+                 break;
+             }
+         }
+       break;
+
+      case WM_NOTIFY:
+        {
+          LPNMHDR lpnm = (LPNMHDR)lParam;
+
+          switch (lpnm->code)
+            {
+              case PSN_SETACTIVE:
+                /* Enable the Back and Next buttons */
+                PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
+                break;
+
+              case PSN_WIZNEXT:
+                break;
+
+              default:
+                break;
+            }
+        }
+        break;
+
+      default:
+        break;
+    }
+
+  return FALSE;
+}
+
+
+static PTIMEZONE_ENTRY
+GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD Index)
+{
+  PTIMEZONE_ENTRY Entry;
+
+  Entry = SetupData->TimeZoneListHead;
+  while (Entry != NULL)
+    {
+      if (Entry->Index >= Index)
+       return Entry;
+
+      Entry = Entry->Next;
+    }
+
+  return NULL;
+}
+
+
+static VOID
+CreateTimeZoneList(PSETUPDATA SetupData)
+{
+  WCHAR szKeyName[256];
+  DWORD dwIndex;
+  DWORD dwNameSize;
+  DWORD dwValueSize;
+  LONG lError;
+  HKEY hZonesKey;
+  HKEY hZoneKey;
+
+  PTIMEZONE_ENTRY Entry;
+  PTIMEZONE_ENTRY Current;
+
+  if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                   L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
+                   0,
+                   KEY_ALL_ACCESS,
+                   &hZonesKey))
+    return;
+
+  dwIndex = 0;
+  while (TRUE)
+    {
+      dwNameSize = 256;
+      lError = RegEnumKeyExW(hZonesKey,
+                            dwIndex,
+                            szKeyName,
+                            &dwNameSize,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL);
+      if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
+       break;
+
+      if (RegOpenKeyExW(hZonesKey,
+                       szKeyName,
+                       0,
+                       KEY_ALL_ACCESS,
+                       &hZoneKey))
+       break;
+
+      Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
+      if (Entry == NULL)
+       {
+         RegCloseKey(hZoneKey);
+         break;
+       }
+
+      dwValueSize = 64 * sizeof(WCHAR);
+      if (RegQueryValueExW(hZoneKey,
+                          L"Display",
+                          NULL,
+                          NULL,
+                          (LPBYTE)&Entry->Description,
+                          &dwValueSize))
+       {
+         RegCloseKey(hZoneKey);
+         break;
+       }
+
+      dwValueSize = 32 * sizeof(WCHAR);
+      if (RegQueryValueExW(hZoneKey,
+                          L"Std",
+                          NULL,
+                          NULL,
+                          (LPBYTE)&Entry->StandardName,
+                          &dwValueSize))
+       {
+         RegCloseKey(hZoneKey);
+         break;
+       }
+
+      dwValueSize = 32 * sizeof(WCHAR);
+      if (RegQueryValueExW(hZoneKey,
+                          L"Dlt",
+                          NULL,
+                          NULL,
+                          (LPBYTE)&Entry->DaylightName,
+                          &dwValueSize))
+       {
+         RegCloseKey(hZoneKey);
+         break;
+       }
+
+      dwValueSize = sizeof(DWORD);
+      if (RegQueryValueExW(hZoneKey,
+                          L"Index",
+                          NULL,
+                          NULL,
+                          (LPBYTE)&Entry->Index,
+                          &dwValueSize))
+       {
+         RegCloseKey(hZoneKey);
+         break;
+       }
+
+      dwValueSize = sizeof(TZ_INFO);
+      if (RegQueryValueExW(hZoneKey,
+                          L"TZI",
+                          NULL,
+                          NULL,
+                          (LPBYTE)&Entry->TimezoneInfo,
+                          &dwValueSize))
+       {
+         RegCloseKey(hZoneKey);
+         break;
+       }
+
+      RegCloseKey(hZoneKey);
+
+      if (SetupData->TimeZoneListHead == NULL &&
+         SetupData->TimeZoneListTail == NULL)
+       {
+         Entry->Prev = NULL;
+         Entry->Next = NULL;
+         SetupData->TimeZoneListHead = Entry;
+         SetupData->TimeZoneListTail = Entry;
+       }
+      else
+       {
+         Current = GetLargerTimeZoneEntry(SetupData, Entry->Index);
+         if (Current != NULL)
+           {
+             if (Current == SetupData->TimeZoneListHead)
+               {
+                 /* Prepend to head */
+                 Entry->Prev = NULL;
+                 Entry->Next = SetupData->TimeZoneListHead;
+                 SetupData->TimeZoneListHead->Prev = Entry;
+                 SetupData->TimeZoneListHead = Entry;
+               }
+             else
+               {
+                 /* Insert before current */
+                 Entry->Prev = Current->Prev;
+                 Entry->Next = Current;
+                 Current->Prev->Next = Entry;
+                 Current->Prev = Entry;
+               }
+           }
+         else
+           {
+             /* Append to tail */
+             Entry->Prev = SetupData->TimeZoneListTail;
+             Entry->Next = NULL;
+             SetupData->TimeZoneListTail->Next = Entry;
+             SetupData->TimeZoneListTail = Entry;
+           }
+       }
+
+      dwIndex++;
+    }
+
+  RegCloseKey(hZonesKey);
+}
+
+
+static VOID
+DestroyTimeZoneList(PSETUPDATA SetupData)
+{
+  PTIMEZONE_ENTRY Entry;
+
+  while (SetupData->TimeZoneListHead != NULL)
+    {
+      Entry = SetupData->TimeZoneListHead;
+
+      SetupData->TimeZoneListHead = Entry->Next;
+      if (SetupData->TimeZoneListHead != NULL)
+       {
+         SetupData->TimeZoneListHead->Prev = NULL;
+       }
+
+      HeapFree(GetProcessHeap(), 0, Entry);
+    }
+
+  SetupData->TimeZoneListTail = NULL;
+}
+
+
+static VOID
+ShowTimeZoneList(HWND hwnd, PSETUPDATA SetupData)
+{
+  PTIMEZONE_ENTRY Entry;
+
+  Entry = SetupData->TimeZoneListHead;
+  while (Entry != NULL)
+    {
+      SendMessageW(hwnd,
+                  CB_ADDSTRING,
+                  0,
+                  (LPARAM)Entry->Description);
+
+
+      Entry = Entry->Next;
+    }
+
+  SendMessageW(hwnd,
+              CB_SETCURSEL,
+              (WPARAM)0, // index
+              0);
+}
+
+
+static VOID
+SetLocalTimeZone(HWND hwnd, PSETUPDATA SetupData)
+{
+  TIME_ZONE_INFORMATION TimeZoneInformation;
+  PTIMEZONE_ENTRY Entry;
+  DWORD dwIndex;
+  DWORD i;
+
+  dwIndex = SendMessage(hwnd,
+                       CB_GETCURSEL,
+                       0,
+                       0);
+
+  i = 0;
+  Entry = SetupData->TimeZoneListHead;
+  while (i < dwIndex)
+    {
+      if (Entry == NULL)
+       return;
+
+      i++;
+      Entry = Entry->Next;
+    }
+
+  wcscpy(TimeZoneInformation.StandardName,
+        Entry->StandardName);
+  wcscpy(TimeZoneInformation.DaylightName,
+        Entry->DaylightName);
+
+  TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias;
+  TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias;
+  TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias;
+
+  memcpy(&TimeZoneInformation.StandardDate,
+        &Entry->TimezoneInfo.StandardDate,
+        sizeof(SYSTEMTIME));
+  memcpy(&TimeZoneInformation.DaylightDate,
+        &Entry->TimezoneInfo.DaylightDate,
+        sizeof(SYSTEMTIME));
+
+  /* Set time zone information */
+  SetTimeZoneInformation(&TimeZoneInformation);
+}
+
+
+static BOOL
+GetLocalSystemTime(HWND hwnd, PSETUPDATA SetupData)
+{
+  SYSTEMTIME Date;
+  SYSTEMTIME Time;
+
+  if (DateTime_GetSystemTime(GetDlgItem(hwnd, IDC_DATEPICKER), &Date) != GDT_VALID)
+    {
+      return FALSE;
+    }
+
+  if (DateTime_GetSystemTime(GetDlgItem(hwnd, IDC_TIMEPICKER), &Time) != GDT_VALID)
+    {
+      return FALSE;
+    }
+
+  SetupData->SystemTime.wYear = Date.wYear;
+  SetupData->SystemTime.wMonth = Date.wMonth;
+  SetupData->SystemTime.wDayOfWeek = Date.wDayOfWeek;
+  SetupData->SystemTime.wDay = Date.wDay;
+  SetupData->SystemTime.wHour = Time.wHour;
+  SetupData->SystemTime.wMinute = Time.wMinute;
+  SetupData->SystemTime.wSecond = Time.wSecond;
+  SetupData->SystemTime.wMilliseconds = Time.wMilliseconds;
+
+  return TRUE;
+}
+
+
+static VOID
+SetAutoDaylightInfo(HWND hwnd)
+{
+  HKEY hKey;
+  DWORD dwValue = 1;
+
+  if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
+    {
+      if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                       L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
+                       0,
+                       KEY_SET_VALUE,
+                       &hKey))
+         return;
+
+      RegSetValueExW(hKey,
+                    L"DisableAutoDaylightTimeSet",
+                    0,
+                    REG_DWORD,
+                    (LPBYTE)&dwValue,
+                    sizeof(DWORD));
+      RegCloseKey(hKey);
+    }
+}
+
+
+INT_PTR CALLBACK
+DateTimePageDlgProc(HWND hwndDlg,
+                    UINT uMsg,
+                    WPARAM wParam,
+                    LPARAM lParam)
+{
+  PSETUPDATA SetupData;
+
+  /* Retrieve pointer to the global setup data */
+  SetupData = (PSETUPDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
 
   switch (uMsg)
     {
@@ -372,8 +855,14 @@ LocalePageDlgProc(HWND hwndDlg,
         {
           /* Save pointer to the global setup data */
           SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
-          SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)SetupData);
+          SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)SetupData);
+
+          CreateTimeZoneList(SetupData);
 
+          ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
+                           SetupData);
+
+          SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
         }
         break;
 
@@ -390,6 +879,13 @@ LocalePageDlgProc(HWND hwndDlg,
                 break;
 
               case PSN_WIZNEXT:
+                {
+                  GetLocalSystemTime(hwndDlg, SetupData);
+                  SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
+                                   SetupData);
+                  SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
+                  SetLocalTime(&SetupData->SystemTime);
+                }
                 break;
 
               default:
@@ -398,6 +894,10 @@ LocalePageDlgProc(HWND hwndDlg,
         }
         break;
 
+      case WM_DESTROY:
+        DestroyTimeZoneList(SetupData);
+        break;
+
       default:
         break;
     }
@@ -406,7 +906,7 @@ LocalePageDlgProc(HWND hwndDlg,
 }
 
 
-BOOL CALLBACK
+INT_PTR CALLBACK
 ProcessPageDlgProc(HWND hwndDlg,
                    UINT uMsg,
                    WPARAM wParam,
@@ -415,7 +915,7 @@ ProcessPageDlgProc(HWND hwndDlg,
   PSETUPDATA SetupData;
 
   /* Retrieve pointer to the global setup data */
-  SetupData = (PSETUPDATA)GetWindowLong (hwndDlg, GWL_USERDATA);
+  SetupData = (PSETUPDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
 
   switch (uMsg)
     {
@@ -423,7 +923,7 @@ ProcessPageDlgProc(HWND hwndDlg,
         {
           /* Save pointer to the global setup data */
           SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
-          SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)SetupData);
+          SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)SetupData);
         }
         break;
 
@@ -481,7 +981,7 @@ ProcessPageDlgProc(HWND hwndDlg,
 
 
 
-BOOL CALLBACK
+INT_PTR CALLBACK
 FinishDlgProc(HWND hwndDlg,
               UINT uMsg,
               WPARAM wParam,
@@ -585,27 +1085,36 @@ InstallWizard(VOID)
   ahpsp[3] = CreatePropertySheetPage(&psp);
 
 
+  /* Create the DateTime page */
+  psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
+  psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE);
+  psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DATETIMESUBTITLE);
+  psp.pfnDlgProc = DateTimePageDlgProc;
+  psp.pszTemplate = MAKEINTRESOURCE(IDD_DATETIMEPAGE);
+  ahpsp[4] = CreatePropertySheetPage(&psp);
+
+
   /* Create the Process page */
   psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
   psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
   psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
   psp.pfnDlgProc = ProcessPageDlgProc;
   psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
-  ahpsp[4] = CreatePropertySheetPage(&psp);
+  ahpsp[5] = CreatePropertySheetPage(&psp);
 
 
   /* Create the Finish page */
   psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
   psp.pfnDlgProc = FinishDlgProc;
   psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
-  ahpsp[5] = CreatePropertySheetPage(&psp);
+  ahpsp[6] = CreatePropertySheetPage(&psp);
 
   /* Create the property sheet */
   psh.dwSize = sizeof(PROPSHEETHEADER);
   psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
   psh.hInstance = hDllInstance;
   psh.hwndParent = NULL;
-  psh.nPages = 6;
+  psh.nPages = 7;
   psh.nStartPage = 0;
   psh.phpage = ahpsp;
   psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);