[BRANCHES]
[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 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(lpName);
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(lpExpandData);
231 GlobalFree(lpName);
232 GlobalFree(lpData);
233 RegCloseKey(hKey);
234 return;
235 }
236
237 if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
238 continue;
239
240 VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
241
242 VarData->dwType = dwType;
243
244 VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
245 _tcscpy(VarData->lpName, lpName);
246
247 VarData->lpRawValue = GlobalAlloc(GPTR, (dwDataLength + 1) * sizeof(TCHAR));
248 _tcscpy(VarData->lpRawValue, lpData);
249
250 ExpandEnvironmentStrings(lpData, lpExpandData, 2048);
251
252 VarData->lpCookedValue = GlobalAlloc(GPTR, (_tcslen(lpExpandData) + 1) * sizeof(TCHAR));
253 _tcscpy(VarData->lpCookedValue, lpExpandData);
254
255 memset(&lvi, 0x00, sizeof(lvi));
256 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
257 lvi.lParam = (LPARAM)VarData;
258 lvi.pszText = VarData->lpName;
259 lvi.state = (i == 0) ? LVIS_SELECTED : 0;
260 iItem = ListView_InsertItem(hwndListView, &lvi);
261
262 ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
263 }
264
265 GlobalFree(lpExpandData);
266 GlobalFree(lpName);
267 GlobalFree(lpData);
268 RegCloseKey(hKey);
269 }
270
271
272 static VOID
273 SetListViewColumns(HWND hwndListView)
274 {
275 RECT rect;
276 LV_COLUMN column;
277 TCHAR szStr[32];
278
279 GetClientRect(hwndListView, &rect);
280
281 memset(&column, 0x00, sizeof(column));
282 column.mask=LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
283 column.fmt=LVCFMT_LEFT;
284 column.cx = (INT)((rect.right - rect.left) * 0.32);
285 column.iSubItem = 0;
286 LoadString(hApplet, IDS_VARIABLE, szStr, sizeof(szStr) / sizeof(szStr[0]));
287 column.pszText = szStr;
288 (void)ListView_InsertColumn(hwndListView, 0, &column);
289
290 column.cx = (INT)((rect.right - rect.left) * 0.63);
291 column.iSubItem = 1;
292 LoadString(hApplet, IDS_VALUE, szStr, sizeof(szStr) / sizeof(szStr[0]));
293 column.pszText = szStr;
294 (void)ListView_InsertColumn(hwndListView, 1, &column);
295 }
296
297
298 static VOID
299 OnInitDialog(HWND hwndDlg)
300 {
301 HWND hwndListView;
302
303 /* Set user environment variables */
304 hwndListView = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_LIST);
305
306 (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
307
308 SetListViewColumns(hwndListView);
309
310 GetEnvironmentVariables(hwndListView,
311 HKEY_CURRENT_USER,
312 _T("Environment"));
313
314 (void)ListView_SetColumnWidth(hwndListView, 2, LVSCW_AUTOSIZE_USEHEADER);
315
316 ListView_SetItemState(hwndListView, 0,
317 LVIS_FOCUSED | LVIS_SELECTED,
318 LVIS_FOCUSED | LVIS_SELECTED);
319
320 (void)ListView_Update(hwndListView,0);
321
322 /* Set system environment variables */
323 hwndListView = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
324
325 (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
326
327 SetListViewColumns(hwndListView);
328
329 GetEnvironmentVariables(hwndListView,
330 HKEY_LOCAL_MACHINE,
331 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"));
332
333 (void)ListView_SetColumnWidth(hwndListView, 2, LVSCW_AUTOSIZE_USEHEADER);
334
335 ListView_SetItemState(hwndListView, 0,
336 LVIS_FOCUSED | LVIS_SELECTED,
337 LVIS_FOCUSED | LVIS_SELECTED);
338
339 (void)ListView_Update(hwndListView, 0);
340 }
341
342
343 static VOID
344 OnNewVariable(HWND hwndDlg,
345 INT iDlgItem)
346 {
347 HWND hwndListView;
348 PVARIABLE_DATA VarData;
349 LV_ITEM lvi;
350 INT iItem;
351
352 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
353
354 VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
355
356 if (!DialogBoxParam(hApplet,
357 MAKEINTRESOURCE(IDD_EDIT_VARIABLE),
358 hwndDlg,
359 (DLGPROC)EditVariableDlgProc,
360 (LPARAM)VarData) > 0)
361 {
362 if (VarData->lpName != NULL)
363 GlobalFree(VarData->lpName);
364
365 if (VarData->lpRawValue != NULL)
366 GlobalFree(VarData->lpRawValue);
367
368 if (VarData->lpCookedValue != NULL)
369 GlobalFree(VarData->lpCookedValue);
370
371 GlobalFree(VarData);
372 }
373 else
374 {
375 if (VarData->lpName != NULL && (VarData->lpCookedValue || VarData->lpRawValue))
376 {
377 memset(&lvi, 0x00, sizeof(lvi));
378 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
379 lvi.lParam = (LPARAM)VarData;
380 lvi.pszText = VarData->lpName;
381 lvi.state = 0;
382 iItem = ListView_InsertItem(hwndListView, &lvi);
383
384 ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
385 }
386 }
387 }
388
389
390 static VOID
391 OnEditVariable(HWND hwndDlg,
392 INT iDlgItem)
393 {
394 HWND hwndListView;
395 PVARIABLE_DATA VarData;
396 LV_ITEM lvi;
397 INT iItem;
398
399 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
400
401 iItem = GetSelectedListViewItem(hwndListView);
402 if (iItem != -1)
403 {
404 memset(&lvi, 0x00, sizeof(lvi));
405 lvi.mask = LVIF_PARAM;
406 lvi.iItem = iItem;
407
408 if (ListView_GetItem(hwndListView, &lvi))
409 {
410 VarData = (PVARIABLE_DATA)lvi.lParam;
411
412 if (DialogBoxParam(hApplet,
413 MAKEINTRESOURCE(IDD_EDIT_VARIABLE),
414 hwndDlg,
415 (DLGPROC)EditVariableDlgProc,
416 (LPARAM)VarData) > 0)
417 {
418 ListView_SetItemText(hwndListView, iItem, 0, VarData->lpName);
419 ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
420 }
421 }
422 }
423 }
424
425
426 static VOID
427 OnDeleteVariable(HWND hwndDlg,
428 INT iDlgItem)
429 {
430 HWND hwndListView;
431 PVARIABLE_DATA VarData;
432 LV_ITEM lvi;
433 INT iItem;
434
435 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
436
437 iItem = GetSelectedListViewItem(hwndListView);
438 if (iItem != -1)
439 {
440 memset(&lvi, 0x00, sizeof(lvi));
441 lvi.mask = LVIF_PARAM;
442 lvi.iItem = iItem;
443
444 if (ListView_GetItem(hwndListView, &lvi))
445 {
446 VarData = (PVARIABLE_DATA)lvi.lParam;
447 if (VarData != NULL)
448 {
449 if (VarData->lpName != NULL)
450 GlobalFree(VarData->lpName);
451
452 if (VarData->lpRawValue != NULL)
453 GlobalFree(VarData->lpRawValue);
454
455 if (VarData->lpCookedValue != NULL)
456 GlobalFree(VarData->lpCookedValue);
457
458 GlobalFree(VarData);
459 lvi.lParam = 0;
460 }
461 }
462
463 (void)ListView_DeleteItem(hwndListView, iItem);
464
465 /* Select the previous item */
466 if (iItem > 0)
467 iItem--;
468
469 ListView_SetItemState(hwndListView, iItem,
470 LVIS_FOCUSED | LVIS_SELECTED,
471 LVIS_FOCUSED | LVIS_SELECTED);
472 }
473 }
474
475
476 static VOID
477 ReleaseListViewItems(HWND hwndDlg,
478 INT iDlgItem)
479 {
480 HWND hwndListView;
481 PVARIABLE_DATA VarData;
482 LV_ITEM lvi;
483 INT nItemCount;
484 INT i;
485
486 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
487
488 memset(&lvi, 0x00, sizeof(lvi));
489
490 nItemCount = ListView_GetItemCount(hwndListView);
491 for (i = 0; i < nItemCount; i++)
492 {
493 lvi.mask = LVIF_PARAM;
494 lvi.iItem = i;
495
496 if (ListView_GetItem(hwndListView, &lvi))
497 {
498 VarData = (PVARIABLE_DATA)lvi.lParam;
499 if (VarData != NULL)
500 {
501 if (VarData->lpName != NULL)
502 GlobalFree(VarData->lpName);
503
504 if (VarData->lpRawValue != NULL)
505 GlobalFree(VarData->lpRawValue);
506
507 if (VarData->lpCookedValue != NULL)
508 GlobalFree(VarData->lpCookedValue);
509
510 GlobalFree(VarData);
511 lvi.lParam = 0;
512 }
513 }
514 }
515 }
516
517
518 static VOID
519 SetAllVars(HWND hwndDlg,
520 INT iDlgItem)
521 {
522 HWND hwndListView;
523 PVARIABLE_DATA VarData;
524 LV_ITEM lvi;
525 INT iItem;
526 HKEY hKey;
527 DWORD dwValueCount;
528 DWORD dwMaxValueNameLength;
529 LPTSTR *aValueArray;
530 DWORD dwNameLength;
531 DWORD i;
532 TCHAR szBuffer[256];
533 LPTSTR lpBuffer;
534
535 memset(&lvi, 0x00, sizeof(lvi));
536
537 /* Get the handle to the list box with all system vars in it */
538 hwndListView = GetDlgItem(hwndDlg, iDlgItem);
539 /* First item is 0 */
540 iItem = 0;
541 /* Set up struct to retreive item */
542 lvi.mask = LVIF_PARAM;
543 lvi.iItem = iItem;
544
545 /* Open or create the key */
546 if (RegCreateKeyEx((iDlgItem == IDC_SYSTEM_VARIABLE_LIST ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER),
547 (iDlgItem == IDC_SYSTEM_VARIABLE_LIST ? _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment") : _T("Environment")),
548 0,
549 NULL,
550 REG_OPTION_NON_VOLATILE,
551 KEY_WRITE | KEY_READ,
552 NULL,
553 &hKey,
554 NULL))
555 {
556 return;
557 }
558
559 /* Get the number of values and the maximum value name length */
560 if (RegQueryInfoKey(hKey,
561 NULL,
562 NULL,
563 NULL,
564 NULL,
565 NULL,
566 NULL,
567 &dwValueCount,
568 &dwMaxValueNameLength,
569 NULL,
570 NULL,
571 NULL))
572 {
573 RegCloseKey(hKey);
574 return;
575 }
576
577 if (dwValueCount > 0)
578 {
579 /* Allocate the value array */
580 aValueArray = GlobalAlloc(GPTR, dwValueCount * sizeof(LPTSTR));
581 if (aValueArray != NULL)
582 {
583 /* Get all value names */
584 for (i = 0; i < dwValueCount; i++)
585 {
586 dwNameLength = 256;
587 if (!RegEnumValue(hKey,
588 i,
589 szBuffer,
590 &dwNameLength,
591 NULL,
592 NULL,
593 NULL,
594 NULL))
595 {
596 /* Allocate a value name buffer, fill it and attach it to the array */
597 lpBuffer = (LPTSTR)GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
598 if (lpBuffer != NULL)
599 {
600 _tcscpy(lpBuffer, szBuffer);
601 aValueArray[i] = lpBuffer;
602 }
603 }
604 }
605
606 /* Delete all values */
607 for (i = 0; i < dwValueCount; i++)
608 {
609 if (aValueArray[i] != NULL)
610 {
611 /* Delete the value */
612 RegDeleteValue(hKey,
613 aValueArray[i]);
614
615 /* Free the value name */
616 GlobalFree(aValueArray[i]);
617 }
618 }
619
620 /* Free the value array */
621 GlobalFree(aValueArray);
622 }
623 }
624
625 /* Loop through all variables */
626 while (ListView_GetItem(hwndListView, &lvi))
627 {
628 /* Get the data in each item */
629 VarData = (PVARIABLE_DATA)lvi.lParam;
630 if (VarData != NULL)
631 {
632 /* Set the new value */
633 if (RegSetValueEx(hKey,
634 VarData->lpName,
635 0,
636 VarData->dwType,
637 (LPBYTE)VarData->lpRawValue,
638 (DWORD)(_tcslen(VarData->lpRawValue) + 1) * sizeof(TCHAR)))
639 {
640 RegCloseKey(hKey);
641 return;
642 }
643 }
644
645 /* Fill struct for next item */
646 lvi.mask = LVIF_PARAM;
647 lvi.iItem = ++iItem;
648 }
649
650 RegCloseKey(hKey);
651 }
652
653
654 static BOOL
655 OnNotify(HWND hwndDlg, NMHDR *phdr)
656 {
657 switch(phdr->code)
658 {
659 case NM_DBLCLK:
660 if (phdr->idFrom == IDC_USER_VARIABLE_LIST ||
661 phdr->idFrom == IDC_SYSTEM_VARIABLE_LIST)
662 {
663 OnEditVariable(hwndDlg, (INT)phdr->idFrom);
664 return TRUE;
665 }
666 break;
667
668 case LVN_KEYDOWN:
669 if (((LPNMLVKEYDOWN)phdr)->wVKey == VK_DELETE &&
670 (phdr->idFrom == IDC_USER_VARIABLE_LIST ||
671 phdr->idFrom == IDC_SYSTEM_VARIABLE_LIST))
672 {
673 OnDeleteVariable(hwndDlg, (INT)phdr->idFrom);
674 return TRUE;
675 }
676 break;
677 }
678
679 return FALSE;
680 }
681
682
683 /* Environment dialog procedure */
684 INT_PTR CALLBACK
685 EnvironmentDlgProc(HWND hwndDlg,
686 UINT uMsg,
687 WPARAM wParam,
688 LPARAM lParam)
689 {
690 switch (uMsg)
691 {
692 case WM_INITDIALOG:
693 OnInitDialog(hwndDlg);
694 break;
695
696 case WM_COMMAND:
697 switch (LOWORD(wParam))
698 {
699 case IDC_USER_VARIABLE_NEW:
700 OnNewVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
701 return TRUE;
702
703 case IDC_USER_VARIABLE_EDIT:
704 OnEditVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
705 return TRUE;
706
707 case IDC_USER_VARIABLE_DELETE:
708 OnDeleteVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
709 return TRUE;
710
711 case IDC_SYSTEM_VARIABLE_NEW:
712 OnNewVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
713 return TRUE;
714
715 case IDC_SYSTEM_VARIABLE_EDIT:
716 OnEditVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
717 return TRUE;
718
719 case IDC_SYSTEM_VARIABLE_DELETE:
720 OnDeleteVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
721 return TRUE;
722
723 case IDOK:
724 SetAllVars(hwndDlg, IDC_USER_VARIABLE_LIST);
725 SetAllVars(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
726 SendMessage(HWND_BROADCAST, WM_WININICHANGE,
727 0, (LPARAM)_T("Environment"));
728 EndDialog(hwndDlg, 0);
729 return TRUE;
730
731 case IDCANCEL:
732 EndDialog(hwndDlg, 0);
733 return TRUE;
734 }
735 break;
736
737 case WM_DESTROY:
738 ReleaseListViewItems(hwndDlg, IDC_USER_VARIABLE_LIST);
739 ReleaseListViewItems(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
740 break;
741
742 case WM_NOTIFY:
743 return OnNotify(hwndDlg, (NMHDR*)lParam);
744 }
745
746 return FALSE;
747 }
748
749 /* EOF */