[INETCPL] Fix a typo in Romanian resource file
[reactos.git] / dll / cpl / timedate / dateandtime.c
1 /*
2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/timedate/dateandtime.c
5 * PURPOSE: Date & Time property page
6 * COPYRIGHT: Copyright 2004-2007 Eric Kohl
7 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
8 * Copyright 2006 Thomas Weidenmueller <w3seek@reactos.com>
9 *
10 */
11
12 #include "timedate.h"
13
14 static WNDPROC pOldWndProc = NULL;
15
16 BOOL
17 SystemSetTime(LPSYSTEMTIME lpSystemTime,
18 BOOL SystemTime)
19 {
20 HANDLE hToken;
21 DWORD PrevSize;
22 TOKEN_PRIVILEGES priv, previouspriv;
23 BOOL Ret = FALSE;
24
25 /*
26 * Enable the SeSystemtimePrivilege privilege
27 */
28
29 if (OpenProcessToken(GetCurrentProcess(),
30 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
31 &hToken))
32 {
33 priv.PrivilegeCount = 1;
34 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
35
36 if (LookupPrivilegeValueW(NULL,
37 SE_SYSTEMTIME_NAME,
38 &priv.Privileges[0].Luid))
39 {
40 if (AdjustTokenPrivileges(hToken,
41 FALSE,
42 &priv,
43 sizeof(previouspriv),
44 &previouspriv,
45 &PrevSize) &&
46 GetLastError() == ERROR_SUCCESS)
47 {
48 /*
49 * We successfully enabled it, we're permitted to change the time.
50 * Check the second parameter for SystemTime and if TRUE set System Time.
51 * Otherwise, if FALSE set the Local Time.
52 * Call SetLocalTime twice to ensure correct results.
53 */
54 if (SystemTime)
55 {
56 Ret = SetSystemTime(lpSystemTime);
57 }
58 else
59 {
60 Ret = SetLocalTime(lpSystemTime) &&
61 SetLocalTime(lpSystemTime);
62 }
63
64 /*
65 * For the sake of security, restore the previous status again
66 */
67 if (previouspriv.PrivilegeCount > 0)
68 {
69 AdjustTokenPrivileges(hToken,
70 FALSE,
71 &previouspriv,
72 0,
73 NULL,
74 0);
75 }
76 }
77 }
78 CloseHandle(hToken);
79 }
80
81 return Ret;
82 }
83
84
85 static VOID
86 SetLocalSystemTime(HWND hwnd)
87 {
88 SYSTEMTIME Time;
89
90 if (DateTime_GetSystemtime(GetDlgItem(hwnd,
91 IDC_TIMEPICKER),
92 &Time) == GDT_VALID &&
93 SendMessageW(GetDlgItem(hwnd,
94 IDC_MONTHCALENDAR),
95 MCCM_GETDATE,
96 (WPARAM)&Time,
97 0))
98 {
99 /* Set Local Time with SystemTime = FALSE */
100 SystemSetTime(&Time, FALSE);
101
102 SetWindowLongPtrW(hwnd,
103 DWLP_MSGRESULT,
104 PSNRET_NOERROR);
105
106 SendMessageW(GetDlgItem(hwnd,
107 IDC_MONTHCALENDAR),
108 MCCM_RESET,
109 (WPARAM)&Time,
110 0);
111
112 /* Broadcast the time change message */
113 SendMessageW(HWND_BROADCAST,
114 WM_TIMECHANGE,
115 0,
116 0);
117 }
118 }
119
120
121 static VOID
122 SetTimeZoneName(HWND hwnd)
123 {
124 TIME_ZONE_INFORMATION TimeZoneInfo;
125 WCHAR TimeZoneString[128];
126 WCHAR TimeZoneText[128];
127 WCHAR TimeZoneName[128];
128 DWORD TimeZoneId;
129
130 TimeZoneId = GetTimeZoneInformation(&TimeZoneInfo);
131
132 LoadStringW(hApplet, IDS_TIMEZONETEXT, TimeZoneText, 128);
133
134 switch (TimeZoneId)
135 {
136 case TIME_ZONE_ID_STANDARD:
137 case TIME_ZONE_ID_UNKNOWN:
138 wcscpy(TimeZoneName, TimeZoneInfo.StandardName);
139 break;
140
141 case TIME_ZONE_ID_DAYLIGHT:
142 wcscpy(TimeZoneName, TimeZoneInfo.DaylightName);
143 break;
144
145 case TIME_ZONE_ID_INVALID:
146 default:
147 LoadStringW(hApplet, IDS_TIMEZONEINVALID, TimeZoneName, 128);
148 break;
149 }
150
151 wsprintfW(TimeZoneString, TimeZoneText, TimeZoneName);
152 SendDlgItemMessageW(hwnd, IDC_TIMEZONE, WM_SETTEXT, 0, (LPARAM)TimeZoneString);
153 }
154
155
156 static VOID
157 FillMonthsComboBox(HWND hCombo)
158 {
159 SYSTEMTIME LocalDate = {0};
160 WCHAR szBuf[64];
161 INT i;
162 UINT Month;
163
164 GetLocalTime(&LocalDate);
165
166 SendMessageW(hCombo,
167 CB_RESETCONTENT,
168 0,
169 0);
170
171 for (Month = 1;
172 Month <= 13;
173 Month++)
174 {
175 i = GetLocaleInfoW(LOCALE_USER_DEFAULT,
176 ((Month < 13) ? LOCALE_SMONTHNAME1 + Month - 1 : LOCALE_SMONTHNAME13),
177 szBuf,
178 sizeof(szBuf) / sizeof(szBuf[0]));
179 if (i > 1)
180 {
181 i = (INT)SendMessageW(hCombo,
182 CB_ADDSTRING,
183 0,
184 (LPARAM)szBuf);
185 if (i != CB_ERR)
186 {
187 SendMessageW(hCombo,
188 CB_SETITEMDATA,
189 (WPARAM)i,
190 Month);
191
192 if (Month == (UINT)LocalDate.wMonth)
193 {
194 SendMessageW(hCombo,
195 CB_SETCURSEL,
196 (WPARAM)i,
197 0);
198 }
199 }
200 }
201 }
202 }
203
204
205 static WORD
206 GetCBSelectedMonth(HWND hCombo)
207 {
208 INT i;
209 WORD Ret = (WORD)-1;
210
211 i = (INT)SendMessageW(hCombo,
212 CB_GETCURSEL,
213 0,
214 0);
215 if (i != CB_ERR)
216 {
217 i = (INT)SendMessageW(hCombo,
218 CB_GETITEMDATA,
219 (WPARAM)i,
220 0);
221
222 if (i >= 1 && i <= 13)
223 Ret = (WORD)i;
224 }
225
226 return Ret;
227 }
228
229
230 static VOID
231 ChangeMonthCalDate(HWND hMonthCal,
232 WORD Day,
233 WORD Month,
234 WORD Year)
235 {
236 SendMessageW(hMonthCal,
237 MCCM_SETDATE,
238 MAKEWPARAM(Day,
239 Month),
240 MAKELPARAM(Year,
241 0));
242 }
243
244 static VOID
245 AutoUpdateMonthCal(HWND hwndDlg,
246 PNMMCCAUTOUPDATE lpAutoUpdate)
247 {
248 UNREFERENCED_PARAMETER(lpAutoUpdate);
249
250 /* Update the controls */
251 FillMonthsComboBox(GetDlgItem(hwndDlg,
252 IDC_MONTHCB));
253 }
254
255
256 static INT_PTR CALLBACK
257 DTPProc(HWND hwnd,
258 UINT uMsg,
259 WPARAM wParam,
260 LPARAM lParam)
261 {
262 switch (uMsg)
263 {
264 case WM_KEYDOWN:
265 /* Stop the timer when the user is about to change the time */
266 if ((wParam != VK_LEFT) & (wParam != VK_RIGHT))
267 KillTimer(GetParent(hwnd), ID_TIMER);
268 break;
269 }
270
271 return CallWindowProcW(pOldWndProc, hwnd, uMsg, wParam, lParam);
272 }
273
274 /* Property page dialog callback */
275 INT_PTR CALLBACK
276 DateTimePageProc(HWND hwndDlg,
277 UINT uMsg,
278 WPARAM wParam,
279 LPARAM lParam)
280 {
281 SYSTEMTIME st;
282 GetLocalTime(&st);
283
284 switch (uMsg)
285 {
286 case WM_INITDIALOG:
287 FillMonthsComboBox(GetDlgItem(hwndDlg,
288 IDC_MONTHCB));
289
290 SetTimer(hwndDlg, ID_TIMER, 1000, NULL);
291
292 /* Set range and current year */
293 SendMessageW(GetDlgItem(hwndDlg, IDC_YEAR), UDM_SETRANGE, 0, MAKELONG ((short) 9999, (short) 1900));
294 SendMessageW(GetDlgItem(hwndDlg, IDC_YEAR), UDM_SETPOS, 0, MAKELONG( (short) st.wYear, 0));
295
296 pOldWndProc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_TIMEPICKER), GWLP_WNDPROC, (LONG_PTR)DTPProc);
297 break;
298
299 case WM_TIMER:
300 SendMessageW(GetDlgItem(hwndDlg, IDC_TIMEPICKER), DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM) &st);
301 break;
302
303 case WM_COMMAND:
304 switch (LOWORD(wParam))
305 {
306 case IDC_MONTHCB:
307 if (HIWORD(wParam) == CBN_SELCHANGE)
308 {
309 ChangeMonthCalDate(GetDlgItem(hwndDlg,
310 IDC_MONTHCALENDAR),
311 (WORD) -1,
312 GetCBSelectedMonth((HWND)lParam),
313 (WORD) -1);
314 }
315 break;
316 }
317 break;
318
319 case WM_CTLCOLORSTATIC:
320 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_YEARTEXT))
321 return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
322 break;
323
324 case WM_NOTIFY:
325 {
326 LPNMHDR lpnm = (LPNMHDR)lParam;
327
328 switch (lpnm->idFrom)
329 {
330 case IDC_YEAR:
331 switch (lpnm->code)
332 {
333 case UDN_DELTAPOS:
334 {
335 SHORT wYear;
336 LPNMUPDOWN updown = (LPNMUPDOWN)lpnm;
337 wYear = (SHORT)SendMessageW(GetDlgItem(hwndDlg, IDC_YEAR), UDM_GETPOS, 0, 0);
338 /* Enable the 'Apply' button */
339 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
340 ChangeMonthCalDate(GetDlgItem(hwndDlg,
341 IDC_MONTHCALENDAR),
342 (WORD) -1,
343 (WORD) -1,
344 (WORD) (wYear + updown->iDelta));
345 }
346 break;
347 }
348 break;
349
350 case IDC_TIMEPICKER:
351 switch (lpnm->code)
352 {
353 case DTN_DATETIMECHANGE:
354 /* Stop the timer */
355 KillTimer(hwndDlg, ID_TIMER);
356
357 /* Tell the clock to stop ticking */
358 SendDlgItemMessageW(hwndDlg, IDC_CLOCKWND, CLM_STOPCLOCK,
359 0, 0);
360
361 /* Enable the 'Apply' button */
362 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
363 break;
364 }
365 break;
366
367 case IDC_MONTHCALENDAR:
368 switch (lpnm->code)
369 {
370 case MCCN_SELCHANGE:
371 /* Enable the 'Apply' button */
372 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
373 break;
374
375 case MCCN_AUTOUPDATE:
376 AutoUpdateMonthCal(hwndDlg,
377 (PNMMCCAUTOUPDATE)lpnm);
378 break;
379 }
380 break;
381
382 default:
383 switch (lpnm->code)
384 {
385 case PSN_SETACTIVE:
386 SetTimeZoneName(hwndDlg);
387 break;
388
389 case PSN_APPLY:
390 SetLocalSystemTime(hwndDlg);
391 SetTimer(hwndDlg, ID_TIMER, 1000, NULL);
392
393 /* Tell the clock to start ticking */
394 SendDlgItemMessageW(hwndDlg, IDC_CLOCKWND, CLM_STARTCLOCK,
395 0, 0);
396 return TRUE;
397 }
398 break;
399 }
400 }
401 break;
402
403 case WM_TIMECHANGE:
404 /* FIXME: We don't get this message as we're not a top-level window... */
405 SendMessageW(GetDlgItem(hwndDlg,
406 IDC_MONTHCALENDAR),
407 MCCM_RESET,
408 0,
409 0);
410 break;
411
412 case WM_DESTROY:
413 KillTimer(hwndDlg, ID_TIMER);
414 break;
415 }
416
417 return FALSE;
418 }