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
29 #include <wine/debug.h>
31 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
35 HKEY configKey = NULL;
38 int initialize(void) {
39 DWORD res = RegCreateKey(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, &configKey);
40 if (res != ERROR_SUCCESS) {
41 WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res);
48 /*****************************************************************************
49 * getConfigValue: Retrieves a configuration value from the registry
51 * char *subKey : the name of the config section
52 * char *valueName : the name of the config value
53 * char *defaultResult : if the key isn't found, return this value instead
55 * Returns a buffer holding the value if successful, NULL if not. Caller is responsible for freeing the result.
58 char *getConfigValue (char *subkey, char *valueName, char *defaultResult)
65 WINE_TRACE("subkey=%s, valueName=%s, defaultResult=%s\n", subkey, valueName, defaultResult);
67 res = RegOpenKeyEx( configKey, subkey, 0, KEY_ALL_ACCESS, &hSubKey );
68 if(res != ERROR_SUCCESS) {
69 if( res==ERROR_FILE_NOT_FOUND )
71 WINE_TRACE("Section key not present - using default\n");
72 return strdup(defaultResult);
76 WINE_ERR("RegOpenKey failed on wine config key (res=%ld)\n", res);
81 res = RegQueryValueExA( hSubKey, valueName, NULL, NULL, NULL, &dataLength);
82 if( res == ERROR_FILE_NOT_FOUND ) {
83 WINE_TRACE("Value not present - using default\n");
84 buffer = strdup(defaultResult);
86 } else if( res!=ERROR_SUCCESS ) {
87 WINE_ERR("Couldn't query value's length (res=%ld)\n", res );
91 buffer = malloc(dataLength);
94 WINE_ERR("Couldn't allocate %lu bytes for the value\n", dataLength );
98 RegQueryValueEx(hSubKey, valueName, NULL, NULL, (LPBYTE)buffer, &dataLength);
102 RegCloseKey( hSubKey );
108 /*****************************************************************************
109 * setConfigValue : Sets a configuration key in the registry. Section will be created if it doesn't already exist
111 * HKEY hCurrent : the registry key that the configuration is rooted at
112 * char *subKey : the name of the config section
113 * char *valueName : the name of the config value
114 * char *value : the value to set the configuration key to
116 * Returns 0 on success, non-zero otherwise
119 int setConfigValue (char *subkey, char *valueName, const char *value) {
123 WINE_TRACE("subkey=%s, valueName=%s, value=%s\n", subkey, valueName, value);
125 assert( subkey != NULL );
126 assert( valueName != NULL );
127 assert( value != NULL );
129 res = RegCreateKey(configKey, subkey, &key);
130 if (res != ERROR_SUCCESS) goto end;
132 res = RegSetValueEx(key, valueName, 0, REG_SZ, value, strlen(value) + 1);
133 if (res != ERROR_SUCCESS) goto end;
137 if (key) RegCloseKey(key);
138 if (res != 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", valueName, subkey, value, res);
142 /* returns 0 on success, an HRESULT from the registry funtions otherwise */
143 HRESULT doesConfigValueExist(char *subkey, char *valueName) {
147 WINE_TRACE("subkey=%s, valueName=%s - ", subkey, valueName);
149 hr = RegOpenKeyEx(configKey, subkey, 0, KEY_READ, &key);
151 WINE_TRACE("no: subkey does not exist\n");
155 hr = RegQueryValueEx(key, valueName, NULL, NULL, NULL, NULL);
157 WINE_TRACE("no: key does not exist\n");
166 /* removes the requested value from the registry, however, does not remove the section if empty. Returns S_OK (0) on success. */
167 HRESULT removeConfigValue(char *subkey, char *valueName) {
170 WINE_TRACE("subkey=%s, valueName=%s\n", subkey, valueName);
172 hr = RegOpenKeyEx(configKey, subkey, 0, KEY_READ, &key);
173 if (hr != S_OK) return hr;
175 hr = RegDeleteValue(key, valueName);
176 if (hr != ERROR_SUCCESS) return hr;
182 /* ========================================================================= */
183 /* Transaction management code */
185 struct transaction *tqhead, *tqtail;
186 int instantApply = 1;
188 void destroyTransaction(struct transaction *trans) {
189 assert( trans != NULL );
191 WINE_TRACE("destroying %p\n", trans);
193 free(trans->section);
195 if (trans->newValue) free(trans->newValue);
197 if (trans->next) trans->next->prev = trans->prev;
198 if (trans->prev) trans->prev->next = trans->next;
199 if (trans == tqhead) tqhead = NULL;
200 if (trans == tqtail) tqtail = NULL;
205 void addTransaction(char *section, char *key, enum transaction_action action, char *newValue) {
206 struct transaction *trans = malloc(sizeof(struct transaction));
208 assert( section != NULL );
209 assert( key != NULL );
210 if (action == ACTION_SET) assert( newValue != NULL );
212 trans->section = strdup(section);
213 trans->key = strdup(key);
214 trans->newValue = strdup(newValue);
215 trans->action = action;
219 if (tqtail == NULL) {
223 tqhead->next = trans;
224 trans->prev = tqhead;
229 processTransaction(trans);
230 destroyTransaction(trans);
234 void processTransaction(struct transaction *trans) {
235 if (trans->action == ACTION_SET) {
236 WINE_TRACE("Setting %s\\%s to '%s'\n", trans->section, trans->key, trans->newValue);
237 setConfigValue(trans->section, trans->key, trans->newValue);
238 } else if (trans->action == ACTION_REMOVE) {
239 WINE_TRACE("Removing %s\\%s", trans->section, trans->key);
240 removeConfigValue(trans->section, trans->key);
242 /* TODO: implement notifications here */
245 void processTransQueue(void)
248 while (tqtail != NULL) {
249 struct transaction *next = tqtail->next;
250 processTransaction(tqtail);
251 destroyTransaction(tqtail);
257 /* ================================== utility functions ============================ */
259 /* returns a string with the window text of the dialog item. user is responsible for freeing the result */
260 char *getDialogItemText(HWND hDlg, WORD controlID) {
261 HWND item = GetDlgItem(hDlg, controlID);
262 int len = GetWindowTextLength(item) + 1;
263 char *result = malloc(len);
264 if (GetWindowText(item, result, len) == 0) return NULL;