Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / comcat / regsvr.c
1 /*
2  *      self-registerable dll helper functions
3  *
4  * Copyright (C) 2002 John K. Hohm
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winuser.h"
24 #include "winreg.h"
25 #include "winerror.h"
26
27 #include "regsvr.h"
28
29 static HRESULT recursive_delete_key(HKEY key);
30
31 /***********************************************************************
32  *              regsvr_register
33  */
34 HRESULT regsvr_register(struct regsvr_entry const *entries, size_t count)
35 {
36     HKEY keys[count];
37     struct regsvr_entry const *e;
38     int i;
39     HRESULT res = S_OK;
40
41     /* Create keys and set values. */
42     for (i = 0, e = entries; i < count; ++i, ++e) {
43         /* predefined HKEY_'s are all >= 0x80000000 */
44         HKEY parent_key = e->parent < 0x80000000 ?
45             keys[e->parent] : (HKEY)e->parent;
46         if (e->value == NULL) {
47             res = RegCreateKeyExW(parent_key, e->name, 0, NULL, 0,
48                                   KEY_READ | KEY_WRITE, NULL, &keys[i], NULL);
49         } else {
50             res = RegSetValueExW(parent_key, e->name, 0, REG_SZ,
51                                  (CONST BYTE*)e->value,
52                                  (lstrlenW(e->value) + 1) * sizeof(WCHAR));
53         }
54         if (res != ERROR_SUCCESS) break;
55     }
56
57     /* Close keys. */
58     for (--i, --e; 0 <= i; --i, --e) {
59         if (e->value == NULL) RegCloseKey(keys[i]);
60     }
61
62     return res == ERROR_SUCCESS ? S_OK : HRESULT_FROM_WIN32(res);
63 }
64
65 /***********************************************************************
66  *              regsvr_unregister
67  */
68 HRESULT regsvr_unregister(struct regsvr_entry const *entries, size_t count)
69 {
70     HKEY keys[count];
71     struct regsvr_entry const *e;
72     int i;
73     HRESULT res = S_OK;
74
75     /* Open (and possibly delete) keys. */
76     for (i = 0, e = entries; i < count; ++i, ++e) {
77         /* predefined HKEY_'s are all >= 0x80000000 */
78         HKEY parent_key = e->parent < 0x80000000 ?
79             keys[e->parent] : (HKEY)e->parent;
80         if (e->value == NULL && parent_key) {
81             res = RegOpenKeyExW(parent_key, e->name, 0,
82                                 KEY_READ | KEY_WRITE, &keys[i]);
83             if (res == ERROR_SUCCESS && e->unreg_del)
84                 res = recursive_delete_key(keys[i]);
85             if (res == ERROR_FILE_NOT_FOUND) continue;
86             if (res != ERROR_SUCCESS) break;
87         } else keys[i] = 0;
88     }
89
90     /* Close keys. */
91     for (--i; 0 <= i; --i) {
92         if (keys[i]) RegCloseKey(keys[i]);
93     }
94
95     return res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND ?
96         HRESULT_FROM_WIN32(res) : S_OK;
97 }
98
99 /***********************************************************************
100  *              recursive_delete_key
101  */
102 static LONG recursive_delete_key(HKEY key)
103 {
104     LONG res;
105     DWORD index;
106     WCHAR subkey_name[MAX_PATH];
107     DWORD cName;
108     HKEY subkey;
109
110     for (index = 0; ; ++index) {
111         cName = sizeof subkey_name / sizeof(WCHAR);
112         res = RegEnumKeyExW(key, index, subkey_name, &cName,
113                             NULL, NULL, NULL, NULL);
114         if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
115             res = ERROR_SUCCESS; /* presumably we're done enumerating */
116             break;
117         }
118         res = RegOpenKeyExW(key, subkey_name, 0,
119                             KEY_READ | KEY_WRITE, &subkey);
120         if (res == ERROR_FILE_NOT_FOUND) continue;
121         if (res != ERROR_SUCCESS) break;
122
123         res = recursive_delete_key(subkey);
124         RegCloseKey(subkey);
125         if (res != ERROR_SUCCESS) break;
126     }
127
128     if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
129     return res;
130 }