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