2 * WineCfg configuration management
4 * Copyright 2002 Jaco Greeff
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2003 Mike Hearn
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.
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.
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
22 * TODO: (in rough order of priority)
23 * - A mind bogglingly vast amount of stuff
25 * - Complete X11DRV page, so all controls are hooked up
26 * - Implement autodetect for drive configuration
27 * - Figure out whether we need the virtual vs real drive selection stuff at the top of the property page
28 * - Implement explicit mode vs instant-apply mode
29 * - AppDefaults handling
31 * - Make a list of prefs that have been dropped from the UI/should be eliminated
33 * - Settings migration code (from old configs)
42 #include <wine/debug.h>
44 WINE_DEFAULT_DEBUG_CHANNEL(winecfg
);
48 HKEY configKey
= NULL
;
51 int initialize(void) {
52 DWORD res
= RegCreateKey(HKEY_LOCAL_MACHINE
, WINE_KEY_ROOT
, &configKey
);
53 if (res
!= ERROR_SUCCESS
) {
54 WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res
);
61 /*****************************************************************************
62 * getConfigValue: Retrieves a configuration value from the registry
64 * char *subKey : the name of the config section
65 * char *valueName : the name of the config value
66 * char *defaultResult : if the key isn't found, return this value instead
68 * Returns a buffer holding the value if successful, NULL if not. Caller is responsible for freeing the result.
71 char *getConfigValue (char *subkey
, char *valueName
, char *defaultResult
)
78 WINE_TRACE("subkey=%s, valueName=%s, defaultResult=%s\n", subkey
, valueName
, defaultResult
);
80 res
= RegOpenKeyEx( configKey
, subkey
, 0, KEY_ALL_ACCESS
, &hSubKey
);
81 if(res
!= ERROR_SUCCESS
) {
82 if( res
==ERROR_FILE_NOT_FOUND
)
84 WINE_TRACE("Section key not present - using default\n");
85 return strdup(defaultResult
);
89 WINE_ERR("RegOpenKey failed on wine config key (res=%ld)\n", res
);
94 res
= RegQueryValueExA( hSubKey
, valueName
, NULL
, NULL
, NULL
, &dataLength
);
95 if( res
== ERROR_FILE_NOT_FOUND
) {
96 WINE_TRACE("Value not present - using default\n");
97 buffer
= strdup(defaultResult
);
99 } else if( res
!=ERROR_SUCCESS
) {
100 WINE_ERR("Couldn't query value's length (res=%ld)\n", res
);
104 buffer
= malloc(dataLength
);
107 WINE_ERR("Couldn't allocate %lu bytes for the value\n", dataLength
);
111 RegQueryValueEx(hSubKey
, valueName
, NULL
, NULL
, (LPBYTE
)buffer
, &dataLength
);
115 RegCloseKey( hSubKey
);
121 /*****************************************************************************
122 * setConfigValue : Sets a configuration key in the registry. Section will be created if it doesn't already exist
124 * HKEY hCurrent : the registry key that the configuration is rooted at
125 * char *subKey : the name of the config section
126 * char *valueName : the name of the config value
127 * char *value : the value to set the configuration key to
129 * Returns 0 on success, non-zero otherwise
132 int setConfigValue (char *subkey
, char *valueName
, const char *value
) {
136 WINE_TRACE("subkey=%s, valueName=%s, value=%s\n", subkey
, valueName
, value
);
138 assert( subkey
!= NULL
);
139 assert( valueName
!= NULL
);
140 assert( value
!= NULL
);
142 res
= RegCreateKey(configKey
, subkey
, &key
);
143 if (res
!= ERROR_SUCCESS
) goto end
;
145 res
= RegSetValueEx(key
, valueName
, 0, REG_SZ
, value
, strlen(value
) + 1);
146 if (res
!= ERROR_SUCCESS
) goto end
;
150 if (key
) RegCloseKey(key
);
151 if (res
!= 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", valueName
, subkey
, value
, res
);
155 /* returns 0 on success, an HRESULT from the registry funtions otherwise */
156 HRESULT
doesConfigValueExist(char *subkey
, char *valueName
) {
160 WINE_TRACE("subkey=%s, valueName=%s - ", subkey
, valueName
);
162 hr
= RegOpenKeyEx(configKey
, subkey
, 0, KEY_READ
, &key
);
164 WINE_TRACE("no: subkey does not exist\n");
168 hr
= RegQueryValueEx(key
, valueName
, NULL
, NULL
, NULL
, NULL
);
170 WINE_TRACE("no: key does not exist\n");
179 /* removes the requested value from the registry, however, does not remove the section if empty. Returns S_OK (0) on success. */
180 HRESULT
removeConfigValue(char *subkey
, char *valueName
) {
183 WINE_TRACE("subkey=%s, valueName=%s\n", subkey
, valueName
);
185 hr
= RegOpenKeyEx(configKey
, subkey
, 0, KEY_READ
, &key
);
186 if (hr
!= S_OK
) return hr
;
188 hr
= RegDeleteValue(key
, valueName
);
189 if (hr
!= ERROR_SUCCESS
) return hr
;
195 /* ========================================================================= */
196 /* Transaction management code */
198 struct transaction
*tqhead
, *tqtail
;
199 int instantApply
= 1;
201 void destroyTransaction(struct transaction
*trans
) {
202 assert( trans
!= NULL
);
204 WINE_TRACE("destroying %p\n", trans
);
206 free(trans
->section
);
208 if (trans
->newValue
) free(trans
->newValue
);
210 if (trans
->next
) trans
->next
->prev
= trans
->prev
;
211 if (trans
->prev
) trans
->prev
->next
= trans
->next
;
212 if (trans
== tqhead
) tqhead
= NULL
;
213 if (trans
== tqtail
) tqtail
= NULL
;
218 void addTransaction(char *section
, char *key
, enum transaction_action action
, char *newValue
) {
219 struct transaction
*trans
= malloc(sizeof(struct transaction
));
221 assert( section
!= NULL
);
222 assert( key
!= NULL
);
223 if (action
== ACTION_SET
) assert( newValue
!= NULL
);
225 trans
->section
= strdup(section
);
226 trans
->key
= strdup(key
);
227 trans
->newValue
= strdup(newValue
);
228 trans
->action
= action
;
232 if (tqtail
== NULL
) {
236 tqhead
->next
= trans
;
237 trans
->prev
= tqhead
;
242 processTransaction(trans
);
243 destroyTransaction(trans
);
247 void processTransaction(struct transaction
*trans
) {
248 if (trans
->action
== ACTION_SET
) {
249 WINE_TRACE("Setting %s\\%s to '%s'\n", trans
->section
, trans
->key
, trans
->newValue
);
250 setConfigValue(trans
->section
, trans
->key
, trans
->newValue
);
251 } else if (trans
->action
== ACTION_REMOVE
) {
252 WINE_TRACE("Removing %s\\%s", trans
->section
, trans
->key
);
253 removeConfigValue(trans
->section
, trans
->key
);
255 /* TODO: implement notifications here */
258 void processTransQueue(void)
261 while (tqtail
!= NULL
) {
262 struct transaction
*next
= tqtail
->next
;
263 processTransaction(tqtail
);
264 destroyTransaction(tqtail
);
270 /* ================================== utility functions ============================ */
272 /* returns a string with the window text of the dialog item. user is responsible for freeing the result */
273 char *getDialogItemText(HWND hDlg
, WORD controlID
) {
274 HWND item
= GetDlgItem(hDlg
, controlID
);
275 int len
= GetWindowTextLength(item
) + 1;
276 char *result
= malloc(len
);
277 if (GetWindowText(item
, result
, len
) == 0) return NULL
;