Message box to suggest the user not run wine as root.
[wine] / programs / winecfg / appdefaults.c
1 /*
2  * WineCfg app settings tabsheet
3  *
4  * Copyright 2004 Robert van Herk
5  *                Chris Morgan
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #define NONAMELESSUNION
24 #include <windows.h>
25 #include <commdlg.h>
26 #include <wine/debug.h>
27 #include <stdio.h>
28 #include "winecfg.h"
29 #include "resource.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
32
33 typedef struct _APPL
34 {
35   BOOL isGlobal;
36   char* lpcApplication;
37   char* lpcVersionSection;
38   char* lpcWinelookSection;
39 } APPL, *LPAPPL;
40
41 static LPAPPL CreateAppl(BOOL isGlobal, char* application, char* version_section, char* winelook_section)
42 {
43   LPAPPL out;
44   WINE_TRACE("application: '%s', version_section: '%s', winelook_section: '%s'\n", application,
45              version_section, winelook_section);
46   out = HeapAlloc(GetProcessHeap(),0,sizeof(APPL));
47   out->lpcApplication = strdup(application);
48   out->lpcVersionSection = strdup(version_section);
49   out->lpcWinelookSection = strdup(winelook_section);
50   out->isGlobal = isGlobal;
51   return out;
52 }
53
54 static VOID FreeAppl(LPAPPL lpAppl)
55 {
56  /* The strings were strdup-ped, so we use "free" */
57   if (lpAppl->lpcApplication) free(lpAppl->lpcApplication);
58   if (lpAppl->lpcVersionSection) free(lpAppl->lpcVersionSection);
59   if (lpAppl->lpcWinelookSection) free(lpAppl->lpcWinelookSection);
60   HeapFree(GetProcessHeap(),0,lpAppl);
61 }
62
63 /* section can be "Version" or "Tweak.Layout" */
64 /* key can be "Windows"/"Dos"/"WineLook" */
65 /* value can be appropriate values for the above keys */
66 typedef struct _APPSETTING
67 {
68   char* section;
69   char* lpcKey;
70   char* value;
71 } APPSETTING, *LPAPPSETTING;
72
73 static LPAPPSETTING CreateAppSetting(char* lpcKey, char* value)
74 {
75         LPAPPSETTING out = HeapAlloc(GetProcessHeap(),0,sizeof(APPSETTING));
76         out->lpcKey = strdup (lpcKey);
77         out->value = strdup(value);
78         return out;
79 }
80
81 static VOID FreeAppSetting(LPAPPSETTING las)
82 {
83   if (las->lpcKey) free(las->lpcKey);
84   if (las->value) free(las->value);
85   HeapFree(GetProcessHeap(),0,las);
86 }
87
88 typedef struct _ITEMTAG
89 {
90   LPAPPL lpAppl;
91   LPAPPSETTING lpSetting;
92 } ITEMTAG, *LPITEMTAG;
93
94 static LPITEMTAG CreateItemTag()
95 {
96   LPITEMTAG out;
97   out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG));
98   out->lpAppl = 0;
99   out->lpSetting = 0;
100   return out;
101 }
102
103 static VOID FreeItemTag(LPITEMTAG lpit)
104 {
105   /* if child, only free the lpSetting, the lpAppl will be freed when we free the parents item tag */
106   if (lpit->lpSetting)
107   {
108     FreeAppSetting(lpit->lpSetting);
109   } else
110   {
111     if (lpit->lpAppl)
112       FreeAppl(lpit->lpAppl);
113   }
114   HeapFree(GetProcessHeap(), 0, lpit);
115 }
116
117 static VOID LoadAppSettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV)
118 {
119   HKEY key;
120   int i;
121   DWORD size;
122   DWORD readSize;
123   char name [255];
124   char read [255];
125   char *description;
126   LPITEMTAG lpIt;
127   TVINSERTSTRUCT tis;   
128   HTREEITEM hParent;
129   LPAPPSETTING lpas;
130         
131   WINE_TRACE("opening '%s' and '%s'\n", appl->lpcVersionSection, appl->lpcWinelookSection);
132   if ((RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS) ||
133       (RegOpenKey (configKey, appl->lpcWinelookSection, &key) == ERROR_SUCCESS))
134   {
135      i = 0;
136      size = 255;
137      readSize = 255;
138
139      lpIt = CreateItemTag();
140      lpIt->lpAppl = appl;
141
142      tis.hParent = NULL;
143      tis.hInsertAfter = TVI_LAST;
144      tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
145      tis.u.item.pszText = appl->lpcApplication;
146      tis.u.item.lParam = (LPARAM)lpIt;
147      hParent = TreeView_InsertItem(hwndTV,&tis);
148      tis.hParent = hParent;
149
150      /* insert version entries */
151      if(RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
152      {
153        while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
154        {
155          char itemtext[128];
156
157          WINE_TRACE("Reading value %s, namely %s\n", name, read);
158                         
159          lpIt = CreateItemTag();
160          lpas = CreateAppSetting(name, read);
161          lpIt->lpSetting = lpas;
162          lpIt->lpAppl = appl;
163          tis.u.item.lParam = (LPARAM)lpIt;
164
165          /* convert the value for 'dosver or winver' to human readable form */
166          description = getDescriptionFromVersion(getWinVersions(), read);
167          if(!description)
168          {
169            description = getDescriptionFromVersion(getDOSVersions(), read);
170            if(!description)
171              description = "Not found";
172          }
173
174          sprintf(itemtext, "%s - %s", name, description);
175          tis.u.item.pszText = itemtext;
176
177          TreeView_InsertItem(hwndTV,&tis);
178          i++; size = 255; readSize = 255;
179        }
180        RegCloseKey(key);
181      } else
182      {
183        WINE_TRACE("no version section found\n");
184      }
185
186      i = 0; /* reset i to 0 before calling RegEnumValue() again */
187
188      /* insert winelook entries */
189      if(RegOpenKey (configKey, appl->lpcWinelookSection, &key) == ERROR_SUCCESS)
190      {
191        while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
192        {
193          char itemtext[128];
194
195          WINE_TRACE("Reading value %s, namely %s\n", name, read);
196                         
197          lpIt = CreateItemTag();
198          lpas = CreateAppSetting(name, read);
199          lpIt->lpSetting = lpas;
200          lpIt->lpAppl = appl;
201          tis.u.item.lParam = (LPARAM)lpIt;
202
203          /* convert the value for 'winelook' to human readable form */
204          description = getDescriptionFromVersion(getWinelook(), read);
205          if(!description) description = "Not found";
206          
207          sprintf(itemtext, "%s - %s", name, description);
208          tis.u.item.pszText = itemtext;
209
210          TreeView_InsertItem(hwndTV,&tis);
211          i++; size = 255; readSize = 255;
212        }
213        RegCloseKey(key);
214      } else
215      {
216        WINE_TRACE("no winelook section found\n");
217      }
218   }
219 }
220
221 static VOID SetEnabledAppControls(HWND dialog)
222 {
223 }
224
225 static VOID UpdateComboboxes(HWND hDlg, LPAPPL lpAppl)
226 {
227   int i;
228   const VERSION_DESC *pVer = NULL;
229
230   /* retrieve the registry values for this application */
231   char *curWinVer = getConfigValue(lpAppl->lpcVersionSection, "Windows", "");
232   char *curDOSVer = getConfigValue(lpAppl->lpcVersionSection, "DOS", "");
233   char *curWineLook = getConfigValue(lpAppl->lpcWinelookSection, "WineLook", "");
234
235   if(curWinVer) WINE_TRACE("curWinVer is '%s'\n", curWinVer);
236   else WINE_TRACE("curWinVer is null\n");
237   if(curDOSVer) WINE_TRACE("curDOSVer is '%s'\n", curDOSVer);
238   else WINE_TRACE("curDOSVer is null\n");
239   if(curWineLook) WINE_TRACE("curWineLook is '%s'\n", curWineLook);
240   else WINE_TRACE("curWineLook is null\n");
241
242   /* normalize the version strings */
243   if(strlen(curWinVer) != 0)
244   {
245     if ((pVer = getWinVersions ()))
246     {
247       WINE_TRACE("Windows version\n");
248       for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
249       {
250         WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
251         if (!strcasecmp (pVer->szVersion, curWinVer))
252         {
253           SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
254                               (WPARAM) i, 0);
255           WINE_TRACE("match with %s\n", pVer->szVersion);
256         }
257       }
258     }
259   } else /* clear selection */
260   {
261     WINE_TRACE("setting winver to nothing\n");
262     SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
263                         -1, 0);
264   }
265
266   if(strlen(curDOSVer) != 0)
267   {
268     if ((pVer = getDOSVersions ()))
269     {
270       WINE_TRACE("DOS version\n");
271       for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
272       {
273         WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
274         if (!strcasecmp (pVer->szVersion, curDOSVer))
275         {
276           SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
277                               (WPARAM) i, 0);
278           WINE_TRACE("match with %s\n", pVer->szVersion);
279         }
280       }
281     }
282   } else
283   {
284     WINE_TRACE("setting dosver to nothing\n");
285     SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
286                         -1, 0);
287   }
288
289   if(strlen(curWineLook) != 0)
290   {
291     if ((pVer = getWinelook ()))
292     {
293       WINE_TRACE("Winelook\n");
294
295       for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
296       {
297         WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
298         if (!strcasecmp (pVer->szVersion, curWineLook))
299         {
300           SendDlgItemMessage (hDlg, IDC_WINELOOK, CB_SETCURSEL,
301                               (WPARAM) i, 0);
302           WINE_TRACE("match with %s\n", pVer->szVersion);
303         }
304       }
305     }
306   } else
307   {
308     WINE_TRACE("setting winelook to nothing\n");
309     SendDlgItemMessage (hDlg, IDC_WINELOOK, CB_SETCURSEL,
310                               -1, 0);
311   }
312
313   if(curWinVer) free(curWinVer);
314   if(curDOSVer) free(curDOSVer);
315   if(curWineLook) free(curWineLook);
316 }
317
318 void
319 initAppDlgComboboxes (HWND hDlg)
320 {
321   int i;
322   const VERSION_DESC *pVer = NULL;
323
324   if ((pVer = getWinVersions ()))
325   {
326     for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
327     {
328       SendDlgItemMessage (hDlg, IDC_WINVER, CB_ADDSTRING,
329                           0, (LPARAM) pVer->szDescription);
330     }
331   }
332   if ((pVer = getDOSVersions ()))
333   {
334     for (i = 0; *pVer->szVersion || *pVer->szDescription ; i++, pVer++)
335     {
336       SendDlgItemMessage (hDlg, IDC_DOSVER, CB_ADDSTRING,
337                           0, (LPARAM) pVer->szDescription);
338     }
339   }
340   if ((pVer = getWinelook ()))
341   {
342     for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
343     {
344       SendDlgItemMessage (hDlg, IDC_WINELOOK, CB_ADDSTRING,
345                           0, (LPARAM) pVer->szDescription);
346     }
347   }
348 }
349
350
351 static VOID OnInitAppDlg(HWND hDlg)
352 {
353   HWND hwndTV;
354   LPAPPL lpAppl;
355   HKEY applKey;
356   int i;
357   DWORD size;
358   char appl [255];
359   char lpcVersionKey [255];
360   char lpcWinelookKey [255];
361   FILETIME ft;
362
363   hwndTV = GetDlgItem(hDlg,IDC_APP_TREEVIEW);
364   lpAppl = CreateAppl(TRUE, "Global Settings", "Version", "Tweak.Layout");
365   LoadAppSettings(lpAppl, hDlg, hwndTV);
366         
367   /*And now the application specific stuff:*/
368   if (RegOpenKey(configKey, "AppDefaults", &applKey) == ERROR_SUCCESS)
369   {
370     i = 0;
371     size = 255;
372     while (RegEnumKeyEx(applKey, i, appl, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
373     {
374       sprintf(lpcVersionKey, "AppDefaults\\%s\\Version", appl);
375       sprintf(lpcWinelookKey, "AppDefaults\\%s\\Tweak.Layout", appl);
376       lpAppl = CreateAppl(FALSE, appl, lpcVersionKey, lpcWinelookKey);
377       LoadAppSettings(lpAppl, hDlg, hwndTV);
378       i++; size = 255;
379     }
380     RegCloseKey(applKey);
381   }
382   SetEnabledAppControls(hDlg);
383 }
384
385 static VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV)
386 {
387   TVITEM ti;
388   LPITEMTAG lpit;
389
390   ti.mask = TVIF_PARAM;
391   ti.hItem = TreeView_GetSelection(hTV);
392   if (TreeView_GetItem (hTV, &ti))
393   {
394     lpit = (LPITEMTAG) ti.lParam;
395     if (lpit->lpAppl)
396     {
397       WINE_TRACE("lpit->lpAppl is non-null\n");
398       /* update comboboxes to reflect settings for this app */
399       UpdateComboboxes(hDlg, lpit->lpAppl);
400     } else
401     {
402       WINE_TRACE("lpit->lpAppl is null\n");
403     }
404   }
405 }
406
407 static VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt)
408 {
409   FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam));
410 }
411
412 static VOID OnAddApplicationClick(HWND hDlg)
413 {
414   char szFileTitle [255];
415   char szFile [255];
416   char lpcVersionKey [255];
417   char lpcWinelookKey [255];
418
419   TVINSERTSTRUCT tis;
420   LPITEMTAG lpit;
421   OPENFILENAME ofn = { sizeof(OPENFILENAME),
422                        0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL, 0, 0, NULL,
423                        0, NULL, 0, NULL, NULL,
424                        OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
425
426   ofn.lpstrFileTitle = szFileTitle;
427   ofn.lpstrFileTitle[0] = '\0';
428   ofn.nMaxFileTitle = sizeof(szFileTitle);
429   ofn.lpstrFile = szFile;
430   ofn.lpstrFile[0] = '\0';
431   ofn.nMaxFile = sizeof(szFile);
432
433   if (GetOpenFileName(&ofn))
434   {
435     tis.hParent = NULL;
436     tis.hInsertAfter = TVI_LAST;
437     tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
438     tis.u.item.pszText = szFileTitle;
439     lpit = CreateItemTag();
440     sprintf(lpcVersionKey, "AppDefaults\\%s\\Version", szFileTitle);
441     sprintf(lpcWinelookKey, "AppDefaults\\%s\\Tweak.Layout", szFileTitle);
442     lpit->lpAppl = CreateAppl(FALSE, szFileTitle, lpcVersionKey, lpcWinelookKey);
443     tis.u.item.lParam = (LPARAM)lpit;
444     TreeView_InsertItem(GetDlgItem(hDlg, IDC_APP_TREEVIEW), &tis);
445
446     /* add the empty entries for the Version and Winelook sections for this app */
447     setConfigValue(lpcVersionKey,NULL,NULL);
448     setConfigValue(lpcWinelookKey,NULL,NULL);
449   }
450 }
451
452 static VOID OnRemoveApplicationClick(HWND hDlg)
453 {
454   HWND hTV;
455   TVITEM ti;
456   LPITEMTAG lpit;
457
458   hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
459   ti.mask = TVIF_PARAM;
460   ti.hItem = TreeView_GetSelection(hTV);
461   if (TreeView_GetItem (hTV, &ti))
462   {
463     lpit = (LPITEMTAG) ti.lParam;
464     if (lpit->lpAppl)
465     {
466       /* add transactions to remove all entries for this application */
467       addTransaction(lpit->lpAppl->lpcVersionSection, NULL, ACTION_REMOVE, NULL);
468       addTransaction(lpit->lpAppl->lpcWinelookSection, NULL, ACTION_REMOVE, NULL);
469       TreeView_DeleteItem(hTV,ti.hItem);
470     }
471   }
472 }
473
474 static void UpdateWinverSelection(HWND hDlg, int selection)
475 {
476   TVITEM ti;
477   LPITEMTAG lpit;
478   VERSION_DESC *pVer = NULL;
479   HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
480
481   ti.mask = TVIF_PARAM;
482   ti.hItem = TreeView_GetSelection(hTV);
483   if (TreeView_GetItem (hTV, &ti))
484   {
485     lpit = (LPITEMTAG) ti.lParam;
486
487     if(lpit->lpAppl)
488     {
489       pVer = getWinVersions();
490
491       /* if no item is selected OR if our version string is null */
492       /* remove this applications setting */
493       if((selection == CB_ERR) || !(*pVer[selection].szVersion))
494       {
495         WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcWinelookSection);
496         addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_REMOVE, NULL); /* change registry entry */
497       } else
498       {
499         WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "Windows", pVer[selection].szVersion);
500         addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
501       }
502
503       TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
504       OnInitAppDlg(hDlg);
505     }
506   }
507 }
508
509 static void UpdateDosverSelection(HWND hDlg, int selection)
510 {
511   TVITEM ti;
512   LPITEMTAG lpit;
513   VERSION_DESC *pVer = NULL;
514   HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
515
516   ti.mask = TVIF_PARAM;
517   ti.hItem = TreeView_GetSelection(hTV);
518   if (TreeView_GetItem (hTV, &ti))
519   {
520     lpit = (LPITEMTAG) ti.lParam;
521
522     if(lpit->lpAppl)
523     {
524       pVer = getDOSVersions();
525
526       /* if no item is selected OR if our version string is null */
527       /* remove this applications setting */
528       if((selection == CB_ERR) || !(*pVer[selection].szVersion))
529       {
530         WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcWinelookSection);
531         addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_REMOVE, NULL); /* change registry entry */
532       } else
533       {
534         WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "DOS", pVer[selection].szVersion);
535         addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
536       }
537
538       TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
539       OnInitAppDlg(hDlg);
540     }
541   }
542 }
543
544 static void UpdateWinelookSelection(HWND hDlg, int selection)
545 {
546   TVITEM ti;
547   LPITEMTAG lpit;
548   VERSION_DESC *pVer = NULL;
549   HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
550
551   ti.mask = TVIF_PARAM;
552   ti.hItem = TreeView_GetSelection(hTV);
553   if (TreeView_GetItem (hTV, &ti))
554   {
555     lpit = (LPITEMTAG) ti.lParam;
556
557     if(lpit->lpAppl)
558     {
559       pVer = getWinelook();
560
561       /* if no item is selected OR if our version string is null */
562       /* remove this applications setting */
563       if((selection == CB_ERR) || !(*pVer[selection].szVersion))
564       {
565         WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcWinelookSection);
566         addTransaction(lpit->lpAppl->lpcWinelookSection, "WineLook", ACTION_REMOVE, NULL); /* change registry entry */
567       } else
568       {
569         WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcWinelookSection, "WineLook", pVer[selection].szVersion);
570         addTransaction(lpit->lpAppl->lpcWinelookSection, "WineLook", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
571       }
572
573       TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
574       OnInitAppDlg(hDlg);
575     }
576   }
577 }
578
579
580
581 INT_PTR CALLBACK
582 AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
583 {
584   int selection;
585   switch (uMsg)
586   {
587   case WM_INITDIALOG:
588     OnInitAppDlg(hDlg);
589     initAppDlgComboboxes(hDlg);
590     break;  
591   case WM_NOTIFY:
592     switch (((LPNMHDR)lParam)->code) {
593     case TVN_SELCHANGED: {
594       switch(LOWORD(wParam)) {
595       case IDC_APP_TREEVIEW:
596         OnTreeViewChangeItem(hDlg, GetDlgItem(hDlg,IDC_APP_TREEVIEW));
597         break;
598       }
599     }
600       break;
601     case TVN_DELETEITEM:
602       OnTreeViewDeleteItem ((LPNMTREEVIEW)lParam);
603       break;
604     }
605     break;
606   case WM_COMMAND:
607     switch(HIWORD(wParam)) {
608     case CBN_SELCHANGE:
609       switch(LOWORD(wParam)) {
610       case IDC_WINVER:
611         selection = SendDlgItemMessage( hDlg, IDC_WINVER, CB_GETCURSEL, 0, 0);
612         UpdateWinverSelection(hDlg, selection);
613         break;
614       case IDC_DOSVER:
615         selection = SendDlgItemMessage( hDlg, IDC_DOSVER, CB_GETCURSEL, 0, 0);
616         UpdateDosverSelection(hDlg, selection);
617         break;
618       case IDC_WINELOOK:
619         selection = SendDlgItemMessage( hDlg, IDC_WINELOOK, CB_GETCURSEL, 0, 0);
620         UpdateWinelookSelection(hDlg, selection);
621         break;
622       }
623     case BN_CLICKED:
624       switch(LOWORD(wParam)) {
625       case IDC_APP_ADDAPP:
626         OnAddApplicationClick(hDlg);
627         break;
628       case IDC_APP_REMOVEAPP:
629         OnRemoveApplicationClick(hDlg);
630         break;
631       }
632       break;
633     }
634     break;
635   }
636
637   return 0;
638 }