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