win95-initial-port-20010430
[openafs.git] / src / WINNT / afsadmsvr / TaAfsAdmSvrClientNotify.cpp
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 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include "TaAfsAdmSvrClientInternal.h"
16 #include <WINNT/AfsAppLib.h>
17
18
19 /*
20  * VARIABLES __________________________________________________________________
21  *
22  */
23
24 typedef struct
25    {
26    ASID idCell;
27    ASID idObject;
28    HWND hNotify;
29    } LISTENER, *LPLISTENER;
30
31 static struct
32    {
33    LPHASHLIST pListeners;
34    LPHASHLISTKEY pListenersKeyObject;
35
36    HWND *ahActionListeners;
37    size_t chActionListeners;
38    } l;
39
40
41 /*
42  * PROTOTYPES _________________________________________________________________
43  *
44  */
45
46 BOOL CALLBACK ListenersKeyObject_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData);
47 HASHVALUE CALLBACK ListenersKeyObject_HashObject (LPHASHLISTKEY pKey, PVOID pObject);
48 HASHVALUE CALLBACK ListenersKeyObject_HashData (LPHASHLISTKEY pKey, PVOID pData);
49
50
51 /*
52  * ROUTINES ___________________________________________________________________
53  *
54  */
55
56 BOOL AddObjectNotification (HWND hNotify, ASID idCell, ASID idObject)
57 {
58    asc_Enter();
59
60    if (!l.pListeners)
61       {
62       l.pListeners = New (HASHLIST);
63       l.pListenersKeyObject = l.pListeners->CreateKey (TEXT("idObject"), ListenersKeyObject_Compare, ListenersKeyObject_HashObject, ListenersKeyObject_HashData);
64       }
65
66    LPLISTENER pl = New (LISTENER);
67    pl->idCell = idCell;
68    pl->idObject = idObject;
69    pl->hNotify = hNotify;
70    l.pListeners->Add (pl);
71
72    asc_Leave();
73    return TRUE;
74 }
75
76
77 void ClearObjectNotifications (HWND hNotify)
78 {
79    asc_Enter();
80
81    if (l.pListeners)
82       {
83       for (LPENUM pEnum = l.pListeners->FindFirst(); pEnum; pEnum = pEnum->FindNext())
84          {
85          LPLISTENER pl = (LPLISTENER)( pEnum->GetObject() );
86          if (pl->hNotify == hNotify)
87             {
88             l.pListeners->Remove (pl);
89             Delete (pl);
90             }
91          }
92       }
93
94    asc_Leave();
95 }
96
97
98 void TestForNotifications (DWORD idClient, ASID idCell, ASID idObject)
99 {
100    if (l.pListeners)
101       {
102       // First we'll zip through our list of listeners and
103       // build an ASIDLIST reflecting the objects in this cell
104       // for which we're listening.
105       //
106       LPASIDLIST pAsidList = NULL;
107       for (LPENUM pEnum = l.pListeners->FindFirst(); pEnum; pEnum = pEnum->FindNext())
108          {
109          LPLISTENER pl = (LPLISTENER)( pEnum->GetObject() );
110          if (pl->idCell != idCell)
111             continue;
112          if (idObject && (pl->idObject != idObject))
113             continue;
114
115          if (!pAsidList)
116             {
117             if (!asc_AsidListCreate (&pAsidList))
118                break;
119             }
120          if (!asc_AsidListAddEntry (&pAsidList, pl->idObject, 0))
121             break;
122          }
123
124       // Then we'll call one of our cache routines, which in turn will tell
125       // the admin server what version of the properties we have for each
126       // of these objects; if any have newer properties available, we'll
127       // get them back--and that will cause us to send out notifications to
128       // our listeners.
129       //
130       if (pAsidList)
131          {
132          ULONG status;
133          (void)RefreshCachedProperties (idClient, idCell, pAsidList, GET_ALL_DATA, &status);
134          }
135       }
136 }
137
138
139 void NotifyObjectListeners (ASID idCell, ASID idObject)
140 {
141    // If we get here, our cache of information for the specified object
142    // has just been updated. Check for listeners who may be interested
143    // in changes to this object.
144    //
145    if (l.pListeners)
146       {
147       for (LPENUM pEnum = l.pListenersKeyObject->FindFirst (&idObject); pEnum; pEnum = pEnum->FindNext())
148          {
149          LPLISTENER pl = (LPLISTENER)( pEnum->GetObject() );
150          if (pl->idCell != idCell)
151             continue;
152
153          if (!IsWindow (pl->hNotify))
154             {
155             l.pListeners->Remove (pl);
156             Delete (pl);
157             continue;
158             }
159
160          PostMessage (pl->hNotify, WM_ASC_NOTIFY_OBJECT, (WPARAM)0, (LPARAM)idObject);
161          }
162       }
163 }
164
165
166 /*
167  * HASHLIST KEYS ______________________________________________________________
168  *
169  */
170
171 BOOL CALLBACK ListenersKeyObject_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
172 {
173    return (((LPLISTENER)pObject)->idObject == *(ASID*)pData) ? TRUE : FALSE;
174 }
175
176 HASHVALUE CALLBACK ListenersKeyObject_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
177 {
178    return ListenersKeyObject_HashData (pKey, &((LPLISTENER)pObject)->idObject);
179 }
180
181 HASHVALUE CALLBACK ListenersKeyObject_HashData (LPHASHLISTKEY pKey, PVOID pData)
182 {
183    return (HASHVALUE)*(ASID*)pData;
184 }
185
186
187
188 /*
189  * ACTION NOTIFICATIONS _______________________________________________________
190  *
191  */
192
193 BOOL SetActionNotification (HWND hNotify, BOOL fSet)
194 {
195    BOOL rc = TRUE;
196    asc_Enter();
197
198    if (!fSet)
199       {
200       for (size_t ii = 0; ii < l.chActionListeners; ++ii)
201          {
202          if (l.ahActionListeners[ ii ] == hNotify)
203             l.ahActionListeners[ ii ] = NULL;
204          }
205       }
206    else // (fSet)
207       {
208       for (size_t ii = 0; ii < l.chActionListeners; ++ii)
209          {
210          if (l.ahActionListeners[ ii ] == NULL)
211             break;
212          }
213       if (!REALLOC (l.ahActionListeners, l.chActionListeners, 1+ii, 1))
214          {
215          rc = FALSE;
216          }
217       else
218          {
219          l.ahActionListeners[ ii ] = hNotify;
220          }
221       }
222
223    asc_Leave();
224    return rc;
225 }
226
227
228 void NotifyActionListeners (LPASACTION pAction, BOOL fFinished)
229 {
230    asc_Enter();
231
232    for (size_t ii = 0; ii < l.chActionListeners; ++ii)
233       {
234       if (IsWindow (l.ahActionListeners[ ii ]))
235          {
236          LPASACTION pActionPost = New (ASACTION);
237          memcpy (pActionPost, pAction, sizeof(ASACTION));
238          PostMessage (l.ahActionListeners[ ii ], WM_ASC_NOTIFY_ACTION, (WPARAM)fFinished, (LPARAM)pActionPost);
239          }
240       }
241
242    asc_Leave();
243 }
244