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