Authors: Mark Westcott <mark@houseoffish.org>, Mike Hearn <mike@theoretic.com>
[wine] / programs / winecfg / winecfg.c
1 /*
2  * WineCfg configuration management
3  *
4  * Copyright 2002 Jaco Greeff
5  * Copyright 2003 Dimitrie O. Paun
6  * Copyright 2003 Mike Hearn
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <stdio.h>
25 #include <limits.h>
26 #include <windows.h>
27 #include <winreg.h>
28 #include <wine/debug.h>
29
30 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
31
32 #include "winecfg.h"
33
34 HKEY configKey = NULL;
35
36 /*****************************************************************************
37  */
38 WINECFG_DESC* allocConfig(void)
39 {
40     WINECFG_DESC* pWineCfg =  malloc (sizeof (WINECFG_DESC));
41
42     if (!pWineCfg) goto fail;
43     ZeroMemory(pWineCfg, sizeof(*pWineCfg));
44
45     pWineCfg->pDlls = DPA_Create(100);
46     if (!pWineCfg->pDlls) goto fail;
47     pWineCfg->pApps = DPA_Create(100);
48     if (!pWineCfg->pApps) goto fail;
49     
50     return pWineCfg;
51
52 fail:
53     /* FIXME: do something nice */
54     printf("Out of memory");
55     exit(1);
56 }
57
58
59 /*****************************************************************************
60  */
61 int freeConfig (WINECFG_DESC* pCfg)
62 {
63     int i;
64
65     for (i = 0; i < pCfg->pDlls->nItemCount; i++)
66         free (DPA_GetPtr(pCfg->pDlls, i));
67     DPA_Destroy(pCfg->pDlls);
68     
69     for (i = 0; i < pCfg->pApps->nItemCount; i++)
70         free (DPA_GetPtr(pCfg->pApps, i));
71     DPA_Destroy(pCfg->pApps);
72     
73     free (pCfg);
74
75     return 0;
76 }
77
78 /*****************************************************************************
79  * getConfigValue: Retrieves a configuration value from the registry
80  *
81  * HKEY  hCurrent : the registry key that the configuration is rooted at
82  * char *subKey : the name of the config section
83  * char *valueName : the name of the config value
84  * char *retVal : pointer to the start of a buffer that has room for >= length chars
85  * int   length : length of the buffer pointed to by retVal
86  * char *defaultResult : if the key isn't found, return this value instead
87  *
88  * Returns 0 upon success, non-zero otherwise
89  *
90  */
91 int getConfigValue (HKEY hCurrent, char *subkey, char *valueName, char *retVal, int length, char *defaultResult)
92 {
93     CHAR *buffer;
94     DWORD dataLength;
95     HKEY hSubKey = NULL;
96     DWORD res = 1; /* assume failure */
97
98     WINE_TRACE("subkey=%s, valueName=%s, defaultResult=%s\n", subkey, valueName, defaultResult);
99     
100     if( (res=RegOpenKeyEx( hCurrent, subkey, 0, KEY_ALL_ACCESS, &hSubKey ))
101             !=ERROR_SUCCESS )
102     {
103         if( res==ERROR_FILE_NOT_FOUND )
104         {
105             WINE_TRACE("Section key not present - using default\n");
106             strncpy(retVal, defaultResult, length);
107         }
108         else
109         {
110             WINE_ERR("RegOpenKey failed on wine config key (res=%ld)\n", res);
111         }
112         goto end;
113     }
114     
115     res = RegQueryValueExA( hSubKey, valueName, NULL, NULL, NULL, &dataLength);
116     if( res == ERROR_FILE_NOT_FOUND )
117     {
118         WINE_TRACE("Value not present - using default\n");
119         strncpy(retVal, defaultResult, length);
120         goto end;
121     }
122
123     if( res!=ERROR_SUCCESS )
124     {
125         WINE_ERR("Couldn't query value's length (res=%ld)\n", res );
126         goto end;
127     }
128
129     buffer=malloc( dataLength );
130     if( buffer==NULL )
131     {
132         WINE_ERR("Couldn't allocate %lu bytes for the value\n", dataLength );
133         goto end;
134     }
135     
136     RegQueryValueEx(hSubKey, valueName, NULL, NULL, (LPBYTE)buffer, &dataLength);
137     strncpy(retVal, buffer, length);
138     free(buffer);
139     res = 0;
140     
141 end:
142     if( hSubKey!=NULL )
143         RegCloseKey( hSubKey );
144
145     return res;
146     
147 }
148
149 /*****************************************************************************
150  * setConfigValue : Sets a configuration key in the registry
151  *
152  * HKEY  hCurrent : the registry key that the configuration is rooted at
153  * char *subKey : the name of the config section
154  * char *valueName : the name of the config value
155  * char *value : the value to set the configuration key to
156  *
157  * Returns 0 on success, non-zero otherwise
158  *
159  */
160 int setConfigValue (HKEY hCurrent, char *subkey, char *valueName, const char *value) {
161     DWORD res = 1;
162     HKEY key = NULL;
163
164     WINE_TRACE("subkey=%s, valueName=%s, value=%s\n", subkey, valueName, value);
165     
166     res = RegCreateKey(hCurrent, subkey, &key);
167     if (res != ERROR_SUCCESS) goto end;
168
169     res = RegSetValueEx(key, valueName, 0, REG_SZ, value, strlen(value) + 1);
170     if (res != ERROR_SUCCESS) goto end;
171
172     res = 0;
173 end:
174     if (key) RegCloseKey(key);
175     if (res != 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", valueName, subkey, value, res);
176     return res;
177 }
178
179
180 /*****************************************************************************
181  * Name       : loadConfig
182  * Description: Loads and populates a configuration structure
183  * Parameters : pCfg
184  * Returns    : 0 on success, -1 otherwise
185  *
186  * FIXME: We are supposed to load these values from the registry.
187  *        This is not active yet, so just setup some (hopefully) 
188  *        sane defaults
189  */
190 int loadConfig (WINECFG_DESC* pCfg)
191 {
192     const DLL_DESC *pDllDefaults;
193     char buffer[MAX_PATH];
194     DWORD res;
195
196     WINE_TRACE("\n");
197
198     res = RegCreateKey(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, &configKey);
199     if (res != ERROR_SUCCESS)
200     {
201         WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res);
202         return -1;
203     }
204
205     /* Windows and DOS versions */
206     getConfigValue(configKey, "Version", "Windows", pCfg->szWinVer, MAX_VERSION_LENGTH, "win95");
207     getConfigValue(configKey, "Version", "DOS", pCfg->szDOSVer, MAX_VERSION_LENGTH, "6.22");
208     getConfigValue(configKey, "Tweak.Layout", "WineLook", pCfg->szWinLook, MAX_VERSION_LENGTH, "win95");
209
210     /* System Paths */
211     getConfigValue(configKey, "Wine", "Windows", pCfg->szWinDir, MAX_PATH, "c:\\Windows");
212     getConfigValue(configKey, "Wine", "System", pCfg->szWinSysDir, MAX_PATH, "c:\\Windows\\System");
213     getConfigValue(configKey, "Wine", "Temp", pCfg->szWinTmpDir, MAX_PATH, "c:\\Windows\\Temp");
214     getConfigValue(configKey, "Wine", "Profile", pCfg->szWinProfDir, MAX_PATH, "c:\\Windows\\Profiles\\Administrator");
215     getConfigValue(configKey, "Wine", "Path", pCfg->szWinPath, MAX_PATH, "c:\\Windows;c:\\Windows\\System");
216
217     /* Graphics driver */
218     getConfigValue(configKey, "Wine", "GraphicsDriver", pCfg->szGraphDriver, MAX_NAME_LENGTH, "x11drv");
219     
220     /*
221      * DLL defaults for all applications is built using
222      * the default DLL structure
223      */
224     for (pDllDefaults = getDLLDefaults (); *pDllDefaults->szName; pDllDefaults++)
225     {
226         DLL_DESC *pDll = malloc(sizeof(DLL_DESC));
227         memcpy (pDll, pDllDefaults, sizeof(DLL_DESC));
228         DPA_InsertPtr(pCfg->pDlls, INT_MAX, pDll);
229     }
230
231     /*
232      * Application defaults on a per application
233      * level (if not set, this defaults to what 
234      * is already there)
235      */
236     
237     /* FIXME: Finish these off. Do we actually need GUI for all of them? */
238
239     /*
240      * X11Drv defaults
241      */
242     getConfigValue(configKey, "x11drv", "Display", pCfg->sX11Drv.szX11Display, sizeof(pCfg->sX11Drv.szX11Display), ":0.0");
243     
244     getConfigValue(configKey, "x11drv", "AllocSystemColors", buffer, sizeof(buffer), "100");
245     pCfg->sX11Drv.nSysColors = atoi(buffer);
246     
247     getConfigValue(configKey, "x11drv", "PrivateColorMap", buffer, sizeof(buffer), "N");
248     pCfg->sX11Drv.nPrivateMap = IS_OPTION_TRUE(buffer[0]);
249     
250     getConfigValue(configKey, "x11drv", "PerfectGraphics", buffer, sizeof(buffer), "N");
251     pCfg->sX11Drv.nPerfect = IS_OPTION_TRUE(buffer[0]);
252     
253     getConfigValue(configKey, "x11drv", "Desktop", buffer, sizeof(buffer), "640x480");
254     sscanf(buffer, "%dx%d", &pCfg->sX11Drv.nDesktopSizeX, &pCfg->sX11Drv.nDesktopSizeY);
255
256     pCfg->sX11Drv.nTextCP = 0;
257     pCfg->sX11Drv.nXVideoPort = 43;
258     pCfg->sX11Drv.nDepth = 16;
259     pCfg->sX11Drv.nManaged = 1;
260     pCfg->sX11Drv.nDesktopSizeX = 640;
261     pCfg->sX11Drv.nDesktopSizeY = 480;
262     pCfg->sX11Drv.nDGA = 1;
263     pCfg->sX11Drv.nXVidMode = 1;
264     pCfg->sX11Drv.nTakeFocus = 1;
265     pCfg->sX11Drv.nDXGrab = 0;
266     pCfg->sX11Drv.nDoubleBuffered = 0;
267     pCfg->sX11Drv.nSynchronous = 1;
268     
269     RegCloseKey( configKey );
270     return 0;
271 }
272
273 /*****************************************************************************
274  * saveConfig : Stores the configuration structure
275  *
276  * Returns    : 0 on success, -1 otherwise
277  *
278  * FIXME: This is where we are to write the changes to the registry.
279  *        This is not setup yet, so do nothing and say ok.
280  */
281 int saveConfig (const WINECFG_DESC* pCfg)
282 {
283     HKEY key;
284     DWORD res;
285
286     WINE_TRACE("\n");
287     
288     res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, 0, KEY_ALL_ACCESS, &key);
289     if (res != ERROR_SUCCESS) {
290         WINE_ERR("Failed to open Wine config registry branch, res=%ld\n", res);
291         return -1;
292     }
293
294     /* Windows and DOS versions */
295     setConfigValue(key, "Version", "Windows", pCfg->szWinVer);
296     
297     WINE_FIXME("We don't write out the entire configuration yet\n");
298     return 0;
299 }