windows-cellservdb-location-20080202
[openafs.git] / src / WINNT / afsreg / afssw.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afs/param.h>
11 #include <afs/stds.h>
12
13 #include <windows.h>
14 #include <shlobj.h>
15 #include <stdlib.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include <errno.h>
19
20 #include <afs/errmap_nt.h>
21
22 #include "afsreg.h"
23 #include "afssw.h"
24
25 static int
26 StringDataRead(const char *keyName, const char *valueName, char **bufPP);
27
28 static int
29 StringDataWrite(const char *keyName, const char *valueName, const char *data);
30
31 static int
32 DwordDataRead(const char *keyName, const char *valueName, DWORD *data);
33
34
35
36 /* Functions for accessing AFS software configuration information. */
37
38 /*
39  * afssw_GetServerInstallDir() -- Get directory in which AFS server software is
40  *     installed.  Sets *bufPP to point to allocated buffer containing string.
41  *
42  * RETURN CODES: 0 success, -1 failed (errno set)
43  */
44 int
45 afssw_GetServerInstallDir(char **bufPP)  /* [out] data buffer */
46 {
47     return StringDataRead(AFSREG_SVR_SW_VERSION_KEY,
48                           AFSREG_SVR_SW_VERSION_DIR_VALUE,
49                           bufPP);
50 }
51
52
53 /*
54  * afssw_GetClientInstallDir() -- Get directory in which AFS client software is
55  *     installed.  Sets *bufPP to point to allocated buffer containing string.
56  *
57  * RETURN CODES: 0 success, -1 failed (errno set)
58  */
59 int
60 afssw_GetClientInstallDir(char **bufPP)   /* [out] data buffer */
61 {
62     int retval = StringDataRead(AFSREG_CLT_SW_VERSION_KEY,
63                           AFSREG_CLT_SW_VERSION_DIR_VALUE,
64                           bufPP);
65     if (retval)
66         retval = StringDataRead(AFSREG_CLT_TOOLS_SW_VERSION_KEY,
67                           AFSREG_CLT_SW_VERSION_DIR_VALUE,
68                           bufPP);
69     return retval;
70 }
71
72 /*
73  * afssw_GetClientCellServDBDir() -- Get directory in which AFS client CellServDB
74  * file is installed.  Sets *bufPP to point to allocated buffer containing string.
75  *
76  * RETURN CODES: 0 success, -1 failed (errno set)
77  */
78 int
79 afssw_GetClientCellServDBDir(char **bufPP)   /* [out] data buffer */
80 {
81     char wdir[512];
82     int tlen;
83     char *path = NULL;
84     DWORD cbPath;
85
86     cbPath = GetEnvironmentVariable("AFSCONF", NULL, 0);
87     if (cbPath) {
88         cbPath += 2;
89         path = malloc(cbPath);
90     }
91     if (path) {
92         GetEnvironmentVariable("AFSCONF", path, cbPath);
93         tlen = (int)strlen(path);
94         if (path[tlen-1] != '\\') {
95             strncat(path, "\\", cbPath);
96             path[cbPath-1] = '\0';
97         }
98         *bufPP = path;
99         return 0;
100     }
101
102     if (!StringDataRead(AFSREG_CLT_OPENAFS_KEY,
103                           AFSREG_CLT_OPENAFS_CELLSERVDB_DIR_VALUE,
104                          &path)) {
105         tlen = (int)strlen(path);
106         if (path[tlen-1] != '\\') {
107             strncat(path, "\\", cbPath);
108             path[cbPath-1] = '\0';
109         }
110         *bufPP = path;
111         return 0;
112     }
113
114     /*
115      * Try to find the All Users\Application Data\OpenAFS\Client directory.
116      * If it exists and it contains a CellServDB file, return that. 
117      * Otherwise, return the Install Directory for backward compatibility.
118      */
119     if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 
120                                     SHGFP_TYPE_CURRENT, wdir)))
121     {   HANDLE fh;
122
123         tlen = (int)strlen(wdir);
124         if (wdir[tlen-1] != '\\') {
125             strncat(wdir, "\\", sizeof(wdir));
126             wdir[sizeof(wdir)-1] = '\0';
127             tlen++;
128         }
129         strncat(wdir, "OpenAFS\\Client\\CellServDB", sizeof(wdir)); 
130         wdir[sizeof(wdir)-1] = '\0';
131
132         fh = CreateFile(wdir, GENERIC_READ, FILE_SHARE_READ, NULL, 
133                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
134         if (fh != INVALID_HANDLE_VALUE) {
135             CloseHandle(fh);
136             tlen += (int)strlen("OpenAFS\\Client\\");
137             wdir[tlen] = '\0';
138             *bufPP = strdup(wdir);
139             return 0;
140         }
141     }
142
143     return afssw_GetClientInstallDir(bufPP);
144 }
145
146
147 /*
148  * afssw_GetClientCellName() -- Get name of cell in which AFS client is
149  *     configured.  Sets *bufPP to point to allocated buffer containing string.
150  *
151  * RETURN CODES: 0 success, -1 failed (errno set)
152  */
153 int
154 afssw_GetClientCellName(char **bufPP)  /* [out] data buffer */
155 {
156     return StringDataRead(AFSREG_CLT_SVC_PARAM_KEY,
157                           AFSREG_CLT_SVC_PARAM_CELL_VALUE,
158                           bufPP);
159 }
160
161
162 /*
163  * afssw_SetClientCellName() -- Set name of cell in which AFS client is
164  *     configured.
165  *
166  * RETURN CODES: 0 success, -1 failed (errno set)
167  */
168 int
169 afssw_SetClientCellName(const char *cellName)
170 {
171     return StringDataWrite(AFSREG_CLT_SVC_PARAM_KEY,
172                            AFSREG_CLT_SVC_PARAM_CELL_VALUE,
173                            cellName);
174 }
175
176
177 /*
178  * afssw_GetServerVersion() -- Get version number of installed server.
179  *
180  * RETURN CODES: 0 success, -1 failed (errno set)
181  */
182 int
183 afssw_GetServerVersion(unsigned *major,  /* major version number */
184                        unsigned *minor,  /* minor version number */
185                        unsigned *patch)  /* patch level */
186 {
187     DWORD dwMajor, dwMinor, dwPatch;
188
189     if (DwordDataRead(AFSREG_SVR_SW_VERSION_KEY,
190                       AFSREG_SVR_SW_VERSION_MAJOR_VALUE,
191                       &dwMajor) ||
192
193         DwordDataRead(AFSREG_SVR_SW_VERSION_KEY,
194                       AFSREG_SVR_SW_VERSION_MINOR_VALUE,
195                       &dwMinor) ||
196
197         DwordDataRead(AFSREG_SVR_SW_VERSION_KEY,
198                       AFSREG_SVR_SW_VERSION_PATCH_VALUE,
199                       &dwPatch)) {
200         /* a read failed */
201         return -1;
202     } else {
203         /* return values */
204         *major = dwMajor;
205         *minor = dwMinor;
206         *patch = dwPatch;
207         return 0;
208     }
209 }
210
211
212 /*
213  * afssw_GetClientVersion() -- Get version number of installed client.
214  *
215  * RETURN CODES: 0 success, -1 failed (errno set)
216  */
217 int
218 afssw_GetClientVersion(unsigned *major,  /* major version number */
219                        unsigned *minor,  /* minor version number */
220                        unsigned *patch)  /* patch level */
221 {
222     DWORD dwMajor, dwMinor, dwPatch;
223
224     if (DwordDataRead(AFSREG_CLT_SW_VERSION_KEY,
225                       AFSREG_CLT_SW_VERSION_MAJOR_VALUE,
226                       &dwMajor) ||
227
228         DwordDataRead(AFSREG_CLT_SW_VERSION_KEY,
229                       AFSREG_CLT_SW_VERSION_MINOR_VALUE,
230                       &dwMinor) ||
231
232         DwordDataRead(AFSREG_CLT_SW_VERSION_KEY,
233                       AFSREG_CLT_SW_VERSION_PATCH_VALUE,
234                       &dwPatch)) {
235         /* a read failed */
236         return -1;
237     } else {
238         /* return values */
239         *major = dwMajor;
240         *minor = dwMinor;
241         *patch = dwPatch;
242         return 0;
243     }
244 }
245
246
247
248
249 /* ----------------------- local functions ------------------------- */
250
251 /*
252  * StringDataRead() -- read registry data of type REG_SZ and return in
253  *     allocated buffer.
254  *
255  * RETURN CODES: 0 success, -1 failed (errno set)
256  */
257 static int
258 StringDataRead(const char *keyName, const char *valueName, char **bufPP)
259 {
260     long status;
261     HKEY key;
262
263     if (bufPP == NULL) {
264         errno = EINVAL;
265         return -1;
266     }
267
268     status = RegOpenKeyAlt(AFSREG_NULL_KEY, keyName, KEY_READ, 0, &key, NULL);
269
270     if (status == ERROR_SUCCESS) {
271         DWORD dataType;
272         char *dataBuf = NULL;
273
274         status = RegQueryValueAlt(key, valueName, &dataType, &dataBuf, NULL);
275
276         if (status == ERROR_SUCCESS) {
277             if (dataType == REG_SZ) {
278                 *bufPP = dataBuf;
279             } else {
280                 /* invalid data type */
281                 free(dataBuf);
282                 status = ERROR_INVALID_DATA;
283             }
284         }
285         (void)RegCloseKey(key);
286     }
287
288     if (status) {
289         errno = nterr_nt2unix(status, EIO);
290         return -1;
291     }
292     return 0;
293 }
294
295
296 /*
297  * StringDataWrite() -- write registry data of type REG_SZ.
298  * 
299  * RETURN CODES: 0 success, -1 failed (errno set)
300  */
301 static int
302 StringDataWrite(const char *keyName, const char *valueName, const char *data)
303 {
304     long status;
305     HKEY key;
306
307     if (data == NULL) {
308         errno = EINVAL;
309         return -1;
310     }
311
312     status = RegOpenKeyAlt(AFSREG_NULL_KEY,
313                            keyName, KEY_WRITE, 1 /* create */, &key, NULL);
314
315     if (status == ERROR_SUCCESS) {
316         status = RegSetValueEx(key,
317                                valueName,
318                                0, REG_SZ, data, (DWORD)strlen(data) + 1);
319
320         (void)RegCloseKey(key);
321     }
322
323     if (status) {
324         errno = nterr_nt2unix(status, EIO);
325         return -1;
326     }
327     return 0;
328 }
329
330
331 /*
332  * DwordDataRead() -- read registry data of type REG_DWORD.
333  *
334  * RETURN CODES: 0 success, -1 failed (errno set)
335  */
336 static int
337 DwordDataRead(const char *keyName, const char *valueName, DWORD *data)
338 {
339     long status;
340     HKEY key;
341
342     status = RegOpenKeyAlt(AFSREG_NULL_KEY, keyName, KEY_READ, 0, &key, NULL);
343
344     if (status == ERROR_SUCCESS) {
345         DWORD dataType;
346         DWORD dataBuf;
347         DWORD dataSize = sizeof(DWORD);
348
349         status = RegQueryValueEx(key, valueName,
350                                  NULL, &dataType, (void *)&dataBuf, &dataSize);
351
352         if (status == ERROR_SUCCESS) {
353             if (dataType == REG_DWORD) {
354                 *data = dataBuf;
355             } else {
356                 /* invalid data type */
357                 status = ERROR_INVALID_DATA;
358             }
359         }
360         (void)RegCloseKey(key);
361     }
362
363     if (status) {
364         errno = nterr_nt2unix(status, EIO);
365         return -1;
366     }
367     return 0;
368 }