xref: /reactos/dll/cpl/sysdm/environment.c (revision 7e22dc05)
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  *              Copyright 2021 Arnav Bhatt <arnavbhatt288@gmail.com>
8  */
9 
10 #include "precomp.h"
11 #include <commctrl.h>
12 #include <commdlg.h>
13 #include <string.h>
14 #include <strsafe.h>
15 
16 #define MAX_STR_LENGTH  128
17 
18 typedef struct _VARIABLE_DATA
19 {
20     DWORD dwType;
21     LPTSTR lpName;
22     LPTSTR lpRawValue;
23     LPTSTR lpCookedValue;
24 } VARIABLE_DATA, *PVARIABLE_DATA;
25 
26 typedef struct _ENVIRONMENT_DIALOG_DATA
27 {
28     DWORD cxMin;
29     DWORD cyMin;
30     DWORD cxOld;
31     DWORD cyOld;
32 } ENVIRONMENT_DIALOG_DATA, *PENVIRONMENT_DIALOG_DATA;
33 
34 typedef struct _ENVIRONMENT_EDIT_DIALOG_DATA
35 {
36     BOOL bIsItemSelected;
37     DWORD dwSelectedValueIndex;
38     DWORD cxMin;
39     DWORD cyMin;
40     DWORD cxOld;
41     DWORD cyOld;
42     DWORD dwDlgID;
43     HWND hEditBox;
44     PVARIABLE_DATA VarData;
45 } EDIT_DIALOG_DATA, *PEDIT_DIALOG_DATA;
46 
47 static BOOL
48 DetermineDialogBoxType(LPTSTR lpRawValue)
49 {
50     DWORD dwValueLength;
51     LPTSTR lpTemp;
52     LPTSTR lpToken;
53 
54     dwValueLength = _tcslen(lpRawValue) + 1;
55     lpTemp = GlobalAlloc(GPTR, dwValueLength * sizeof(TCHAR));
56     if (!lpTemp)
57         return FALSE;
58 
59     StringCchCopy(lpTemp, dwValueLength, lpRawValue);
60 
61     for (lpToken = _tcstok(lpTemp, _T(";"));
62          lpToken != NULL;
63          lpToken = _tcstok(NULL, _T(";")))
64     {
65         /* If the string has environment variable then expand it */
66         ExpandEnvironmentStrings(lpToken, lpToken, dwValueLength);
67 
68         if (!PathIsDirectoryW(lpToken))
69             return FALSE;
70     }
71     GlobalFree(lpTemp);
72 
73     return TRUE;
74 }
75 
76 static DWORD
77 GatherDataFromEditBox(HWND hwndDlg,
78                       PVARIABLE_DATA VarData)
79 {
80     DWORD dwNameLength;
81     DWORD dwValueLength;
82 
83     dwNameLength = SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_GETTEXTLENGTH, 0, 0);
84     dwValueLength = SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_GETTEXTLENGTH, 0, 0);
85 
86     if (dwNameLength == 0 || dwValueLength == 0)
87     {
88         return 0;
89     }
90 
91     /* Reallocate the name buffer, regrowing it if necessary */
92     if (!VarData->lpName || (_tcslen(VarData->lpName) < dwNameLength))
93     {
94         if (VarData->lpName)
95             GlobalFree(VarData->lpName);
96 
97         VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
98         if (!VarData->lpName)
99             return 0;
100     }
101     SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_GETTEXT, dwNameLength + 1, (LPARAM)VarData->lpName);
102 
103     /* Reallocate the value buffer, regrowing it if necessary */
104     if (!VarData->lpRawValue || (_tcslen(VarData->lpRawValue) < dwValueLength))
105     {
106         if (VarData->lpRawValue)
107             GlobalFree(VarData->lpRawValue);
108 
109         VarData->lpRawValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
110         if (!VarData->lpRawValue)
111             return 0;
112     }
113     SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_GETTEXT, dwValueLength + 1, (LPARAM)VarData->lpRawValue);
114 
115     return dwValueLength;
116 }
117 
118 static DWORD
119 GatherDataFromListView(HWND hwndListView,
120                        PVARIABLE_DATA VarData)
121 {
122     DWORD dwValueLength;
123     DWORD NumberOfItems;
124     DWORD i;
125     TCHAR szData[MAX_PATH];
126 
127     /* Gather the number of items for the semi-colon */
128     NumberOfItems = ListView_GetItemCount(hwndListView);
129     if (NumberOfItems == 0)
130     {
131         return 0;
132     }
133 
134     /* Since the last item doesn't need the semi-colon subtract 1 */
135     dwValueLength = NumberOfItems - 1;
136 
137     for (i = 0; i < NumberOfItems; i++)
138     {
139         ListView_GetItemText(hwndListView,
140                              i,
141                              0,
142                              szData,
143                              _countof(szData));
144         dwValueLength += _tcslen(szData);
145     }
146 
147     /* Reallocate the value buffer, regrowing it if necessary */
148     if (!VarData->lpRawValue || (_tcslen(VarData->lpRawValue) < dwValueLength))
149     {
150         if (VarData->lpRawValue)
151             GlobalFree(VarData->lpRawValue);
152 
153         VarData->lpRawValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
154         if (!VarData->lpRawValue)
155             return 0;
156     }
157 
158     /* First reinitialize the value buffer, then copy the variable values while
159      * separating them with a semi-colon, except for the last value. */
160     VarData->lpRawValue[0] = _T('\0');
161     for (i = 0; i < NumberOfItems; i++)
162     {
163         if (i > 0)
164         {
165             StringCchCat(VarData->lpRawValue, dwValueLength + 1, _T(";"));
166         }
167         ListView_GetItemText(hwndListView,
168                              i,
169                              0,
170                              szData,
171                              _countof(szData));
172         StringCchCat(VarData->lpRawValue, dwValueLength + 1, szData);
173     }
174     return dwValueLength;
175 }
176 
177 static INT
178 GetSelectedListViewItem(HWND hwndListView)
179 {
180     INT iCount;
181     INT iItem;
182 
183     iCount = SendMessage(hwndListView,
184                          LVM_GETITEMCOUNT,
185                          0,
186                          0);
187     if (iCount != LB_ERR)
188     {
189         for (iItem = 0; iItem < iCount; iItem++)
190         {
191             if (SendMessage(hwndListView,
192                             LVM_GETITEMSTATE,
193                             iItem,
194                             (LPARAM) LVIS_SELECTED) == LVIS_SELECTED)
195             {
196                 return iItem;
197             }
198         }
199     }
200 
201     return -1;
202 }
203 
204 static LRESULT CALLBACK
205 ListViewSubclassProc(HWND hListBox,
206                     UINT uMsg,
207                     WPARAM wParam,
208                     LPARAM lParam,
209                     UINT_PTR uIdSubclass,
210                     DWORD_PTR dwRefData)
211 {
212     switch (uMsg)
213     {
214         case WM_DESTROY:
215         {
216             RemoveWindowSubclass(hListBox, ListViewSubclassProc, uIdSubclass);
217             break;
218         }
219 
220         /* Whenever the control is resized make sure it doesn't spawn the horizontal scrollbar */
221         case WM_SIZE:
222         {
223             ShowScrollBar(hListBox, SB_HORZ, FALSE);
224             break;
225         }
226     }
227 
228     return DefSubclassProc(hListBox, uMsg, wParam, lParam);
229 }
230 
231 static VOID
232 AddEmptyItem(HWND hwndListView,
233              DWORD dwSelectedValueIndex)
234 {
235     LV_ITEM lvi;
236 
237     ZeroMemory(&lvi, sizeof(lvi));
238     lvi.mask = LVIF_TEXT | LVIF_STATE;
239     lvi.cchTextMax = MAX_PATH;
240     lvi.pszText = _T("");
241     lvi.iItem = dwSelectedValueIndex;
242     lvi.iSubItem = 0;
243     ListView_InsertItem(hwndListView, &lvi);
244 }
245 
246 static VOID
247 AddValuesToList(HWND hwndDlg,
248                 PEDIT_DIALOG_DATA DlgData)
249 {
250     LV_COLUMN column;
251     LV_ITEM lvi;
252     RECT rItem;
253 
254     DWORD dwValueLength;
255     DWORD i;
256     HWND hwndListView;
257     LPTSTR lpTemp;
258     LPTSTR lpToken;
259 
260     ZeroMemory(&column, sizeof(column));
261     ZeroMemory(&lvi, sizeof(lvi));
262 
263     hwndListView = GetDlgItem(hwndDlg, IDC_LIST_VARIABLE_VALUE);
264 
265     GetClientRect(hwndListView, &rItem);
266 
267     column.mask = LVCF_WIDTH;
268     column.cx = rItem.right;
269     ListView_InsertColumn(hwndListView, 0, &column);
270     ShowScrollBar(hwndListView, SB_HORZ, FALSE);
271 
272     lvi.mask = LVIF_TEXT | LVIF_STATE;
273     lvi.cchTextMax = MAX_PATH;
274     lvi.iSubItem = 0;
275 
276     dwValueLength = _tcslen(DlgData->VarData->lpRawValue) + 1;
277     lpTemp = GlobalAlloc(GPTR, dwValueLength * sizeof(TCHAR));
278     if (!lpTemp)
279         return;
280 
281     StringCchCopy(lpTemp, dwValueLength, DlgData->VarData->lpRawValue);
282 
283     for (lpToken = _tcstok(lpTemp, _T(";")), i = 0;
284          lpToken != NULL;
285          lpToken = _tcstok(NULL, _T(";")), i++)
286     {
287         lvi.iItem = i;
288         lvi.pszText = lpToken;
289         lvi.state = (i == 0) ? LVIS_SELECTED : 0;
290         ListView_InsertItem(hwndListView, &lvi);
291     }
292 
293     DlgData->dwSelectedValueIndex = 0;
294     ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
295     ListView_SetItemState(hwndListView, DlgData->dwSelectedValueIndex,
296                           LVIS_FOCUSED | LVIS_SELECTED,
297                           LVIS_FOCUSED | LVIS_SELECTED);
298 
299     ListView_Update(hwndListView, DlgData->dwSelectedValueIndex);
300     GlobalFree(lpTemp);
301 }
302 
303 static VOID
304 BrowseRequiredFile(HWND hwndDlg)
305 {
306     OPENFILENAME ofn;
307     TCHAR szFilter[MAX_STR_LENGTH] = _T("");
308     TCHAR szFile[MAX_PATH] = _T("");
309 
310     LoadString(hApplet, IDS_FILE_BROWSE_FILTER, szFilter, _countof(szFilter));
311 
312     ZeroMemory(&ofn, sizeof(ofn));
313 
314     ofn.lStructSize = sizeof(ofn);
315     ofn.hwndOwner = hwndDlg;
316     ofn.lpstrFilter = szFilter;
317     ofn.lpstrFile = szFile;
318     ofn.nMaxFile = _countof(szFile);
319     ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
320 
321     if (GetOpenFileName(&ofn))
322     {
323         SetDlgItemText(hwndDlg, IDC_VARIABLE_VALUE, szFile);
324     }
325 }
326 
327 static VOID
328 BrowseRequiredFolder(HWND hwndDlg,
329                      PEDIT_DIALOG_DATA DlgData)
330 {
331     HWND hwndListView;
332     TCHAR szDir[MAX_PATH];
333 
334     BROWSEINFO bi;
335     LPITEMIDLIST pidllist;
336 
337     ZeroMemory(&bi, sizeof(bi));
338     bi.hwndOwner = hwndDlg;
339     bi.ulFlags = BIF_NEWDIALOGSTYLE;
340 
341     hwndListView = GetDlgItem(hwndDlg, IDC_LIST_VARIABLE_VALUE);
342 
343     pidllist = SHBrowseForFolder(&bi);
344     if (!pidllist)
345     {
346         return;
347     }
348 
349     if (SHGetPathFromIDList(pidllist, szDir))
350     {
351         if (DlgData->dwDlgID == IDD_EDIT_VARIABLE_FANCY)
352         {
353             /* If no item is selected then create a new empty item and add the required location to it */
354             if (!DlgData->bIsItemSelected)
355             {
356                 DlgData->dwSelectedValueIndex = ListView_GetItemCount(hwndListView);
357                 AddEmptyItem(hwndListView, DlgData->dwSelectedValueIndex);
358             }
359             ListView_SetItemText(hwndListView,
360                                  DlgData->dwSelectedValueIndex,
361                                  0,
362                                  szDir);
363             ListView_SetItemState(hwndListView, DlgData->dwSelectedValueIndex,
364                                   LVIS_FOCUSED | LVIS_SELECTED,
365                                   LVIS_FOCUSED | LVIS_SELECTED);
366         }
367         else
368         {
369             SetDlgItemText(hwndDlg, IDC_VARIABLE_VALUE, szDir);
370         }
371     }
372 
373     CoTaskMemFree(pidllist);
374 }
375 
376 static VOID
377 MoveListItem(HWND hwndDlg,
378              PEDIT_DIALOG_DATA DlgData,
379              BOOL bMoveUp)
380 {
381     TCHAR szDest[MAX_PATH];
382     TCHAR szSource[MAX_PATH];
383     HWND hwndListView;
384     DWORD dwSrcIndex, dwDestIndex, dwLastIndex;
385 
386     hwndListView = GetDlgItem(hwndDlg, IDC_LIST_VARIABLE_VALUE);
387 
388     dwLastIndex = ListView_GetItemCount(hwndListView) - 1;
389     dwSrcIndex = DlgData->dwSelectedValueIndex;
390     dwDestIndex = bMoveUp ? (dwSrcIndex - 1) : (dwSrcIndex + 1);
391 
392     if ((bMoveUp && dwSrcIndex > 0) || (!bMoveUp && dwSrcIndex < dwLastIndex))
393     {
394         ListView_GetItemText(hwndListView,
395                              dwSrcIndex,
396                              0,
397                              szDest,
398                              _countof(szDest));
399         ListView_GetItemText(hwndListView,
400                              dwDestIndex,
401                              0,
402                              szSource,
403                              _countof(szSource));
404 
405         ListView_SetItemText(hwndListView,
406                              dwDestIndex,
407                              0,
408                              szDest);
409         ListView_SetItemText(hwndListView,
410                              dwSrcIndex,
411                              0,
412                              szSource);
413 
414         DlgData->dwSelectedValueIndex = dwDestIndex;
415         ListView_SetItemState(hwndListView, DlgData->dwSelectedValueIndex,
416                               LVIS_FOCUSED | LVIS_SELECTED,
417                               LVIS_FOCUSED | LVIS_SELECTED);
418     }
419 }
420 
421 static VOID
422 OnEnvironmentEditDlgResize(HWND hwndDlg,
423                            PEDIT_DIALOG_DATA DlgData,
424                            DWORD cx,
425                            DWORD cy)
426 {
427     RECT rect;
428     HDWP hdwp = NULL;
429     HWND hItemWnd;
430 
431     if ((cx == DlgData->cxOld) && (cy == DlgData->cyOld))
432         return;
433 
434     if (DlgData->dwDlgID == IDD_EDIT_VARIABLE)
435     {
436         hdwp = BeginDeferWindowPos(5);
437 
438         /* For the edit control */
439         hItemWnd = GetDlgItem(hwndDlg, IDC_VARIABLE_NAME);
440         GetWindowRect(hItemWnd, &rect);
441         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
442 
443         if (hdwp)
444         {
445             hdwp = DeferWindowPos(hdwp,
446                                   hItemWnd,
447                                   NULL,
448                                   0, 0,
449                                   (rect.right - rect.left) + (cx - DlgData->cxOld),
450                                   rect.bottom - rect.top,
451                                   SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
452         }
453 
454         hItemWnd = GetDlgItem(hwndDlg, IDC_VARIABLE_VALUE);
455         GetWindowRect(hItemWnd, &rect);
456         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
457 
458         if (hdwp)
459         {
460             hdwp = DeferWindowPos(hdwp,
461                                   hItemWnd,
462                                   NULL,
463                                   0, 0,
464                                   (rect.right - rect.left) + (cx - DlgData->cxOld),
465                                   rect.bottom - rect.top,
466                                   SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
467         }
468     }
469     else if (DlgData->dwDlgID == IDD_EDIT_VARIABLE_FANCY)
470     {
471         hdwp = BeginDeferWindowPos(11);
472 
473         /* For the list view control */
474         hItemWnd = GetDlgItem(hwndDlg, IDC_LIST_VARIABLE_VALUE);
475         GetWindowRect(hItemWnd, &rect);
476         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
477 
478         if (hdwp)
479         {
480             hdwp = DeferWindowPos(hdwp,
481                                   hItemWnd,
482                                   NULL,
483                                   0, 0,
484                                   (rect.right - rect.left) + (cx - DlgData->cxOld),
485                                   (rect.bottom - rect.top) + (cy - DlgData->cyOld),
486                                   SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
487             ListView_SetColumnWidth(hItemWnd, 0, (rect.right - rect.left) + (cx - DlgData->cxOld));
488         }
489 
490         /* For the buttons */
491         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_BROWSE_FOLDER);
492         GetWindowRect(hItemWnd, &rect);
493         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
494 
495         if (hdwp)
496         {
497             hdwp = DeferWindowPos(hdwp,
498                                   hItemWnd,
499                                   NULL,
500                                   rect.left + (cx - DlgData->cxOld),
501                                   rect.top,
502                                   0, 0,
503                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
504         }
505 
506         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_NEW);
507         GetWindowRect(hItemWnd, &rect);
508         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
509 
510         if (hdwp)
511         {
512             hdwp = DeferWindowPos(hdwp,
513                                   hItemWnd,
514                                   NULL,
515                                   rect.left + (cx - DlgData->cxOld),
516                                   rect.top,
517                                   0, 0,
518                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
519         }
520 
521         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_EDIT);
522         GetWindowRect(hItemWnd, &rect);
523         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
524 
525         if (hdwp)
526         {
527             hdwp = DeferWindowPos(hdwp,
528                                   hItemWnd,
529                                   NULL,
530                                   rect.left + (cx - DlgData->cxOld),
531                                   rect.top,
532                                   0, 0,
533                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
534         }
535 
536         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE);
537         GetWindowRect(hItemWnd, &rect);
538         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
539 
540         if (hdwp)
541         {
542             hdwp = DeferWindowPos(hdwp,
543                                   hItemWnd,
544                                   NULL,
545                                   rect.left + (cx - DlgData->cxOld),
546                                   rect.top,
547                                   0, 0,
548                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
549         }
550 
551         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_MOVE_UP);
552         GetWindowRect(hItemWnd, &rect);
553         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
554 
555         if (hdwp)
556         {
557             hdwp = DeferWindowPos(hdwp,
558                                   hItemWnd,
559                                   NULL,
560                                   rect.left + (cx - DlgData->cxOld),
561                                   rect.top,
562                                   0, 0,
563                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
564         }
565 
566         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_MOVE_DOWN);
567         GetWindowRect(hItemWnd, &rect);
568         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
569 
570         if (hdwp)
571         {
572             hdwp = DeferWindowPos(hdwp,
573                                   hItemWnd,
574                                   NULL,
575                                   rect.left + (cx - DlgData->cxOld),
576                                   rect.top,
577                                   0, 0,
578                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
579         }
580 
581         hItemWnd = GetDlgItem(hwndDlg, IDC_BUTTON_EDIT_TEXT);
582         GetWindowRect(hItemWnd, &rect);
583         MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
584 
585         if (hdwp)
586         {
587             hdwp = DeferWindowPos(hdwp,
588                                   hItemWnd,
589                                   NULL,
590                                   rect.left + (cx - DlgData->cxOld),
591                                   rect.top,
592                                   0, 0,
593                                   SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
594         }
595     }
596 
597     hItemWnd = GetDlgItem(hwndDlg, IDOK);
598     GetWindowRect(hItemWnd, &rect);
599     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
600 
601     if (hdwp)
602     {
603         hdwp = DeferWindowPos(hdwp,
604                               hItemWnd,
605                               NULL,
606                               rect.left + (cx - DlgData->cxOld),
607                               rect.top + (cy - DlgData->cyOld),
608                               0, 0,
609                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
610     }
611 
612     hItemWnd = GetDlgItem(hwndDlg, IDCANCEL);
613     GetWindowRect(hItemWnd, &rect);
614     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
615 
616     if (hdwp)
617     {
618         hdwp = DeferWindowPos(hdwp,
619                               hItemWnd,
620                               NULL,
621                               rect.left + (cx - DlgData->cxOld),
622                               rect.top + (cy - DlgData->cyOld),
623                               0, 0,
624                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
625     }
626 
627     /* For the size grip */
628     hItemWnd = GetDlgItem(hwndDlg, IDC_DIALOG_GRIP);
629     GetWindowRect(hItemWnd, &rect);
630     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
631 
632     if (hdwp)
633     {
634         hdwp = DeferWindowPos(hdwp,
635                               hItemWnd,
636                               NULL,
637                               rect.left + (cx - DlgData->cxOld),
638                               rect.top + (cy - DlgData->cyOld),
639                               0, 0,
640                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
641     }
642 
643     if (hdwp)
644     {
645         EndDeferWindowPos(hdwp);
646     }
647 
648     DlgData->cxOld = cx;
649     DlgData->cyOld = cy;
650 }
651 
652 static BOOL
653 OnBeginLabelEdit(NMLVDISPINFO* pnmv)
654 {
655     HWND hwndEdit;
656 
657     hwndEdit = ListView_GetEditControl(pnmv->hdr.hwndFrom);
658     if (hwndEdit == NULL)
659     {
660         return TRUE;
661     }
662 
663     SendMessage(hwndEdit, EM_SETLIMITTEXT, MAX_PATH - 1, 0);
664 
665     return FALSE;
666 }
667 
668 static BOOL
669 OnEndLabelEdit(NMLVDISPINFO* pnmv)
670 {
671     HWND hwndEdit;
672     TCHAR szOldDir[MAX_PATH];
673     TCHAR szNewDir[MAX_PATH];
674 
675     hwndEdit = ListView_GetEditControl(pnmv->hdr.hwndFrom);
676     if (hwndEdit == NULL)
677     {
678         return TRUE;
679     }
680 
681     /* Leave, if there is no valid listview item */
682     if (pnmv->item.iItem == -1)
683     {
684         return FALSE;
685     }
686 
687     ListView_GetItemText(pnmv->hdr.hwndFrom,
688                          pnmv->item.iItem, 0,
689                          szOldDir,
690                          _countof(szOldDir));
691 
692     SendMessage(hwndEdit, WM_GETTEXT, _countof(szNewDir), (LPARAM)szNewDir);
693 
694     /* If there is nothing in the text box then remove the item */
695     if (_tcslen(szNewDir) == 0)
696     {
697         ListView_DeleteItem(pnmv->hdr.hwndFrom, pnmv->item.iItem);
698         ListView_SetItemState(pnmv->hdr.hwndFrom, pnmv->item.iItem - 1,
699                               LVIS_FOCUSED | LVIS_SELECTED,
700                               LVIS_FOCUSED | LVIS_SELECTED);
701         return FALSE;
702     }
703 
704     /* If nothing has been changed then just bail out */
705     if (_tcscmp(szOldDir, szNewDir) == 0)
706     {
707         return FALSE;
708     }
709 
710     ListView_SetItemText(pnmv->hdr.hwndFrom,
711                          pnmv->item.iItem, 0,
712                          szNewDir);
713 
714     return TRUE;
715 }
716 
717 static BOOL
718 OnNotifyEditVariableDlg(HWND hwndDlg, PEDIT_DIALOG_DATA DlgData, NMHDR *phdr)
719 {
720     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
721 
722     switch (phdr->idFrom)
723     {
724         case IDC_LIST_VARIABLE_VALUE:
725             switch (phdr->code)
726             {
727                 case NM_CLICK:
728                 {
729                     /* Detect if an item is selected */
730                     DlgData->bIsItemSelected = (lpnmlv->iItem != -1);
731                     if (lpnmlv->iItem != -1)
732                     {
733                         DlgData->dwSelectedValueIndex = lpnmlv->iItem;
734                     }
735                     break;
736                 }
737 
738                 case NM_DBLCLK:
739                 {
740                     /* Either simulate IDC_BUTTON_NEW or edit an item depending upon the condition */
741                     if (lpnmlv->iItem == -1)
742                     {
743                         SendMessage(GetDlgItem(hwndDlg, IDC_BUTTON_NEW), BM_CLICK, 0, 0);
744                     }
745                     else
746                     {
747                         ListView_EditLabel(GetDlgItem(hwndDlg, IDC_LIST_VARIABLE_VALUE), DlgData->dwSelectedValueIndex);
748                     }
749                     break;
750                 }
751 
752                 case LVN_BEGINLABELEDIT:
753                 {
754                     return OnBeginLabelEdit((NMLVDISPINFO*)phdr);
755                 }
756 
757                 case LVN_ENDLABELEDIT:
758                 {
759                     return OnEndLabelEdit((NMLVDISPINFO*)phdr);
760                 }
761             }
762             break;
763     }
764 
765     return FALSE;
766 }
767 
768 static INT_PTR CALLBACK
769 EditVariableDlgProc(HWND hwndDlg,
770                     UINT uMsg,
771                     WPARAM wParam,
772                     LPARAM lParam)
773 {
774     PEDIT_DIALOG_DATA DlgData;
775     HWND hwndListView;
776 
777     DlgData = (PEDIT_DIALOG_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
778     hwndListView = GetDlgItem(hwndDlg, IDC_LIST_VARIABLE_VALUE);
779 
780     switch (uMsg)
781     {
782         case WM_INITDIALOG:
783         {
784             RECT rect;
785 
786             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
787             DlgData = (PEDIT_DIALOG_DATA)lParam;
788 
789             GetClientRect(hwndDlg, &rect);
790             DlgData->cxOld = rect.right - rect.left;
791             DlgData->cyOld = rect.bottom - rect.top;
792 
793             GetWindowRect(hwndDlg, &rect);
794             DlgData->cxMin = rect.right - rect.left;
795             DlgData->cyMin = rect.bottom - rect.top;
796 
797             /* Either get the values from list box or from edit box */
798             if (DlgData->dwDlgID == IDD_EDIT_VARIABLE_FANCY)
799             {
800                 /* Subclass the listview control first */
801                 SetWindowSubclass(hwndListView, ListViewSubclassProc, 1, 0);
802 
803                 if (DlgData->VarData->lpRawValue != NULL)
804                 {
805                     AddValuesToList(hwndDlg, DlgData);
806                 }
807             }
808             else
809             {
810                 if (DlgData->VarData->lpName != NULL)
811                 {
812                     SendDlgItemMessage(hwndDlg, IDC_VARIABLE_NAME, WM_SETTEXT, 0, (LPARAM)DlgData->VarData->lpName);
813                 }
814 
815                 if (DlgData->VarData->lpRawValue != NULL)
816                 {
817                     SendDlgItemMessage(hwndDlg, IDC_VARIABLE_VALUE, WM_SETTEXT, 0, (LPARAM)DlgData->VarData->lpRawValue);
818                 }
819             }
820             break;
821         }
822 
823         case WM_SIZE:
824         {
825             OnEnvironmentEditDlgResize(hwndDlg, DlgData, LOWORD(lParam), HIWORD(lParam));
826             SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, 0);
827             return TRUE;
828         }
829 
830         case WM_SIZING:
831         {
832             /* Forbid resizing the dialog smaller than its minimal size */
833             PRECT pRect = (PRECT)lParam;
834 
835             if ((wParam == WMSZ_LEFT) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_BOTTOMLEFT))
836             {
837                 if (pRect->right - pRect->left < DlgData->cxMin)
838                     pRect->left = pRect->right - DlgData->cxMin;
839             }
840             else
841             if ((wParam == WMSZ_RIGHT) || (wParam == WMSZ_TOPRIGHT) || (wParam == WMSZ_BOTTOMRIGHT))
842             {
843                 if (pRect->right - pRect->left < DlgData->cxMin)
844                     pRect->right = pRect->left + DlgData->cxMin;
845             }
846 
847             if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT))
848             {
849                 if (pRect->bottom - pRect->top < DlgData->cyMin)
850                     pRect->top = pRect->bottom - DlgData->cyMin;
851             }
852             else
853             if ((wParam == WMSZ_BOTTOM) || (wParam == WMSZ_BOTTOMLEFT) || (wParam == WMSZ_BOTTOMRIGHT))
854             {
855                 if (pRect->bottom - pRect->top < DlgData->cyMin)
856                     pRect->bottom = pRect->top + DlgData->cyMin;
857             }
858 
859             /* Make sure the normal variable edit dialog doesn't change its height */
860             if (DlgData->dwDlgID == IDD_EDIT_VARIABLE)
861             {
862                 if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT))
863                 {
864                     if (pRect->bottom - pRect->top > DlgData->cyMin)
865                         pRect->top = pRect->bottom - DlgData->cyMin;
866                 }
867                 else
868                 if ((wParam == WMSZ_BOTTOM) || (wParam == WMSZ_BOTTOMLEFT) || (wParam == WMSZ_BOTTOMRIGHT))
869                 {
870                     if (pRect->bottom - pRect->top > DlgData->cyMin)
871                         pRect->bottom = pRect->top + DlgData->cyMin;
872                 }
873             }
874 
875             SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
876             return TRUE;
877         }
878 
879         case WM_NOTIFY:
880         {
881             return OnNotifyEditVariableDlg(hwndDlg, DlgData, (NMHDR*)lParam);
882         }
883 
884         case WM_COMMAND:
885             switch (LOWORD(wParam))
886             {
887                 case IDOK:
888                 {
889                     LPTSTR p;
890                     DWORD dwValueLength;
891 
892                     /* Either set the values to the list box or to the edit box */
893                     if (DlgData->dwDlgID == IDD_EDIT_VARIABLE_FANCY)
894                     {
895                         dwValueLength = GatherDataFromListView(hwndListView, DlgData->VarData);
896                     }
897                     else
898                     {
899                         dwValueLength = GatherDataFromEditBox(hwndDlg, DlgData->VarData);
900                     }
901 
902                     if (dwValueLength == 0)
903                     {
904                         break;
905                     }
906 
907                     if (DlgData->VarData->lpCookedValue != NULL)
908                     {
909                         GlobalFree(DlgData->VarData->lpCookedValue);
910                         DlgData->VarData->lpCookedValue = NULL;
911                     }
912 
913                     p = _tcschr(DlgData->VarData->lpRawValue, _T('%'));
914                     if (p && _tcschr(++p, _T('%')))
915                     {
916                         DlgData->VarData->dwType = REG_EXPAND_SZ;
917 
918                         DlgData->VarData->lpCookedValue = GlobalAlloc(GPTR, 2 * MAX_PATH * sizeof(TCHAR));
919                         if (!DlgData->VarData->lpCookedValue)
920                             return FALSE;
921 
922                         ExpandEnvironmentStrings(DlgData->VarData->lpRawValue,
923                                                  DlgData->VarData->lpCookedValue,
924                                                  2 * MAX_PATH);
925                     }
926                     else
927                     {
928                         DlgData->VarData->dwType = REG_SZ;
929 
930                         DlgData->VarData->lpCookedValue = GlobalAlloc(GPTR, (dwValueLength + 1) * sizeof(TCHAR));
931                         if (!DlgData->VarData->lpCookedValue)
932                             return FALSE;
933 
934                         _tcscpy(DlgData->VarData->lpCookedValue, DlgData->VarData->lpRawValue);
935                     }
936 
937                     EndDialog(hwndDlg, 1);
938                     return TRUE;
939                 }
940 
941                 case IDCANCEL:
942                     EndDialog(hwndDlg, 0);
943                     return TRUE;
944 
945                 case IDC_BUTTON_BROWSE_FILE:
946                 {
947                     BrowseRequiredFile(hwndDlg);
948                     break;
949                 }
950 
951                 case IDC_BUTTON_BROWSE_FOLDER:
952                 {
953                     BrowseRequiredFolder(hwndDlg, DlgData);
954                     break;
955                 }
956 
957                 case IDC_BUTTON_DELETE:
958                 {
959                     DWORD dwLastIndex;
960 
961                     dwLastIndex = ListView_GetItemCount(hwndListView) - 1;
962                     ListView_DeleteItem(hwndListView, DlgData->dwSelectedValueIndex);
963 
964                     if (dwLastIndex == DlgData->dwSelectedValueIndex)
965                     {
966                         DlgData->dwSelectedValueIndex--;
967                     }
968 
969                     ListView_SetItemState(hwndListView, DlgData->dwSelectedValueIndex,
970                                           LVIS_FOCUSED | LVIS_SELECTED,
971                                           LVIS_FOCUSED | LVIS_SELECTED);
972                     break;
973                 }
974 
975                 case IDC_BUTTON_MOVE_UP:
976                 {
977                     MoveListItem(hwndDlg, DlgData, TRUE);
978                     break;
979                 }
980 
981                 case IDC_BUTTON_MOVE_DOWN:
982                 {
983                     MoveListItem(hwndDlg, DlgData, FALSE);
984                     break;
985                 }
986 
987                 case IDC_BUTTON_EDIT_TEXT:
988                 {
989                     TCHAR szStr[MAX_STR_LENGTH] = _T("");
990                     TCHAR szStr2[MAX_STR_LENGTH] = _T("");
991 
992                     LoadString(hApplet, IDS_ENVIRONMENT_WARNING, szStr, _countof(szStr));
993                     LoadString(hApplet, IDS_ENVIRONMENT_WARNING_TITLE, szStr2, _countof(szStr2));
994 
995                     if (MessageBox(hwndDlg,
996                                    szStr,
997                                    szStr2,
998                                    MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON1) == IDOK)
999                     {
1000                         EndDialog(hwndDlg, -1);
1001                     }
1002                     break;
1003                 }
1004 
1005                 case IDC_BUTTON_NEW:
1006                 {
1007                     DlgData->dwSelectedValueIndex = ListView_GetItemCount(hwndListView);
1008                     AddEmptyItem(hwndListView, DlgData->dwSelectedValueIndex);
1009                     ListView_EditLabel(hwndListView, DlgData->dwSelectedValueIndex);
1010                     break;
1011                 }
1012 
1013                 case IDC_BUTTON_EDIT:
1014                 {
1015                     ListView_EditLabel(hwndListView, DlgData->dwSelectedValueIndex);
1016                     break;
1017                 }
1018             }
1019             break;
1020     }
1021 
1022     return FALSE;
1023 }
1024 
1025 
1026 static VOID
1027 GetEnvironmentVariables(HWND hwndListView,
1028                         HKEY hRootKey,
1029                         LPTSTR lpSubKeyName)
1030 {
1031     HKEY hKey;
1032     DWORD dwValues;
1033     DWORD dwMaxValueNameLength;
1034     DWORD dwMaxValueDataLength;
1035     DWORD i;
1036     LPTSTR lpName;
1037     LPTSTR lpData;
1038     LPTSTR lpExpandData;
1039     DWORD dwNameLength;
1040     DWORD dwDataLength;
1041     DWORD dwType;
1042     PVARIABLE_DATA VarData;
1043 
1044     LV_ITEM lvi;
1045     int iItem;
1046 
1047     if (RegOpenKeyEx(hRootKey,
1048                      lpSubKeyName,
1049                      0,
1050                      KEY_READ,
1051                      &hKey))
1052         return;
1053 
1054     if (RegQueryInfoKey(hKey,
1055                         NULL,
1056                         NULL,
1057                         NULL,
1058                         NULL,
1059                         NULL,
1060                         NULL,
1061                         &dwValues,
1062                         &dwMaxValueNameLength,
1063                         &dwMaxValueDataLength,
1064                         NULL,
1065                         NULL))
1066     {
1067         RegCloseKey(hKey);
1068         return;
1069     }
1070 
1071     lpName = GlobalAlloc(GPTR, (dwMaxValueNameLength + 1) * sizeof(TCHAR));
1072     if (lpName == NULL)
1073     {
1074         RegCloseKey(hKey);
1075         return;
1076     }
1077 
1078     lpData = GlobalAlloc(GPTR, (dwMaxValueDataLength + 1) * sizeof(TCHAR));
1079     if (lpData == NULL)
1080     {
1081         GlobalFree(lpName);
1082         RegCloseKey(hKey);
1083         return;
1084     }
1085 
1086     lpExpandData = GlobalAlloc(GPTR, 2048 * sizeof(TCHAR));
1087     if (lpExpandData == NULL)
1088     {
1089         GlobalFree(lpName);
1090         GlobalFree(lpData);
1091         RegCloseKey(hKey);
1092         return;
1093     }
1094 
1095     for (i = 0; i < dwValues; i++)
1096     {
1097         dwNameLength = dwMaxValueNameLength + 1;
1098         dwDataLength = dwMaxValueDataLength + 1;
1099 
1100         if (RegEnumValue(hKey,
1101                          i,
1102                          lpName,
1103                          &dwNameLength,
1104                          NULL,
1105                          &dwType,
1106                          (LPBYTE)lpData,
1107                          &dwDataLength))
1108         {
1109             GlobalFree(lpExpandData);
1110             GlobalFree(lpName);
1111             GlobalFree(lpData);
1112             RegCloseKey(hKey);
1113             return;
1114         }
1115 
1116         if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
1117             continue;
1118 
1119         VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
1120 
1121         VarData->dwType = dwType;
1122 
1123         VarData->lpName = GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
1124         _tcscpy(VarData->lpName, lpName);
1125 
1126         VarData->lpRawValue = GlobalAlloc(GPTR, (dwDataLength + 1) * sizeof(TCHAR));
1127         _tcscpy(VarData->lpRawValue, lpData);
1128 
1129         ExpandEnvironmentStrings(lpData, lpExpandData, 2048);
1130 
1131         VarData->lpCookedValue = GlobalAlloc(GPTR, (_tcslen(lpExpandData) + 1) * sizeof(TCHAR));
1132         _tcscpy(VarData->lpCookedValue, lpExpandData);
1133 
1134         memset(&lvi, 0x00, sizeof(lvi));
1135         lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
1136         lvi.lParam = (LPARAM)VarData;
1137         lvi.pszText = VarData->lpName;
1138         lvi.state = (i == 0) ? LVIS_SELECTED : 0;
1139         iItem = ListView_InsertItem(hwndListView, &lvi);
1140 
1141         ListView_SetItemText(hwndListView, iItem, 1, VarData->lpCookedValue);
1142     }
1143 
1144     GlobalFree(lpExpandData);
1145     GlobalFree(lpName);
1146     GlobalFree(lpData);
1147     RegCloseKey(hKey);
1148 }
1149 
1150 
1151 static VOID
1152 SetEnvironmentDialogListViewColumns(HWND hwndListView)
1153 {
1154     RECT rect;
1155     LV_COLUMN column;
1156     TCHAR szStr[32];
1157 
1158     GetClientRect(hwndListView, &rect);
1159 
1160     memset(&column, 0x00, sizeof(column));
1161     column.mask=LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
1162     column.fmt=LVCFMT_LEFT;
1163     column.cx = (INT)((rect.right - rect.left) * 0.32);
1164     column.iSubItem = 0;
1165     LoadString(hApplet, IDS_VARIABLE, szStr, sizeof(szStr) / sizeof(szStr[0]));
1166     column.pszText = szStr;
1167     (void)ListView_InsertColumn(hwndListView, 0, &column);
1168 
1169     column.cx = (INT)((rect.right - rect.left) * 0.63);
1170     column.iSubItem = 1;
1171     LoadString(hApplet, IDS_VALUE, szStr, sizeof(szStr) / sizeof(szStr[0]));
1172     column.pszText = szStr;
1173     (void)ListView_InsertColumn(hwndListView, 1, &column);
1174 }
1175 
1176 
1177 static VOID
1178 OnInitEnvironmentDialog(HWND hwndDlg)
1179 {
1180     HWND hwndListView;
1181 
1182     /* Set user environment variables */
1183     hwndListView = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_LIST);
1184 
1185     (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
1186 
1187     SetEnvironmentDialogListViewColumns(hwndListView);
1188 
1189     GetEnvironmentVariables(hwndListView,
1190                             HKEY_CURRENT_USER,
1191                             _T("Environment"));
1192 
1193     (void)ListView_SetColumnWidth(hwndListView, 2, LVSCW_AUTOSIZE_USEHEADER);
1194 
1195     ListView_SetItemState(hwndListView, 0,
1196                           LVIS_FOCUSED | LVIS_SELECTED,
1197                           LVIS_FOCUSED | LVIS_SELECTED);
1198 
1199     (void)ListView_Update(hwndListView,0);
1200 
1201     /* Set system environment variables */
1202     hwndListView = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1203 
1204     (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
1205 
1206     SetEnvironmentDialogListViewColumns(hwndListView);
1207 
1208     GetEnvironmentVariables(hwndListView,
1209                             HKEY_LOCAL_MACHINE,
1210                             _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"));
1211 
1212     (void)ListView_SetColumnWidth(hwndListView, 2, LVSCW_AUTOSIZE_USEHEADER);
1213 
1214     ListView_SetItemState(hwndListView, 0,
1215                           LVIS_FOCUSED | LVIS_SELECTED,
1216                           LVIS_FOCUSED | LVIS_SELECTED);
1217 
1218     (void)ListView_Update(hwndListView, 0);
1219 }
1220 
1221 
1222 static VOID
1223 OnNewVariable(HWND hwndDlg,
1224               INT iDlgItem)
1225 {
1226     HWND hwndListView;
1227     PEDIT_DIALOG_DATA DlgData;
1228     LV_ITEM lvi;
1229     INT iItem;
1230 
1231     DlgData = GlobalAlloc(GPTR, sizeof(EDIT_DIALOG_DATA));
1232     if (!DlgData)
1233         return;
1234 
1235     hwndListView = GetDlgItem(hwndDlg, iDlgItem);
1236     DlgData->dwDlgID = IDD_EDIT_VARIABLE;
1237     DlgData->dwSelectedValueIndex = -1;
1238 
1239     DlgData->VarData = GlobalAlloc(GPTR, sizeof(VARIABLE_DATA));
1240     if (!DlgData->VarData)
1241         return;
1242 
1243     if (DialogBoxParam(hApplet,
1244                        MAKEINTRESOURCE(DlgData->dwDlgID),
1245                        hwndDlg,
1246                        EditVariableDlgProc,
1247                        (LPARAM)DlgData) <= 0)
1248     {
1249         if (DlgData->VarData->lpName != NULL)
1250             GlobalFree(DlgData->VarData->lpName);
1251 
1252         if (DlgData->VarData->lpRawValue != NULL)
1253             GlobalFree(DlgData->VarData->lpRawValue);
1254 
1255         if (DlgData->VarData->lpCookedValue != NULL)
1256             GlobalFree(DlgData->VarData->lpCookedValue);
1257 
1258         GlobalFree(DlgData);
1259     }
1260     else
1261     {
1262         if (DlgData->VarData->lpName != NULL && (DlgData->VarData->lpCookedValue || DlgData->VarData->lpRawValue))
1263         {
1264             ZeroMemory(&lvi, sizeof(lvi));
1265             lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
1266             lvi.lParam = (LPARAM)DlgData->VarData;
1267             lvi.pszText = DlgData->VarData->lpName;
1268             lvi.state = 0;
1269             iItem = ListView_InsertItem(hwndListView, &lvi);
1270 
1271             ListView_SetItemText(hwndListView, iItem, 1, DlgData->VarData->lpCookedValue);
1272         }
1273     }
1274 }
1275 
1276 
1277 static VOID
1278 OnEditVariable(HWND hwndDlg,
1279                INT iDlgItem)
1280 {
1281     HWND hwndListView;
1282     PEDIT_DIALOG_DATA DlgData;
1283     LV_ITEM lvi;
1284     INT iItem;
1285     INT iRet;
1286 
1287     DlgData = GlobalAlloc(GPTR, sizeof(EDIT_DIALOG_DATA));
1288     if (!DlgData)
1289         return;
1290 
1291     DlgData->dwDlgID = IDD_EDIT_VARIABLE;
1292     DlgData->dwSelectedValueIndex = -1;
1293 
1294     hwndListView = GetDlgItem(hwndDlg, iDlgItem);
1295 
1296     iItem = GetSelectedListViewItem(hwndListView);
1297     if (iItem != -1)
1298     {
1299         ZeroMemory(&lvi, sizeof(lvi));
1300         lvi.mask = LVIF_PARAM;
1301         lvi.iItem = iItem;
1302 
1303         if (ListView_GetItem(hwndListView, &lvi))
1304         {
1305             DlgData->VarData = (PVARIABLE_DATA)lvi.lParam;
1306 
1307             /* If the value has multiple values and directories then edit value with fancy dialog box */
1308             if (DetermineDialogBoxType(DlgData->VarData->lpRawValue))
1309                 DlgData->dwDlgID = IDD_EDIT_VARIABLE_FANCY;
1310 
1311             iRet = DialogBoxParam(hApplet,
1312                                   MAKEINTRESOURCE(DlgData->dwDlgID),
1313                                   hwndDlg,
1314                                   EditVariableDlgProc,
1315                                   (LPARAM)DlgData);
1316 
1317             /* If iRet is less than 0 edit the value and name normally */
1318             if (iRet < 0)
1319             {
1320                 DlgData->dwDlgID = IDD_EDIT_VARIABLE;
1321                 iRet = DialogBoxParam(hApplet,
1322                                       MAKEINTRESOURCE(DlgData->dwDlgID),
1323                                       hwndDlg,
1324                                       EditVariableDlgProc,
1325                                       (LPARAM)DlgData);
1326             }
1327 
1328             if (iRet > 0)
1329             {
1330                 ListView_SetItemText(hwndListView, iItem, 0, DlgData->VarData->lpName);
1331                 ListView_SetItemText(hwndListView, iItem, 1, DlgData->VarData->lpCookedValue);
1332             }
1333         }
1334 
1335         GlobalFree(DlgData);
1336     }
1337 }
1338 
1339 
1340 static VOID
1341 OnDeleteVariable(HWND hwndDlg,
1342                  INT iDlgItem)
1343 {
1344     HWND hwndListView;
1345     PVARIABLE_DATA VarData;
1346     LV_ITEM lvi;
1347     INT iItem;
1348 
1349     hwndListView = GetDlgItem(hwndDlg, iDlgItem);
1350 
1351     iItem = GetSelectedListViewItem(hwndListView);
1352     if (iItem != -1)
1353     {
1354         memset(&lvi, 0x00, sizeof(lvi));
1355         lvi.mask = LVIF_PARAM;
1356         lvi.iItem = iItem;
1357 
1358         if (ListView_GetItem(hwndListView, &lvi))
1359         {
1360             VarData = (PVARIABLE_DATA)lvi.lParam;
1361             if (VarData != NULL)
1362             {
1363                 if (VarData->lpName != NULL)
1364                     GlobalFree(VarData->lpName);
1365 
1366                 if (VarData->lpRawValue != NULL)
1367                     GlobalFree(VarData->lpRawValue);
1368 
1369                 if (VarData->lpCookedValue != NULL)
1370                     GlobalFree(VarData->lpCookedValue);
1371 
1372                 GlobalFree(VarData);
1373                 lvi.lParam = 0;
1374             }
1375         }
1376 
1377         (void)ListView_DeleteItem(hwndListView, iItem);
1378 
1379         /* Select the previous item */
1380         if (iItem > 0)
1381             iItem--;
1382 
1383         ListView_SetItemState(hwndListView, iItem,
1384                               LVIS_FOCUSED | LVIS_SELECTED,
1385                               LVIS_FOCUSED | LVIS_SELECTED);
1386     }
1387 }
1388 
1389 static VOID
1390 OnEnvironmentDlgResize(HWND hwndDlg,
1391                        PENVIRONMENT_DIALOG_DATA DlgData,
1392                        DWORD cx,
1393                        DWORD cy)
1394 {
1395     RECT rect;
1396     INT Colx, y = 0;
1397     HDWP hdwp = NULL;
1398     HWND hItemWnd;
1399 
1400     if ((cx == DlgData->cxOld) && (cy == DlgData->cyOld))
1401         return;
1402 
1403     hdwp = BeginDeferWindowPos(13);
1404 
1405     if (cy >= DlgData->cyOld)
1406         y += (cy - DlgData->cyOld + 1) / 2;
1407     else
1408         y -= (DlgData->cyOld - cy + 1) / 2;
1409 
1410     /* For the group box controls */
1411     hItemWnd = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_GROUP);
1412     GetWindowRect(hItemWnd, &rect);
1413     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1414 
1415     if (hdwp)
1416     {
1417         hdwp = DeferWindowPos(hdwp,
1418                               hItemWnd,
1419                               NULL,
1420                               0, 0,
1421                               (rect.right - rect.left) + (cx - DlgData->cxOld),
1422                               (rect.bottom - rect.top) + y,
1423                               SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1424     }
1425 
1426     hItemWnd = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_GROUP);
1427     GetWindowRect(hItemWnd, &rect);
1428     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1429 
1430     if (hdwp)
1431     {
1432         hdwp = DeferWindowPos(hdwp,
1433                               hItemWnd,
1434                               NULL,
1435                               rect.left, rect.top + y,
1436                               (rect.right - rect.left) + (cx - DlgData->cxOld),
1437                               (rect.bottom - rect.top) + y,
1438                               SWP_NOZORDER | SWP_NOACTIVATE);
1439     }
1440 
1441     /* For the list view controls */
1442     hItemWnd = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_LIST);
1443     GetWindowRect(hItemWnd, &rect);
1444     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1445 
1446     if (hdwp)
1447     {
1448         hdwp = DeferWindowPos(hdwp,
1449                               hItemWnd,
1450                               NULL,
1451                               0, 0,
1452                               (rect.right - rect.left) + (cx - DlgData->cxOld),
1453                               (rect.bottom - rect.top) + y,
1454                               SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1455         Colx = ListView_GetColumnWidth(hItemWnd, 1);
1456         ListView_SetColumnWidth(hItemWnd, 1, Colx + (cx - DlgData->cxOld));
1457     }
1458 
1459     hItemWnd = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1460     GetWindowRect(hItemWnd, &rect);
1461     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1462 
1463     if (hdwp)
1464     {
1465         hdwp = DeferWindowPos(hdwp,
1466                               hItemWnd,
1467                               NULL,
1468                               rect.left, rect.top + y,
1469                               (rect.right - rect.left) + (cx - DlgData->cxOld),
1470                               (rect.bottom - rect.top) + y,
1471                               SWP_NOZORDER | SWP_NOACTIVATE);
1472         Colx = ListView_GetColumnWidth(hItemWnd, 1);
1473         ListView_SetColumnWidth(hItemWnd, 1, Colx + (cx - DlgData->cxOld));
1474     }
1475 
1476     /* For the buttons */
1477     hItemWnd = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_NEW);
1478     GetWindowRect(hItemWnd, &rect);
1479     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1480 
1481     if (hdwp)
1482     {
1483         hdwp = DeferWindowPos(hdwp,
1484                               hItemWnd,
1485                               NULL,
1486                               rect.left + (cx - DlgData->cxOld),
1487                               rect.top + y,
1488                               0, 0,
1489                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1490     }
1491 
1492     hItemWnd = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_EDIT);
1493     GetWindowRect(hItemWnd, &rect);
1494     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1495 
1496     if (hdwp)
1497     {
1498         hdwp = DeferWindowPos(hdwp,
1499                               hItemWnd,
1500                               NULL,
1501                               rect.left + (cx - DlgData->cxOld),
1502                               rect.top + y,
1503                               0, 0,
1504                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1505     }
1506 
1507     hItemWnd = GetDlgItem(hwndDlg, IDC_USER_VARIABLE_DELETE);
1508     GetWindowRect(hItemWnd, &rect);
1509     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1510 
1511     if (hdwp)
1512     {
1513         hdwp = DeferWindowPos(hdwp,
1514                               hItemWnd,
1515                               NULL,
1516                               rect.left + (cx - DlgData->cxOld),
1517                               rect.top + y,
1518                               0, 0,
1519                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1520     }
1521 
1522     hItemWnd = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_NEW);
1523     GetWindowRect(hItemWnd, &rect);
1524     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1525 
1526     if (hdwp)
1527     {
1528         hdwp = DeferWindowPos(hdwp,
1529                               hItemWnd,
1530                               NULL,
1531                               rect.left + (cx - DlgData->cxOld),
1532                               rect.top + y * 2,
1533                               0, 0,
1534                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1535     }
1536 
1537     hItemWnd = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_EDIT);
1538     GetWindowRect(hItemWnd, &rect);
1539     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1540 
1541     if (hdwp)
1542     {
1543         hdwp = DeferWindowPos(hdwp,
1544                               hItemWnd,
1545                               NULL,
1546                               rect.left + (cx - DlgData->cxOld),
1547                               rect.top + y * 2,
1548                               0, 0,
1549                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1550     }
1551 
1552     hItemWnd = GetDlgItem(hwndDlg, IDC_SYSTEM_VARIABLE_DELETE);
1553     GetWindowRect(hItemWnd, &rect);
1554     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1555 
1556     if (hdwp)
1557     {
1558         hdwp = DeferWindowPos(hdwp,
1559                               hItemWnd,
1560                               NULL,
1561                               rect.left + (cx - DlgData->cxOld),
1562                               rect.top + y * 2,
1563                               0, 0,
1564                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1565     }
1566 
1567     hItemWnd = GetDlgItem(hwndDlg, IDOK);
1568     GetWindowRect(hItemWnd, &rect);
1569     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1570 
1571     if (hdwp)
1572     {
1573         hdwp = DeferWindowPos(hdwp,
1574                               hItemWnd,
1575                               NULL,
1576                               rect.left + (cx - DlgData->cxOld),
1577                               rect.top + (cy - DlgData->cyOld),
1578                               0, 0,
1579                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1580     }
1581 
1582     hItemWnd = GetDlgItem(hwndDlg, IDCANCEL);
1583     GetWindowRect(hItemWnd, &rect);
1584     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1585 
1586     if (hdwp)
1587     {
1588         hdwp = DeferWindowPos(hdwp,
1589                               hItemWnd,
1590                               NULL,
1591                               rect.left + (cx - DlgData->cxOld),
1592                               rect.top + (cy - DlgData->cyOld),
1593                               0, 0,
1594                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1595     }
1596 
1597     /* For the size grip */
1598     hItemWnd = GetDlgItem(hwndDlg, IDC_DIALOG_GRIP);
1599     GetWindowRect(hItemWnd, &rect);
1600     MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
1601 
1602     if (hdwp)
1603     {
1604         hdwp = DeferWindowPos(hdwp,
1605                               hItemWnd,
1606                               NULL,
1607                               rect.left + (cx - DlgData->cxOld),
1608                               rect.top + (cy - DlgData->cyOld),
1609                               0, 0,
1610                               SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
1611     }
1612 
1613     if (hdwp)
1614     {
1615         EndDeferWindowPos(hdwp);
1616     }
1617 
1618     DlgData->cxOld = cx;
1619     DlgData->cyOld = cy;
1620 }
1621 
1622 static VOID
1623 ReleaseListViewItems(HWND hwndDlg,
1624                      INT iDlgItem)
1625 {
1626     HWND hwndListView;
1627     PVARIABLE_DATA VarData;
1628     LV_ITEM lvi;
1629     INT nItemCount;
1630     INT i;
1631 
1632     hwndListView = GetDlgItem(hwndDlg, iDlgItem);
1633 
1634     memset(&lvi, 0x00, sizeof(lvi));
1635 
1636     nItemCount = ListView_GetItemCount(hwndListView);
1637     for (i = 0; i < nItemCount; i++)
1638     {
1639         lvi.mask = LVIF_PARAM;
1640         lvi.iItem = i;
1641 
1642         if (ListView_GetItem(hwndListView, &lvi))
1643         {
1644             VarData = (PVARIABLE_DATA)lvi.lParam;
1645             if (VarData != NULL)
1646             {
1647                 if (VarData->lpName != NULL)
1648                     GlobalFree(VarData->lpName);
1649 
1650                 if (VarData->lpRawValue != NULL)
1651                     GlobalFree(VarData->lpRawValue);
1652 
1653                 if (VarData->lpCookedValue != NULL)
1654                     GlobalFree(VarData->lpCookedValue);
1655 
1656                 GlobalFree(VarData);
1657                 lvi.lParam = 0;
1658             }
1659         }
1660     }
1661 }
1662 
1663 
1664 static VOID
1665 SetAllVars(HWND hwndDlg,
1666            INT iDlgItem)
1667 {
1668     HWND hwndListView;
1669     PVARIABLE_DATA VarData;
1670     LV_ITEM lvi;
1671     INT iItem;
1672     HKEY hKey;
1673     DWORD dwValueCount;
1674     DWORD dwMaxValueNameLength;
1675     LPTSTR *aValueArray;
1676     DWORD dwNameLength;
1677     DWORD i;
1678     TCHAR szBuffer[256];
1679     LPTSTR lpBuffer;
1680 
1681     memset(&lvi, 0x00, sizeof(lvi));
1682 
1683     /* Get the handle to the list box with all system vars in it */
1684     hwndListView = GetDlgItem(hwndDlg, iDlgItem);
1685     /* First item is 0 */
1686     iItem = 0;
1687     /* Set up struct to retrieve item */
1688     lvi.mask = LVIF_PARAM;
1689     lvi.iItem = iItem;
1690 
1691     /* Open or create the key */
1692     if (RegCreateKeyEx((iDlgItem == IDC_SYSTEM_VARIABLE_LIST ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER),
1693                        (iDlgItem == IDC_SYSTEM_VARIABLE_LIST ? _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment") : _T("Environment")),
1694                        0,
1695                        NULL,
1696                        REG_OPTION_NON_VOLATILE,
1697                        KEY_WRITE | KEY_READ,
1698                        NULL,
1699                        &hKey,
1700                        NULL))
1701     {
1702         return;
1703     }
1704 
1705     /* Get the number of values and the maximum value name length */
1706     if (RegQueryInfoKey(hKey,
1707                         NULL,
1708                         NULL,
1709                         NULL,
1710                         NULL,
1711                         NULL,
1712                         NULL,
1713                         &dwValueCount,
1714                         &dwMaxValueNameLength,
1715                         NULL,
1716                         NULL,
1717                         NULL))
1718     {
1719         RegCloseKey(hKey);
1720         return;
1721     }
1722 
1723     if (dwValueCount > 0)
1724     {
1725         /* Allocate the value array */
1726         aValueArray = GlobalAlloc(GPTR, dwValueCount * sizeof(LPTSTR));
1727         if (aValueArray != NULL)
1728         {
1729             /* Get all value names */
1730             for (i = 0; i < dwValueCount; i++)
1731             {
1732                 dwNameLength = 256;
1733                 if (!RegEnumValue(hKey,
1734                                   i,
1735                                   szBuffer,
1736                                   &dwNameLength,
1737                                   NULL,
1738                                   NULL,
1739                                   NULL,
1740                                   NULL))
1741                 {
1742                     /* Allocate a value name buffer, fill it and attach it to the array */
1743                     lpBuffer = (LPTSTR)GlobalAlloc(GPTR, (dwNameLength + 1) * sizeof(TCHAR));
1744                     if (lpBuffer != NULL)
1745                     {
1746                         _tcscpy(lpBuffer, szBuffer);
1747                         aValueArray[i] = lpBuffer;
1748                     }
1749                 }
1750             }
1751 
1752             /* Delete all values */
1753             for (i = 0; i < dwValueCount; i++)
1754             {
1755                 if (aValueArray[i] != NULL)
1756                 {
1757                     /* Delete the value */
1758                     RegDeleteValue(hKey,
1759                                    aValueArray[i]);
1760 
1761                     /* Free the value name */
1762                     GlobalFree(aValueArray[i]);
1763                 }
1764             }
1765 
1766             /* Free the value array */
1767             GlobalFree(aValueArray);
1768         }
1769     }
1770 
1771     /* Loop through all variables */
1772     while (ListView_GetItem(hwndListView, &lvi))
1773     {
1774         /* Get the data in each item */
1775         VarData = (PVARIABLE_DATA)lvi.lParam;
1776         if (VarData != NULL)
1777         {
1778             /* Set the new value */
1779             if (RegSetValueEx(hKey,
1780                               VarData->lpName,
1781                               0,
1782                               VarData->dwType,
1783                               (LPBYTE)VarData->lpRawValue,
1784                               (DWORD)(_tcslen(VarData->lpRawValue) + 1) * sizeof(TCHAR)))
1785             {
1786                 RegCloseKey(hKey);
1787                 return;
1788             }
1789         }
1790 
1791         /* Fill struct for next item */
1792         lvi.mask = LVIF_PARAM;
1793         lvi.iItem = ++iItem;
1794     }
1795 
1796     RegCloseKey(hKey);
1797 }
1798 
1799 
1800 static BOOL
1801 OnNotify(HWND hwndDlg, NMHDR *phdr)
1802 {
1803     switch (phdr->code)
1804     {
1805         case NM_DBLCLK:
1806             if (phdr->idFrom == IDC_USER_VARIABLE_LIST ||
1807                 phdr->idFrom == IDC_SYSTEM_VARIABLE_LIST)
1808             {
1809                 OnEditVariable(hwndDlg, (INT)phdr->idFrom);
1810                 return TRUE;
1811             }
1812             break;
1813 
1814         case LVN_KEYDOWN:
1815             if (((LPNMLVKEYDOWN)phdr)->wVKey == VK_DELETE &&
1816                 (phdr->idFrom == IDC_USER_VARIABLE_LIST ||
1817                  phdr->idFrom == IDC_SYSTEM_VARIABLE_LIST))
1818             {
1819                 OnDeleteVariable(hwndDlg, (INT)phdr->idFrom);
1820                 return TRUE;
1821             }
1822             break;
1823     }
1824 
1825     return FALSE;
1826 }
1827 
1828 
1829 /* Environment dialog procedure */
1830 INT_PTR CALLBACK
1831 EnvironmentDlgProc(HWND hwndDlg,
1832                    UINT uMsg,
1833                    WPARAM wParam,
1834                    LPARAM lParam)
1835 {
1836     PENVIRONMENT_DIALOG_DATA DlgData;
1837     DlgData = (PENVIRONMENT_DIALOG_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1838 
1839     switch (uMsg)
1840     {
1841         case WM_INITDIALOG:
1842         {
1843             RECT rect;
1844 
1845             DlgData = GlobalAlloc(GPTR, sizeof(ENVIRONMENT_DIALOG_DATA));
1846             if (!DlgData)
1847             {
1848                 EndDialog(hwndDlg, 0);
1849                 return (INT_PTR)TRUE;
1850             }
1851             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)DlgData);
1852 
1853             GetClientRect(hwndDlg, &rect);
1854             DlgData->cxOld = rect.right - rect.left;
1855             DlgData->cyOld = rect.bottom - rect.top;
1856 
1857             GetWindowRect(hwndDlg, &rect);
1858             DlgData->cxMin = rect.right - rect.left;
1859             DlgData->cyMin = rect.bottom - rect.top;
1860 
1861             OnInitEnvironmentDialog(hwndDlg);
1862             break;
1863         }
1864 
1865         case WM_SIZE:
1866         {
1867             OnEnvironmentDlgResize(hwndDlg, DlgData, LOWORD(lParam), HIWORD(lParam));
1868             SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, 0);
1869             return TRUE;
1870         }
1871 
1872         case WM_SIZING:
1873         {
1874             /* Forbid resizing the dialog smaller than its minimal size */
1875             PRECT pRect = (PRECT)lParam;
1876 
1877             if ((wParam == WMSZ_LEFT) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_BOTTOMLEFT))
1878             {
1879                 if (pRect->right - pRect->left < DlgData->cxMin)
1880                     pRect->left = pRect->right - DlgData->cxMin;
1881             }
1882             else
1883             if ((wParam == WMSZ_RIGHT) || (wParam == WMSZ_TOPRIGHT) || (wParam == WMSZ_BOTTOMRIGHT))
1884             {
1885                 if (pRect->right - pRect->left < DlgData->cxMin)
1886                     pRect->right = pRect->left + DlgData->cxMin;
1887             }
1888 
1889             if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT))
1890             {
1891                 if (pRect->bottom - pRect->top < DlgData->cyMin)
1892                     pRect->top = pRect->bottom - DlgData->cyMin;
1893             }
1894             else
1895             if ((wParam == WMSZ_BOTTOM) || (wParam == WMSZ_BOTTOMLEFT) || (wParam == WMSZ_BOTTOMRIGHT))
1896             {
1897                 if (pRect->bottom - pRect->top < DlgData->cyMin)
1898                     pRect->bottom = pRect->top + DlgData->cyMin;
1899             }
1900 
1901             SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
1902             return TRUE;
1903         }
1904 
1905         case WM_COMMAND:
1906             switch (LOWORD(wParam))
1907             {
1908                 case IDC_USER_VARIABLE_NEW:
1909                     OnNewVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
1910                     return TRUE;
1911 
1912                 case IDC_USER_VARIABLE_EDIT:
1913                     OnEditVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
1914                     return TRUE;
1915 
1916                 case IDC_USER_VARIABLE_DELETE:
1917                     OnDeleteVariable(hwndDlg, IDC_USER_VARIABLE_LIST);
1918                     return TRUE;
1919 
1920                 case IDC_SYSTEM_VARIABLE_NEW:
1921                     OnNewVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1922                     return TRUE;
1923 
1924                 case IDC_SYSTEM_VARIABLE_EDIT:
1925                     OnEditVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1926                     return TRUE;
1927 
1928                 case IDC_SYSTEM_VARIABLE_DELETE:
1929                     OnDeleteVariable(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1930                     return TRUE;
1931 
1932                 case IDOK:
1933                     SetAllVars(hwndDlg, IDC_USER_VARIABLE_LIST);
1934                     SetAllVars(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1935                     SendMessage(HWND_BROADCAST, WM_WININICHANGE,
1936                                 0, (LPARAM)_T("Environment"));
1937                     EndDialog(hwndDlg, 0);
1938                     return TRUE;
1939 
1940                 case IDCANCEL:
1941                     EndDialog(hwndDlg, 0);
1942                     return TRUE;
1943             }
1944             break;
1945 
1946         case WM_DESTROY:
1947             ReleaseListViewItems(hwndDlg, IDC_USER_VARIABLE_LIST);
1948             ReleaseListViewItems(hwndDlg, IDC_SYSTEM_VARIABLE_LIST);
1949             GlobalFree(DlgData);
1950             break;
1951 
1952         case WM_NOTIFY:
1953             return OnNotify(hwndDlg, (NMHDR*)lParam);
1954     }
1955 
1956     return FALSE;
1957 }
1958 
1959 /* EOF */
1960