25af0c96ec1f3b07dc03e93533e6232ec5b78264
[openafs.git] / src / WINNT / afsd / cm_volstat.c
1 /* 
2  * Copyright (c) 2007 Secure Endpoints Inc.
3  *
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  * 
10  *     * Redistributions of source code must retain the above copyright 
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Neither the name of the Secure Endpoints Inc. nor the names of its 
13  *       contributors may be used to endorse or promote products derived 
14  *       from this software without specific prior written permission.
15  * 
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 /* This source file provides the declarations 
30  * which specify the AFS Cache Manager Volume Status Event
31  * Notification API
32  */
33
34 #include <afs/param.h>
35 #include <afs/stds.h>
36
37 #include <windows.h>
38 #include <winsock2.h>
39 #include <nb30.h>
40 #include <string.h>
41 #include <malloc.h>
42 #include "afsd.h"
43 #include <WINNT/afsreg.h>
44
45 HMODULE hVolStatus = NULL;
46 dll_VolStatus_Funcs_t dll_funcs;
47 cm_VolStatus_Funcs_t cm_funcs;
48
49 /* This function is used to load any Volume Status Handlers 
50  * and their associated function pointers.  
51  */
52 long 
53 cm_VolStatus_Initialization(void)
54 {
55     long (__fastcall * dll_VolStatus_Initialization)(dll_VolStatus_Funcs_t * dll_funcs, cm_VolStatus_Funcs_t *cm_funcs) = NULL;
56     long code = 0;
57     HKEY parmKey;
58     DWORD dummyLen;
59     char wd[MAX_PATH+1] = "";
60
61     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
62                          0, KEY_QUERY_VALUE, &parmKey);
63     if (code == ERROR_SUCCESS) {
64         dummyLen = sizeof(wd);
65         code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL,
66                                 (BYTE *) &wd, &dummyLen);
67         RegCloseKey (parmKey);
68     }
69
70     if (code == ERROR_SUCCESS && wd[0])
71         hVolStatus = LoadLibrary(wd);
72     if (hVolStatus) {
73         (FARPROC) dll_VolStatus_Initialization = GetProcAddress(hVolStatus, "@VolStatus_Initialization@8");
74         if (dll_VolStatus_Initialization) {
75             cm_funcs.version = CM_VOLSTATUS_FUNCS_VERSION;
76             cm_funcs.cm_VolStatus_Path_To_ID = cm_VolStatus_Path_To_ID;
77             cm_funcs.cm_VolStatus_Path_To_DFSlink = cm_VolStatus_Path_To_DFSlink;
78
79             code = dll_VolStatus_Initialization(&dll_funcs, &cm_funcs);
80         } 
81
82         if (dll_VolStatus_Initialization == NULL || code != 0 || 
83             dll_funcs.version != DLL_VOLSTATUS_FUNCS_VERSION) {
84             FreeLibrary(hVolStatus);
85             hVolStatus = NULL;
86             code = -1;
87         }
88     }
89
90     return code;
91 }
92
93 /* This function is used to unload any Volume Status Handlers
94  * that were loaded during initialization.
95  */
96 long 
97 cm_VolStatus_Finalize(void)
98 {
99     if (hVolStatus == NULL)
100         return 0;
101
102     FreeLibrary(hVolStatus);
103     hVolStatus = NULL;
104     return 0;
105 }
106
107 /* This function notifies the Volume Status Handlers that the
108  * AFS client service has started.  If the network is started
109  * at this point we call cm_VolStatus_Network_Started().
110  */
111 long 
112 cm_VolStatus_Service_Started(void)
113 {
114     long code = 0;
115
116     if (hVolStatus == NULL)
117         return 0;
118    
119     code = dll_funcs.dll_VolStatus_Service_Started();
120     if (code == 0 && smb_IsNetworkStarted())
121         code = dll_funcs.dll_VolStatus_Network_Started(cm_NetbiosName, cm_NetbiosName);
122
123     return code;
124 }
125
126 /* This function notifies the Volume Status Handlers that the
127  * AFS client service is stopping.
128  */
129 long 
130 cm_VolStatus_Service_Stopped(void)
131 {
132     long code = 0;
133
134     if (hVolStatus == NULL)
135         return 0;
136    
137     code = dll_funcs.dll_VolStatus_Service_Stopped();
138
139     return code;
140 }
141
142
143 /* This function notifies the Volume Status Handlers that the
144  * AFS client service is accepting network requests using the 
145  * specified netbios names.
146  */
147 long
148 #ifdef _WIN64
149 cm_VolStatus_Network_Started(const char * netbios32, const char * netbios64)
150 #else /* _WIN64 */
151 cm_VolStatus_Network_Started(const char * netbios)
152 #endif /* _WIN64 */
153 {
154     long code = 0;
155
156     if (hVolStatus == NULL)
157         return 0;
158
159 #ifdef _WIN64
160     code = dll_funcs.dll_VolStatus_Network_Started(netbios32, netbios64);
161 #else
162     code = dll_funcs.dll_VolStatus_Network_Started(netbios, netbios);
163 #endif
164
165     return code;
166 }
167
168 /* This function notifies the Volume Status Handlers that the
169  * AFS client service is no longer accepting network requests 
170  * using the specified netbios names 
171  */
172 long
173 #ifdef _WIN64
174 cm_VolStatus_Network_Stopped(const char * netbios32, const char * netbios64)
175 #else /* _WIN64 */
176 cm_VolStatus_Network_Stopped(const char * netbios)
177 #endif /* _WIN64 */
178 {
179     long code = 0;
180
181     if (hVolStatus == NULL)
182         return 0;
183
184 #ifdef _WIN64
185     code = dll_funcs.dll_VolStatus_Network_Stopped(netbios32, netbios64);
186 #else
187     code = dll_funcs.dll_VolStatus_Network_Stopped(netbios, netbios);
188 #endif
189
190     return code;
191 }
192
193 /* This function is called when the IP address list changes.
194  * Volume Status Handlers can use this notification as a hint 
195  * that it might be possible to determine volume IDs for paths 
196  * that previously were not accessible.  
197  */
198 long 
199 cm_VolStatus_Network_Addr_Change(void)
200 {
201     long code = 0;
202
203     if (hVolStatus == NULL)
204         return 0;
205
206     code = dll_funcs.dll_VolStatus_Network_Addr_Change();
207
208     return code;
209 }
210
211 /* This function notifies the Volume Status Handlers that the 
212  * state of the specified cell.volume has changed.
213  */
214 long 
215 cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status)
216 {
217     long code = 0;
218
219     if (hVolStatus == NULL)
220         return 0;
221
222     code = dll_funcs.dll_VolStatus_Change_Notification(cellID, volID, status);
223
224     return code;
225 }
226
227
228 long __fastcall
229 cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID)
230 {
231     afs_uint32  code;
232     cm_req_t    req;
233     cm_scache_t *scp;
234
235     if (cellID == NULL || volID == NULL)
236         return CM_ERROR_INVAL;
237
238     cm_InitReq(&req);
239
240
241     code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
242     if (code)
243         return code;
244
245     lock_ObtainMutex(&scp->mx);
246     code = cm_SyncOp(scp, NULL,cm_rootUserp, &req, 0,
247                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
248     if (code) {
249         lock_ReleaseMutex(&scp->mx);
250         cm_ReleaseSCache(scp);
251         return code;
252     }
253         
254     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
255
256     *cellID = scp->fid.cell;
257     *volID  = scp->fid.volume;
258
259     lock_ReleaseMutex(&scp->mx);
260     cm_ReleaseSCache(scp);
261
262     return 0;
263 }
264
265 long __fastcall
266 cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer)
267 {
268     afs_uint32  code;
269     cm_req_t    req;
270     cm_scache_t *scp;
271     size_t      len;
272
273     if (pBufSize == NULL || (pBuffer == NULL && *pBufSize != 0))
274         return CM_ERROR_INVAL;
275
276     cm_InitReq(&req);
277
278     code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
279     if (code)
280         return code;
281
282     lock_ObtainMutex(&scp->mx);
283     code = cm_SyncOp(scp, NULL, cm_rootUserp, &req, 0,
284                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
285     if (code) {
286         lock_ReleaseMutex(&scp->mx);
287         cm_ReleaseSCache(scp);
288         return code;
289     }
290         
291     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
292
293     if (scp->fileType != CM_SCACHETYPE_DFSLINK)
294         return CM_ERROR_NOT_A_DFSLINK;
295
296     len = strlen(scp->mountPointStringp) + 1;
297     if (pBuffer == NULL)
298         *pBufSize = len;
299     else if (*pBufSize >= len) {
300         strcpy(pBuffer, scp->mountPointStringp);
301         *pBufSize = len;
302     } else 
303         code = CM_ERROR_TOOBIG;
304
305     lock_ReleaseMutex(&scp->mx);
306     cm_ReleaseSCache(scp);
307
308     return 0;
309 }