- Keep the value type of each environment variable that was read from the registry...
[reactos.git] / reactos / dll / cpl / sysdm / environment.c
1 /*
2 * PROJECT: ReactOS System Control Panel Applet
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/sysdm/environment.c
5 * PURPOSE: Environment variable settings
6 * COPYRIGHT: Copyright Eric Kohl
7 *
8 */
9
10 #include "precomp.h"
11
12
13 typedef struct _VARIABLE_DATA
14 {
15 DWORD dwType;
16 LPTSTR lpName;
17 LPTSTR lpRawValue;
18 LPTSTR lpCookedValue;
19 } VARIABLE_DATA, *PVARIABLE_DATA;
20
21
22 INT_PTR CALLBACK
23 EditVariableDlgProc(HWND hwndDlg,
24 UINT uMsg,
25 WPARAM wParam,
26 LPARAM lParam)
27 {
28 PVARIABLE_DATA VarData;
29 DWORD dwNameLength;
30 DWORD dwValueLength;
31
32 VarData = (PVARIABLE_DATA)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
33
34 switch (uMsg)
35 {
36 case WM_INITDIALOG:
37 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (LONG_PTR)lParam);
38 VarData = (PVARIABLE_DATA)lParam;
39
40 if (VarData->lpName != NULL)
41 {
42 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_SETTEXT, 0, (LPARAM)VarData->lpName);
43 }
44
45 if (VarData->lpRawValue != NULL)
46 {
47 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_SETTEXT, 0, (LPARAM)VarData->lpRawValue);
48 }
49 break;
50
51 case WM_COMMAND:
52 switch (LOWORD(wParam))
53 {
54 case IDOK:
55 dwNameLength = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_GETTEXTLENGTH, 0, 0);
56 dwValueLength = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_GETTEXTLENGTH, 0, 0);
57 if (dwNameLength > 0 && dwValueLength > 0)
58 {
59 if (VarData->lpName == NULL)
60 {
61 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
62 }
63 else if (_tcslen(VarData->lpName) < dwNameLength)
64 {
65 GlobalFree(VarData->lpName);
66 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
67 }
68 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_GETTEXT, dwNameLength + 1, (LPARAM)VarData->lpName);
69
70 if (VarData->lpRawValue == NULL)
71 {
72 VarData->lpRawValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
73 }
74 else if (_tcslen(VarData->lpRawValue) < dwValueLength)
75 {
76 GlobalFree(VarData->lpRawValue);
77 VarData->lpRawValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
78 }
79 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_GETTEXT, dwValueLength + 1, (LPARAM)VarData->lpRawValue);
80
81 if (VarData->lpCookedValue != NULL)
82 {
83 GlobalFree(VarData->lpCookedValue);
84 VarData->lpCookedValue = NULL;
85 }
86
87 if (_tcschr(VarData->lpRawValue, _T('%')))
88 {
89 VarData->dwType = REG_EXPAND_SZ;
90 VarData->lpCookedValue = GlobalAlloc(GPTR, 2 * MAX_PATH * sizeof(TCHAR));
91
92 ExpandEnvironmentStrings(VarData->lpRawValue,
93 VarData->lpCookedValue,
94 2 * MAX_PATH);
95 }
96 else
97 {
98 VarData->dwType = REG_SZ;
99 VarData->lpCookedValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
100 _tcscpy(VarData->lpCookedValue, VarData->lpRawValue);
101 }
102 }
103 EndDialog(hwndDlg, 1);
104 return TRUE;
105
106 case IDCANCEL:
107 EndDialog(hwndDlg, 0);
108 return TRUE;
109 }
110 break;
111 }
112
113 return FALSE;
114 }
115
116
117 static VOID
118 SetEnvironmentVariables(HWND hwndListView,
119 HKEY hRootKey,
120 LPTSTR lpSubKeyName)
121 {
122 HKEY hKey;
123 DWORD dwValues;
124 DWORD dwMaxValueNameLength;
125 DWORD dwMaxValueDataLength;
126 DWORD i;
127 LPTSTR lpName;
128 LPTSTR lpData;
129 LPTSTR lpExpandData;
130 DWORD dwNameLength;
131 DWORD dwDataLength;
132 DWORD dwType;
133 PVARIABLE_DATA VarData;
134
135 LV_ITEM lvi;
136 int iItem;
137
138 if (RegOpenKeyEx(hRootKey,
139 lpSubKeyName,
140 0,
141 KEY_READ,
142 &hKey))
143 return;
144
145 if (RegQueryInfoKey(hKey,
146 NULL,
147 NULL,
148 NULL,
149 NULL,
150 NULL,
151 NULL,
152 &dwValues,
153 &dwMaxValueNameLength,
154 &dwMaxValueDataLength,
155 NULL,
156 NULL))
157 {
158 RegCloseKey(hKey);
159 return;
160 }
161
162 lpName = GlobalAlloc(GPTR, (dwMaxValueNameLength + 1) * sizeof(TCHAR));
163 if (lpName == NULL)
164 {
165 RegCloseKey(hKey);
166 return;
167 }
168
169 lpData = GlobalAlloc(GPTR, (dwMaxValueDataLength + 1) * sizeof(TCHAR));
170 if (lpData == NULL)
171 {
172 GlobalFree(lpData);
173 RegCloseKey(hKey);
174 return;
175 }
176
177 lpExpandData = GlobalAlloc(GPTR, 2048 * sizeof(TCHAR));
178 if (lpExpandData == NULL)
179 {
180 GlobalFree(lpName);
181 GlobalFree(lpData);
182 RegCloseKey(hKey);
183 return;
184 }
185
186 for (i = 0; i < dwValues; i++)
187 {
188 dwNameLength = dwMaxValueNameLength + 1;
189 dwDataLength = dwMaxValueDataLength + 1;
190
191 if (RegEnumValue(hKey,
192 i,
193 lpName,
194 &dwNameLength,
195 NULL,
196 &dwType,
197 (LPBYTE)lpData,
198 &dwDataLength))
199 {
200 GlobalFree(lpName);
201 GlobalFree(lpData);
202 RegCloseKey(hKey);
203 return;
204 }
205
206 if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
207 continue;
208
209 VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
210
211 VarData->dwType = dwType;
212
213 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
214 _tcscpy(VarData->lpName, lpName);
215
216 VarData->lpRawValue = GlobalAlloc(GPTR, (dwDataLength + 1) * sizeof(TCHAR));
217 _tcscpy(VarData->lpRawValue, lpData);
218
219 ExpandEnvironmentStrings(lpData, lpExpandData, 2048);
220
221 VarData->lpCookedValue = GlobalAlloc(GPTR, (_tcslen(lpExpandData) + 1) * sizeof(TCHAR));
222 _tcscpy(VarData->lpCookedValue, lpExpandData);
223
224 memset(&lvi, 0x00, sizeof(lvi));
225 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
226 lvi.lParam = (LPARAM)VarData;
227 lvi.pszText = VarData->lpName;
228 lvi.state = (i == 0) ? LVIS_SELECTED : 0;
229 iItem = ListView_InsertItem(hwndListView, &lvi);
230
231 ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
232 }
233
234 GlobalFree(lpExpandData);
235 GlobalFree(lpName);
236 GlobalFree(lpData);
237 RegCloseKey(hKey);
238 }
239
240
241 static VOID
242 SetListViewColumns(HWND hwndListView)
243 {
244 RECT rect;
245 LV_COLUMN column;
246 TCHAR szStr[32];
247
248 GetClientRect(hwndListView, &rect);
249
250 memset(&column, 0x00, sizeof(column));
251 column.mask=LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
252 column.fmt=LVCFMT_LEFT;
253 column.cx = (INT)((rect.right - rect.left) * 0.32);
254 column.iSubItem = 0;
255 LoadString(hApplet, IDS_VARIABLE, szStr, sizeof(szStr) / sizeof(szStr[0]));
256 column.pszText = szStr;
257 (void)ListView_InsertColumn(hwndListView, 0, &column);
258
259 column.cx = (INT)((rect.right - rect.left) * 0.63);
260 column.iSubItem = 1;
261 LoadString(hApplet, IDS_VALUE, szStr, sizeof(szStr) / sizeof(szStr[0]));
262 column.pszText = szStr;
263 (void)ListView_InsertColumn(hwndListView, 1, &column);
264 }
265
266
267 static VOID
268 OnInitDialog(HWND hwndDlg)
269 {
270 HWND hwndListView;
271
272 /* Set user environment variables */
273 hwndListView = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_LIST);
274
275 (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
276
277 SetListViewColumns(hwndListView);
278
279 SetEnvironmentVariables(hwndListView,
280 HKEY_CURRENT_USER,
281 _T("Environment"));
282
283 (void)ListView_SetColumnWidth(hwndListView,2,LVSCW_AUTOSIZE_USEHEADER);
284
285 ListView_SetItemState(hwndListView,0,LVIS_FOCUSED,LVIS_FOCUSED);
286
287 (void)ListView_Update(hwndListView,0);
288
289
290 /* Set system environment variables */
291 hwndListView = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
292
293 (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
294
295 SetListViewColumns(hwndListView);
296
297 SetEnvironmentVariables(hwndListView,
298 HKEY_LOCAL_MACHINE,
299 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"));
300
301 (void)ListView_SetColumnWidth(hwndListView,2,LVSCW_AUTOSIZE_USEHEADER);
302
303 ListView_SetItemState(hwndListView,0,LVIS_FOCUSED,LVIS_FOCUSED);
304
305 (void)ListView_Update(hwndListView,0);
306 }
307
308
309 VOID
310 OnNewVariable(HWND hwndDlg,
311 int iDlgItem)
312 {
313 HWND hwndListView;
314 PVARIABLE_DATA VarData;
315 LV_ITEM lvi;
316 int iItem;
317
318 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
319
320 VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
321
322 if (!DialogBoxParam(hApplet,
323 MAKEINTRESOURCE(IDD_EDIT_VARIABLE),
324 hwndDlg,
325 (DLGPROC)EditVariableDlgProc,
326 (LPARAM)VarData) > 0)
327 {
328 if (VarData->lpName != NULL)
329 GlobalFree(VarData->lpName);
330
331 if (VarData->lpRawValue != NULL)
332 GlobalFree(VarData->lpRawValue);
333
334 if (VarData->lpCookedValue != NULL)
335 GlobalFree(VarData->lpCookedValue);
336
337 GlobalFree(VarData);
338 }
339 else
340 {
341 if (VarData->lpName != NULL && (VarData->lpCookedValue || VarData->lpRawValue))
342 {
343 memset(&lvi, 0x00, sizeof(lvi));
344 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
345 lvi.lParam = (LPARAM)VarData;
346 lvi.pszText = VarData->lpName;
347 lvi.state = 0;
348 iItem = ListView_InsertItem(hwndListView, &lvi);
349
350 ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
351 }
352 }
353 }
354
355
356 VOID
357 OnEditVariable(HWND hwndDlg,
358 int iDlgItem)
359 {
360 HWND hwndListView;
361 PVARIABLE_DATA VarData;
362 LV_ITEM lvi;
363 int iItem;
364
365 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
366
367 iItem = ListView_GetSelectionMark(hwndListView);
368 if (iItem != -1)
369 {
370 memset(&lvi, 0x00, sizeof(lvi));
371 lvi.mask = LVIF_PARAM;
372 lvi.iItem = iItem;
373
374 if (ListView_GetItem(hwndListView, &lvi))
375 {
376 VarData = (PVARIABLE_DATA)lvi.lParam;
377
378 if (DialogBoxParam(hApplet,
379 MAKEINTRESOURCE(IDD_EDIT_VARIABLE),
380 hwndDlg,
381 (DLGPROC)EditVariableDlgProc,
382 (LPARAM)VarData) > 0)
383 {
384 ListView_SetItemText(hwndListView, iItem, 0, VarData->lpName);
385 ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
386 }
387 }
388 }
389 }
390
391
392 VOID
393 OnDeleteVariable(HWND hwndDlg,
394 int iDlgItem)
395 {
396 HWND hwndListView;
397 PVARIABLE_DATA VarData;
398 LV_ITEM lvi;
399 int iItem;
400
401 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
402
403 iItem = ListView_GetSelectionMark(hwndListView);
404 if (iItem != -1)
405 {
406 memset(&lvi, 0x00, sizeof(lvi));
407 lvi.mask = LVIF_PARAM;
408 lvi.iItem = iItem;
409
410 if (ListView_GetItem(hwndListView, &lvi))
411 {
412 VarData = (PVARIABLE_DATA)lvi.lParam;
413 if (VarData != NULL)
414 {
415 if (VarData->lpName != NULL)
416 GlobalFree(VarData->lpName);
417
418 if (VarData->lpRawValue != NULL)
419 GlobalFree(VarData->lpRawValue);
420
421 if (VarData->lpCookedValue != NULL)
422 GlobalFree(VarData->lpCookedValue);
423
424 GlobalFree(VarData);
425 lvi.lParam = 0;
426 }
427 }
428
429 (void)ListView_DeleteItem(hwndListView, iItem);
430 }
431 }
432
433
434 VOID
435 ReleaseListViewItems(HWND hwndDlg,
436 int iDlgItem)
437 {
438 HWND hwndListView;
439 PVARIABLE_DATA VarData;
440 int nItemCount;
441 LV_ITEM lvi;
442 int i;
443
444 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
445
446 memset(&lvi, 0x00, sizeof(lvi));
447
448 nItemCount = ListView_GetItemCount(hwndListView);
449 for (i = 0; i < nItemCount; i++)
450 {
451 lvi.mask = LVIF_PARAM;
452 lvi.iItem = i;
453
454 if (ListView_GetItem(hwndListView, &lvi))
455 {
456 VarData = (PVARIABLE_DATA)lvi.lParam;
457 if (VarData != NULL)
458 {
459 if (VarData->lpName != NULL)
460 GlobalFree(VarData->lpName);
461
462 if (VarData->lpRawValue != NULL)
463 GlobalFree(VarData->lpRawValue);
464
465 if (VarData->lpCookedValue != NULL)
466 GlobalFree(VarData->lpCookedValue);
467
468 GlobalFree(VarData);
469 lvi.lParam = 0;
470 }
471 }
472 }
473 }
474
475
476 VOID
477 SetAllVars(HWND hwndDlg,
478 INT iDlgItem)
479 {
480 HWND hwndListView;
481 PVARIABLE_DATA VarData;
482 LV_ITEM lvi;
483 INT iItem;
484 HKEY hk;
485
486 memset(&lvi, 0x00, sizeof(lvi));
487
488 /* Get the handle to the list box with all system vars in it */
489 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
490 /* first item is 0 */
491 iItem = 0;
492 /* set up struct to retreive item */
493 lvi.mask = LVIF_PARAM;
494 lvi.iItem = iItem;
495
496 /* Open or create the key */
497 if (RegCreateKeyEx((iDlgItem == IDC_SYSTEM_VARIABLE_LIST ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER),
498 (iDlgItem == IDC_SYSTEM_VARIABLE_LIST ? _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment") : _T("Environment")),
499 0,
500 NULL,
501 REG_OPTION_NON_VOLATILE,
502 KEY_WRITE | KEY_READ,
503 NULL,
504 &hk,
505 NULL))
506 {
507 return;
508 }
509
510 /* Loop through all variables */
511 while(ListView_GetItem(hwndListView, &lvi))
512 {
513 /* Get the data in each item */
514 VarData = (PVARIABLE_DATA)lvi.lParam;
515 if (VarData != NULL)
516 {
517 /* Set the new value */
518 if (RegSetValueEx(hk,
519 VarData->lpName,
520 0,
521 VarData->dwType,
522 (LPBYTE)VarData->lpRawValue,
523 (DWORD)(_tcslen(VarData->lpRawValue) + 1) * sizeof(TCHAR)))
524 {
525 RegCloseKey(hk);
526 return;
527 }
528 }
529
530 /* Fill struct for next item */
531 lvi.mask = LVIF_PARAM;
532 lvi.iItem = ++iItem;
533 }
534
535 RegCloseKey(hk);
536 }
537
538
539 /* Environment dialog procedure */
540 INT_PTR CALLBACK
541 EnvironmentDlgProc(HWND hwndDlg,
542 UINT uMsg,
543 WPARAM wParam,
544 LPARAM lParam)
545 {
546 switch (uMsg)
547 {
548 case WM_INITDIALOG:
549 OnInitDialog(hwndDlg);
550 break;
551
552 case WM_COMMAND:
553 switch (LOWORD(wParam))
554 {
555 case IDC_USER_VARIABLE_NEW:
556 OnNewVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
557 return TRUE;
558
559 case IDC_USER_VARIABLE_EDIT:
560 OnEditVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
561 return TRUE;
562
563 case IDC_USER_VARIABLE_DELETE:
564 OnDeleteVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
565 return TRUE;
566
567 case IDC_SYSTEM_VARIABLE_NEW:
568 OnNewVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
569 return TRUE;
570
571 case IDC_SYSTEM_VARIABLE_EDIT:
572 OnEditVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
573 return TRUE;
574
575 case IDC_SYSTEM_VARIABLE_DELETE:
576 OnDeleteVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
577 return TRUE;
578
579 case IDOK:
580 SetAllVars(hwndDlg, IDC_USER_VARIABLE_LIST);
581 SetAllVars(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
582 EndDialog(hwndDlg, 0);
583 return TRUE;
584
585 case IDCANCEL:
586 EndDialog(hwndDlg, 0);
587 return TRUE;
588 }
589 break;
590
591 case WM_DESTROY:
592 ReleaseListViewItems(hwndDlg, IDC_USER_VARIABLE_LIST);
593 ReleaseListViewItems(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
594 break;
595
596 case WM_NOTIFY:
597 {
598 NMHDR *phdr;
599
600 phdr = (NMHDR*)lParam;
601 switch(phdr->code)
602 {
603 case NM_DBLCLK:
604 {
605 if (phdr->idFrom == IDC_USER_VARIABLE_LIST ||
606 phdr->idFrom == IDC_SYSTEM_VARIABLE_LIST)
607 {
608 OnEditVariable(hwndDlg, (INT)phdr->idFrom);
609 return TRUE;
610 }
611 }
612 }
613 }
614 break;
615 }
616
617 return FALSE;
618 }
619
620 /* EOF */