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