windows-64bit-data-version-20071114
[openafs.git] / src / WINNT / afsd / cm_volstat.c
1 /* Copyright 2007 Secure Endpoints Inc.
2  *
3  * BSD 2-part License 
4  */
5
6 /* This source file provides the declarations 
7  * which specify the AFS Cache Manager Volume Status Event
8  * Notification API
9  */
10
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <windows.h>
15 #include <winsock2.h>
16 #include <nb30.h>
17 #include <string.h>
18 #include <malloc.h>
19 #include "afsd.h"
20 #include <WINNT/afsreg.h>
21
22 HMODULE hVolStatus = NULL;
23 dll_VolStatus_Funcs_t dll_funcs;
24 cm_VolStatus_Funcs_t cm_funcs;
25
26 /* This function is used to load any Volume Status Handlers 
27  * and their associated function pointers.  
28  */
29 long 
30 cm_VolStatus_Initialization(void)
31 {
32     long (__fastcall * dll_VolStatus_Initialization)(dll_VolStatus_Funcs_t * dll_funcs, cm_VolStatus_Funcs_t *cm_funcs) = NULL;
33     long code = 0;
34     HKEY parmKey;
35     DWORD dummyLen;
36     char wd[MAX_PATH+1] = "";
37
38     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
39                          0, KEY_QUERY_VALUE, &parmKey);
40     if (code == ERROR_SUCCESS) {
41         dummyLen = sizeof(wd);
42         code = RegQueryValueEx(parmKey, "VolStatusHandler", NULL, NULL,
43                                 (BYTE *) &wd, &dummyLen);
44         RegCloseKey (parmKey);
45     }
46
47     if (code == ERROR_SUCCESS && wd[0])
48         hVolStatus = LoadLibrary(wd);
49     if (hVolStatus) {
50         (FARPROC) dll_VolStatus_Initialization = GetProcAddress(hVolStatus, "@VolStatus_Initialization@8");
51         if (dll_VolStatus_Initialization) {
52             cm_funcs.version = CM_VOLSTATUS_FUNCS_VERSION;
53             cm_funcs.cm_VolStatus_Path_To_ID = cm_VolStatus_Path_To_ID;
54             cm_funcs.cm_VolStatus_Path_To_DFSlink = cm_VolStatus_Path_To_DFSlink;
55
56             code = dll_VolStatus_Initialization(&dll_funcs, &cm_funcs);
57         } 
58
59         if (dll_VolStatus_Initialization == NULL || code != 0 || 
60             dll_funcs.version != DLL_VOLSTATUS_FUNCS_VERSION) {
61             FreeLibrary(hVolStatus);
62             hVolStatus = NULL;
63             code = -1;
64         }
65     }
66
67     return code;
68 }
69
70 /* This function is used to unload any Volume Status Handlers
71  * that were loaded during initialization.
72  */
73 long 
74 cm_VolStatus_Finalize(void)
75 {
76     if (hVolStatus == NULL)
77         return 0;
78
79     FreeLibrary(hVolStatus);
80     hVolStatus = NULL;
81     return 0;
82 }
83
84 /* This function notifies the Volume Status Handlers that the
85  * AFS client service has started.  If the network is started
86  * at this point we call cm_VolStatus_Network_Started().
87  */
88 long 
89 cm_VolStatus_Service_Started(void)
90 {
91     long code = 0;
92
93     if (hVolStatus == NULL)
94         return 0;
95    
96     code = dll_funcs.dll_VolStatus_Service_Started();
97     if (code == 0 && smb_IsNetworkStarted())
98         code = dll_funcs.dll_VolStatus_Network_Started(cm_NetbiosName, cm_NetbiosName);
99
100     return code;
101 }
102
103 /* This function notifies the Volume Status Handlers that the
104  * AFS client service is stopping.
105  */
106 long 
107 cm_VolStatus_Service_Stopped(void)
108 {
109     long code = 0;
110
111     if (hVolStatus == NULL)
112         return 0;
113    
114     code = dll_funcs.dll_VolStatus_Service_Stopped();
115
116     return code;
117 }
118
119
120 /* This function notifies the Volume Status Handlers that the
121  * AFS client service is accepting network requests using the 
122  * specified netbios names.
123  */
124 long
125 #ifdef _WIN64
126 cm_VolStatus_Network_Started(const char * netbios32, const char * netbios64)
127 #else /* _WIN64 */
128 cm_VolStatus_Network_Started(const char * netbios)
129 #endif /* _WIN64 */
130 {
131     long code = 0;
132
133     if (hVolStatus == NULL)
134         return 0;
135
136 #ifdef _WIN64
137     code = dll_funcs.dll_VolStatus_Network_Started(netbios32, netbios64);
138 #else
139     code = dll_funcs.dll_VolStatus_Network_Started(netbios, netbios);
140 #endif
141
142     return code;
143 }
144
145 /* This function notifies the Volume Status Handlers that the
146  * AFS client service is no longer accepting network requests 
147  * using the specified netbios names 
148  */
149 long
150 #ifdef _WIN64
151 cm_VolStatus_Network_Stopped(const char * netbios32, const char * netbios64)
152 #else /* _WIN64 */
153 cm_VolStatus_Network_Stopped(const char * netbios)
154 #endif /* _WIN64 */
155 {
156     long code = 0;
157
158     if (hVolStatus == NULL)
159         return 0;
160
161 #ifdef _WIN64
162     code = dll_funcs.dll_VolStatus_Network_Stopped(netbios32, netbios64);
163 #else
164     code = dll_funcs.dll_VolStatus_Network_Stopped(netbios, netbios);
165 #endif
166
167     return code;
168 }
169
170 /* This function is called when the IP address list changes.
171  * Volume Status Handlers can use this notification as a hint 
172  * that it might be possible to determine volume IDs for paths 
173  * that previously were not accessible.  
174  */
175 long 
176 cm_VolStatus_Network_Addr_Change(void)
177 {
178     long code = 0;
179
180     if (hVolStatus == NULL)
181         return 0;
182
183     code = dll_funcs.dll_VolStatus_Network_Addr_Change();
184
185     return code;
186 }
187
188 /* This function notifies the Volume Status Handlers that the 
189  * state of the specified cell.volume has changed.
190  */
191 long 
192 cm_VolStatus_Change_Notification(afs_uint32 cellID, afs_uint32 volID, enum volstatus status)
193 {
194     long code = 0;
195
196     if (hVolStatus == NULL)
197         return 0;
198
199     code = dll_funcs.dll_VolStatus_Change_Notification(cellID, volID, status);
200
201     return code;
202 }
203
204
205 long __fastcall
206 cm_VolStatus_Path_To_ID(const char * share, const char * path, afs_uint32 * cellID, afs_uint32 * volID)
207 {
208     afs_uint32  code;
209     cm_req_t    req;
210     cm_scache_t *scp;
211
212     if (cellID == NULL || volID == NULL)
213         return CM_ERROR_INVAL;
214
215     cm_InitReq(&req);
216
217
218     code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
219     if (code)
220         return code;
221
222     lock_ObtainMutex(&scp->mx);
223     code = cm_SyncOp(scp, NULL,cm_rootUserp, &req, 0,
224                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
225     if (code) {
226         lock_ReleaseMutex(&scp->mx);
227         cm_ReleaseSCache(scp);
228         return code;
229     }
230         
231     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
232
233     *cellID = scp->fid.cell;
234     *volID  = scp->fid.volume;
235
236     lock_ReleaseMutex(&scp->mx);
237     cm_ReleaseSCache(scp);
238
239     return 0;
240 }
241
242 long __fastcall
243 cm_VolStatus_Path_To_DFSlink(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer)
244 {
245     afs_uint32  code;
246     cm_req_t    req;
247     cm_scache_t *scp;
248     size_t      len;
249
250     if (pBufSize == NULL || (pBuffer == NULL && *pBufSize != 0))
251         return CM_ERROR_INVAL;
252
253     cm_InitReq(&req);
254
255     code = cm_NameI(cm_data.rootSCachep, (char *)path, CM_FLAG_FOLLOW, cm_rootUserp, (char *)share, &req, &scp);
256     if (code)
257         return code;
258
259     lock_ObtainMutex(&scp->mx);
260     code = cm_SyncOp(scp, NULL, cm_rootUserp, &req, 0,
261                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
262     if (code) {
263         lock_ReleaseMutex(&scp->mx);
264         cm_ReleaseSCache(scp);
265         return code;
266     }
267         
268     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
269
270     if (scp->fileType != CM_SCACHETYPE_DFSLINK)
271         return CM_ERROR_NOT_A_DFSLINK;
272
273     len = strlen(scp->mountPointStringp) + 1;
274     if (pBuffer == NULL)
275         *pBufSize = len;
276     else if (*pBufSize >= len) {
277         strcpy(pBuffer, scp->mountPointStringp);
278         *pBufSize = len;
279     } else 
280         code = CM_ERROR_TOOBIG;
281
282     lock_ReleaseMutex(&scp->mx);
283     cm_ReleaseSCache(scp);
284
285     return 0;
286 }