migrate substitution keywords to SVN
[reactos.git] / reactos / lib / cpl / sysdm / environment.c
1 /*
2 * ReactOS
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS System Control Panel
22 * FILE: lib/cpl/sysdm/environment.c
23 * PURPOSE: Environment variable settings
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <stdlib.h>
30 #include <tchar.h>
31
32 #include "resource.h"
33 #include "sysdm.h"
34
35
36 typedef struct _VARIABLE_DATA
37 {
38 LPTSTR lpName;
39 LPTSTR lpRawValue;
40 LPTSTR lpCookedValue;
41 } VARIABLE_DATA, *PVARIABLE_DATA;
42
43
44
45 INT_PTR CALLBACK
46 EditVariableDlgProc(HWND hwndDlg,
47 UINT uMsg,
48 WPARAM wParam,
49 LPARAM lParam)
50 {
51 PVARIABLE_DATA VarData;
52 DWORD dwNameLength;
53 DWORD dwValueLength;
54
55 VarData = (PVARIABLE_DATA)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
56
57 switch (uMsg)
58 {
59 case WM_INITDIALOG:
60 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)lParam);
61 VarData = (PVARIABLE_DATA)lParam;
62
63 if (VarData->lpName != NULL)
64 {
65 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_SETTEXT, 0, (LPARAM)VarData->lpName);
66 }
67
68 if (VarData->lpRawValue != NULL)
69 {
70 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_SETTEXT, 0, (LPARAM)VarData->lpRawValue);
71 }
72 break;
73
74 case WM_COMMAND:
75 switch (LOWORD(wParam))
76 {
77 case IDOK:
78 dwNameLength = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_GETTEXTLENGTH, 0, 0);
79 dwValueLength = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_GETTEXTLENGTH, 0, 0);
80 if (dwNameLength != 0 && dwValueLength != 0)
81 {
82 if (VarData->lpName == NULL)
83 {
84 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
85 }
86 else if (_tcslen(VarData->lpName) < dwNameLength)
87 {
88 GlobalFree(VarData->lpName);
89 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
90 }
91 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_GETTEXT, dwNameLength + 1, (LPARAM)VarData->lpName);
92
93 if (VarData->lpRawValue == NULL)
94 {
95 VarData->lpRawValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
96 }
97 else if (_tcslen(VarData->lpRawValue) < dwValueLength)
98 {
99 GlobalFree(VarData->lpRawValue);
100 VarData->lpRawValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
101 }
102 SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_GETTEXT, dwValueLength + 1, (LPARAM)VarData->lpRawValue);
103
104 if (_tcschr(VarData->lpRawValue, _T('%')))
105 {
106 if (VarData->lpCookedValue == NULL)
107 {
108 VarData->lpCookedValue = GlobalAlloc(GPTR, 2 * MAX_PATH * sizeof(TCHAR));
109 }
110
111 ExpandEnvironmentStrings(VarData->lpRawValue,
112 VarData->lpCookedValue,
113 2 * MAX_PATH);
114 }
115 else if (VarData->lpCookedValue)
116 {
117 GlobalFree(VarData->lpCookedValue);
118 }
119 }
120 EndDialog(hwndDlg, 1);
121 return TRUE;
122
123 case IDCANCEL:
124 EndDialog(hwndDlg, 0);
125 return TRUE;
126 }
127 break;
128 }
129
130 return FALSE;
131 }
132
133
134 static VOID
135 SetEnvironmentVariables(HWND hwndListView,
136 HKEY hRootKey,
137 LPTSTR lpSubKeyName)
138 {
139 HKEY hKey;
140 DWORD dwValues;
141 DWORD dwMaxValueNameLength;
142 DWORD dwMaxValueDataLength;
143 DWORD i;
144 LPTSTR lpName;
145 LPTSTR lpData;
146 LPTSTR lpExpandData = NULL;
147 DWORD dwNameLength;
148 DWORD dwDataLength;
149 DWORD dwType;
150 PVARIABLE_DATA VarData;
151
152 LV_ITEM lvi;
153 int iItem;
154
155 if (RegOpenKeyEx(hRootKey,
156 lpSubKeyName,
157 0,
158 KEY_READ,
159 &hKey))
160 return;
161
162 if (RegQueryInfoKey(hKey,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 &dwValues,
170 &dwMaxValueNameLength,
171 &dwMaxValueDataLength,
172 NULL,
173 NULL))
174 {
175 RegCloseKey(hKey);
176 return;
177 }
178
179 lpName = GlobalAlloc(GPTR, (dwMaxValueNameLength + 1) * sizeof(TCHAR));
180 if (lpName == NULL)
181 {
182 RegCloseKey(hKey);
183 return;
184 }
185
186 lpData = GlobalAlloc(GPTR, (dwMaxValueDataLength + 1) * sizeof(TCHAR));
187 if (lpData == NULL)
188 {
189 GlobalFree(lpData);
190 RegCloseKey(hKey);
191 return;
192 }
193
194 for (i = 0; i < dwValues; i++)
195 {
196 dwNameLength = dwMaxValueNameLength + 1;
197 dwDataLength = dwMaxValueDataLength + 1;
198 if (RegEnumValue(hKey,
199 i,
200 lpName,
201 &dwNameLength,
202 NULL,
203 &dwType,
204 (LPBYTE)lpData,
205 &dwDataLength))
206 {
207 GlobalFree(lpName);
208 GlobalFree(lpData);
209 RegCloseKey(hKey);
210 return;
211 }
212
213 VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
214
215 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
216 _tcscpy(VarData->lpName, lpName);
217
218 VarData->lpRawValue = GlobalAlloc(GPTR, (dwDataLength + 1) * sizeof(TCHAR));
219 _tcscpy(VarData->lpRawValue, lpData);
220
221 if (dwType == REG_EXPAND_SZ)
222 {
223 lpExpandData = GlobalAlloc(GPTR, MAX_PATH * 2* sizeof(TCHAR));
224 if (lpExpandData == NULL)
225 {
226 GlobalFree(lpName);
227 GlobalFree(lpData);
228 RegCloseKey(hKey);
229 return;
230 }
231
232 ExpandEnvironmentStrings(lpData,
233 lpExpandData,
234 2 * MAX_PATH);
235
236 VarData->lpCookedValue = GlobalAlloc(GPTR, (_tcslen(lpExpandData) + 1) * sizeof(TCHAR));
237 _tcscpy(VarData->lpCookedValue, lpExpandData);
238 GlobalFree(lpExpandData);
239 }
240
241 memset(&lvi, 0x00, sizeof(lvi));
242 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
243 lvi.lParam = (LPARAM)VarData;
244 lvi.pszText = VarData->lpName;
245 lvi.state = (i == 0) ? LVIS_SELECTED : 0;
246 iItem = ListView_InsertItem(hwndListView, &lvi);
247
248 ListView_SetItemText(hwndListView, iItem, 1,
249 (VarData->lpCookedValue) ? VarData->lpCookedValue : VarData->lpRawValue);
250 }
251
252 GlobalFree(lpName);
253 GlobalFree(lpData);
254 RegCloseKey(hKey);
255 }
256
257
258 static VOID
259 SetListViewColumns(HWND hwndListView)
260 {
261 RECT rect;
262 LV_COLUMN column;
263
264 GetClientRect(hwndListView, &rect);
265
266 memset(&column, 0x00, sizeof(column));
267 column.mask=LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
268 column.fmt=LVCFMT_LEFT;
269 column.cx = (rect.right - rect.left) / 3;
270 column.iSubItem = 0;
271 column.pszText = _T("Variable");
272 ListView_InsertColumn(hwndListView, 0, &column);
273
274 column.cx = (rect.right - rect.left) - ((rect.right - rect.left) / 3) - 1;
275 column.iSubItem = 1;
276 column.pszText = _T("Value");
277 ListView_InsertColumn(hwndListView, 1, &column);
278 }
279
280
281 static VOID
282 OnInitDialog(HWND hwndDlg)
283 {
284 HWND hwndListView;
285
286 /* Set user environment variables */
287 hwndListView = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_LIST);
288
289 SetListViewColumns(hwndListView);
290
291 SetEnvironmentVariables(hwndListView,
292 HKEY_CURRENT_USER,
293 _T("Environment"));
294
295 ListView_SetColumnWidth(hwndListView,2,LVSCW_AUTOSIZE_USEHEADER);
296 ListView_Update(hwndListView,0);
297
298
299 /* Set system environment variables */
300 hwndListView = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
301
302 SetListViewColumns(hwndListView);
303
304 SetEnvironmentVariables(hwndListView,
305 HKEY_LOCAL_MACHINE,
306 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"));
307
308 ListView_SetColumnWidth(hwndListView,2,LVSCW_AUTOSIZE_USEHEADER);
309 ListView_Update(hwndListView,0);
310 }
311
312
313 VOID
314 OnNewVariable(HWND hwndDlg,
315 int iDlgItem)
316 {
317 HWND hwndListView;
318 PVARIABLE_DATA VarData;
319 LV_ITEM lvi;
320 int iItem;
321
322 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
323
324 VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
325
326 if (!DialogBoxParam(hApplet,
327 MAKEINTRESOURCE(IDD_EDIT_VARIABLE),
328 hwndDlg,
329 EditVariableDlgProc,
330 (LPARAM)VarData) > 0)
331 {
332 if (VarData->lpName != NULL)
333 GlobalFree(VarData->lpName);
334
335 if (VarData->lpRawValue != NULL)
336 GlobalFree(VarData->lpRawValue);
337
338 if (VarData->lpCookedValue != NULL)
339 GlobalFree(VarData->lpCookedValue);
340
341 GlobalFree(VarData);
342 }
343
344 memset(&lvi, 0x00, sizeof(lvi));
345 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
346 lvi.lParam = (LPARAM)VarData;
347 lvi.pszText = VarData->lpName;
348 lvi.state = 0;
349 iItem = ListView_InsertItem(hwndListView, &lvi);
350
351 ListView_SetItemText(hwndListView, iItem, 1,
352 (VarData->lpCookedValue) ? VarData->lpCookedValue : VarData->lpRawValue);
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 EditVariableDlgProc,
382 (LPARAM)VarData) > 0)
383 {
384 ListView_SetItemText(hwndListView, iItem, 0, VarData->lpName);
385 ListView_SetItemText(hwndListView, iItem, 1,
386 (VarData->lpCookedValue) ? VarData->lpCookedValue : VarData->lpRawValue);
387 }
388 }
389 }
390 }
391
392
393 VOID
394 OnDeleteVariable(HWND hwndDlg,
395 int iDlgItem)
396 {
397 HWND hwndListView;
398 PVARIABLE_DATA VarData;
399 LV_ITEM lvi;
400 int iItem;
401
402 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
403
404 iItem = ListView_GetSelectionMark(hwndListView);
405 if (iItem != -1)
406 {
407 memset(&lvi, 0x00, sizeof(lvi));
408 lvi.mask = LVIF_PARAM;
409 lvi.iItem = iItem;
410
411 if (ListView_GetItem(hwndListView, &lvi))
412 {
413 VarData = (PVARIABLE_DATA)lvi.lParam;
414 if (VarData != NULL)
415 {
416 if (VarData->lpName != NULL)
417 GlobalFree(VarData->lpName);
418
419 if (VarData->lpRawValue != NULL)
420 GlobalFree(VarData->lpRawValue);
421
422 if (VarData->lpCookedValue != NULL)
423 GlobalFree(VarData->lpCookedValue);
424
425 GlobalFree(VarData);
426 lvi.lParam = 0;
427 }
428 }
429
430 ListView_DeleteItem(hwndListView, iItem);
431 }
432 }
433
434
435 VOID
436 ReleaseListViewItems(HWND hwndDlg,
437 int iDlgItem)
438 {
439 HWND hwndListView;
440 PVARIABLE_DATA VarData;
441 int nItemCount;
442 LV_ITEM lvi;
443 int i;
444
445 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
446
447 memset(&lvi, 0x00, sizeof(lvi));
448
449 nItemCount = ListView_GetItemCount(hwndListView);
450 for (i = 0; i < nItemCount; i++)
451 {
452 lvi.mask = LVIF_PARAM;
453 lvi.iItem = i;
454
455 if (ListView_GetItem(hwndListView, &lvi))
456 {
457 VarData = (PVARIABLE_DATA)lvi.lParam;
458 if (VarData != NULL)
459 {
460 if (VarData->lpName != NULL)
461 GlobalFree(VarData->lpName);
462
463 if (VarData->lpRawValue != NULL)
464 GlobalFree(VarData->lpRawValue);
465
466 if (VarData->lpCookedValue != NULL)
467 GlobalFree(VarData->lpCookedValue);
468
469 GlobalFree(VarData);
470 lvi.lParam = 0;
471 }
472 }
473 }
474 }
475
476
477 /* Environment dialog procedure */
478 INT_PTR CALLBACK
479 EnvironmentDlgProc(HWND hwndDlg,
480 UINT uMsg,
481 WPARAM wParam,
482 LPARAM lParam)
483 {
484 switch (uMsg)
485 {
486 case WM_INITDIALOG:
487 OnInitDialog(hwndDlg);
488 break;
489
490 case WM_COMMAND:
491 switch (LOWORD(wParam))
492 {
493 case IDC_USER_VARIABLE_NEW:
494 OnNewVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
495 return TRUE;
496
497 case IDC_USER_VARIABLE_EDIT:
498 OnEditVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
499 return TRUE;
500
501 case IDC_USER_VARIABLE_DELETE:
502 OnDeleteVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
503 return TRUE;
504
505 case IDC_SYSTEM_VARIABLE_NEW:
506 OnNewVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
507 return TRUE;
508
509 case IDC_SYSTEM_VARIABLE_EDIT:
510 OnEditVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
511 return TRUE;
512
513 case IDC_SYSTEM_VARIABLE_DELETE:
514 OnDeleteVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
515 return TRUE;
516
517 case IDOK:
518 /* FIXME: Set environment variables in the registry */
519
520 case IDCANCEL:
521 ReleaseListViewItems(hwndDlg, IDC_USER_VARIABLE_LIST);
522 ReleaseListViewItems(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
523 EndDialog(hwndDlg, 0);
524 return TRUE;
525 }
526 break;
527
528 case WM_NOTIFY:
529 {
530 NMHDR *phdr;
531
532 phdr = (NMHDR*)lParam;
533 switch(phdr->code)
534 {
535 case NM_DBLCLK:
536 {
537 if (phdr->idFrom == IDC_USER_VARIABLE_LIST ||
538 phdr->idFrom == IDC_SYSTEM_VARIABLE_LIST)
539 {
540 OnEditVariable(hwndDlg, phdr->idFrom);
541 return TRUE;
542 }
543 }
544 }
545 }
546 break;
547 }
548
549 return FALSE;
550 }
551
552 /* EOF */