jbuehler-add-missing-extern-c-patch-20031207
[openafs.git] / src / WINNT / afsadmsvr / TaAfsAdmSvrClient.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
17
18 /*
19  * VARIABLES __________________________________________________________________
20  *
21  */
22
23 static struct
24    {
25    BOOL fInitializedSockets;
26    size_t cReqForAdminServer;
27    } l;
28
29
30 /*
31  * ROUTINES ___________________________________________________________________
32  *
33  */
34
35 extern "C" void __RPC_FAR * __RPC_USER MIDL_user_allocate (size_t cbAllocate)
36 {
37    return (void __RPC_FAR *)Allocate (cbAllocate);
38 }
39
40 extern "C" void __RPC_USER MIDL_user_free (void __RPC_FAR *pData)
41 {
42    Free (pData);
43 }
44
45
46 /*
47  * DATA STRUCTURES ____________________________________________________________
48  *
49  */
50
51 BOOL ADMINAPI asc_AsidListCreate (LPASIDLIST *ppList)
52 {
53    return ((*ppList = AfsAdmSvr_CreateAsidList()) != NULL);
54 }
55
56 BOOL ADMINAPI asc_AsidListCopy (LPASIDLIST *ppListTarget, LPASIDLIST *ppListSource)
57 {
58    return ((*ppListTarget = AfsAdmSvr_CopyAsidList (*ppListSource)) != NULL);
59 }
60
61 BOOL ADMINAPI asc_AsidListAddEntry (LPASIDLIST *ppList, ASID idObject, LPARAM lp)
62 {
63    return AfsAdmSvr_AddToAsidList (ppList, idObject, lp);
64 }
65
66 BOOL ADMINAPI asc_AsidListRemoveEntry (LPASIDLIST *ppList, ASID idObject)
67 {
68    return AfsAdmSvr_RemoveFromAsidList (ppList, idObject);
69 }
70
71 BOOL ADMINAPI asc_AsidListRemoveEntryByIndex (LPASIDLIST *ppList, size_t iIndex)
72 {
73    return AfsAdmSvr_RemoveFromAsidListByIndex (ppList, iIndex);
74 }
75
76 BOOL ADMINAPI asc_AsidListSetEntryParam (LPASIDLIST *ppList, ASID idObject, LPARAM lp)
77 {
78    return AfsAdmSvr_SetAsidListParam (ppList, idObject, lp);
79 }
80
81 BOOL ADMINAPI asc_AsidListSetEntryParamByIndex (LPASIDLIST *ppList, size_t iIndex, LPARAM lp)
82 {
83    return AfsAdmSvr_SetAsidListParamByIndex (ppList, iIndex, lp);
84 }
85
86 BOOL ADMINAPI asc_AsidListTest (LPASIDLIST *ppList, ASID idObject, LPARAM *pParam)
87 {
88    return AfsAdmSvr_IsInAsidList (ppList, idObject, pParam);
89 }
90
91 BOOL ADMINAPI asc_AsidListFree (LPASIDLIST *ppList)
92 {
93    AfsAdmSvr_FreeAsidList (ppList);
94    return TRUE;
95 }
96
97
98 BOOL ADMINAPI asc_ObjPropListCreate (LPASOBJPROPLIST *ppList)
99 {
100    return ((*ppList = AfsAdmSvr_CreateObjPropList()) != NULL);
101 }
102
103 BOOL ADMINAPI asc_ObjPropListCopy (LPASOBJPROPLIST *ppListTarget, LPASOBJPROPLIST *ppListSource)
104 {
105    return ((*ppListTarget = AfsAdmSvr_CopyObjPropList (*ppListSource)) != NULL);
106 }
107
108 BOOL ADMINAPI asc_ObjPropListAddEntry (LPASOBJPROPLIST *ppList, LPASOBJPROP pProperties, LPARAM lp)
109 {
110    return AfsAdmSvr_AddToObjPropList (ppList, pProperties, lp);
111 }
112
113 BOOL ADMINAPI asc_ObjPropListRemoveEntry (LPASOBJPROPLIST *ppList, ASID idObject)
114 {
115    return AfsAdmSvr_RemoveFromObjPropList (ppList, idObject);
116 }
117
118 BOOL ADMINAPI asc_ObjPropListTest (LPASOBJPROPLIST *ppList, ASID idObject, LPASOBJPROP pProperties, LPARAM *pParam)
119 {
120    return AfsAdmSvr_IsInObjPropList (ppList, idObject, pProperties, pParam);
121 }
122
123 BOOL ADMINAPI asc_ObjPropListFree (LPASOBJPROPLIST *ppList)
124 {
125    AfsAdmSvr_FreeObjPropList (ppList);
126    return TRUE;
127 }
128
129
130 BOOL ADMINAPI asc_ActionListCreate (LPASACTIONLIST *ppList)
131 {
132    return ((*ppList = AfsAdmSvr_CreateActionList()) != NULL);
133 }
134
135 BOOL ADMINAPI asc_ActionListCopy (LPASACTIONLIST *ppListTarget, LPASACTIONLIST *ppListSource)
136 {
137    return ((*ppListTarget = AfsAdmSvr_CopyActionList (*ppListSource)) != NULL);
138 }
139
140 BOOL ADMINAPI asc_ActionListAddEntry (LPASACTIONLIST *ppList, LPASACTION pAction)
141 {
142    return AfsAdmSvr_AddToActionList (ppList, pAction);
143 }
144
145 BOOL ADMINAPI asc_ActionListRemoveEntry (LPASACTIONLIST *ppList, DWORD idAction)
146 {
147    return AfsAdmSvr_RemoveFromActionList (ppList, idAction);
148 }
149
150 BOOL ADMINAPI asc_ActionListTest (LPASACTIONLIST *ppList, DWORD idAction, LPASACTION pAction)
151 {
152    return AfsAdmSvr_IsInActionList (ppList, idAction, pAction);
153 }
154
155 BOOL ADMINAPI asc_ActionListFree (LPASACTIONLIST *ppList)
156 {
157    AfsAdmSvr_FreeActionList (ppList);
158    return TRUE;
159 }
160
161
162 /*
163  * ROUTINES ___________________________________________________________________
164  *
165  */
166
167 BOOL ADMINAPI asc_AdminServerOpen (LPCTSTR pszAddress, DWORD *pidClient, ULONG *pStatus)
168 {
169    BOOL rc = TRUE;
170    ULONG status = 0;
171
172    if (!l.fInitializedSockets)
173       {
174       WSADATA Data;
175       WSAStartup (0x0101, &Data);
176       l.fInitializedSockets = TRUE;
177       }
178
179    if ((++l.cReqForAdminServer) == 1)
180       {
181       LPCTSTR pszResolvedAddress = ResolveAddress (pszAddress);
182       if (!BindToAdminServer (pszResolvedAddress, FALSE, pidClient, &status))
183          {
184          if (status != RPC_S_CALL_FAILED_DNE) // server rejected us?
185             rc = FALSE;
186          else if (pszResolvedAddress || !ForkNewAdminServer (&status))
187             rc = FALSE;
188          else
189             rc = BindToAdminServer (pszResolvedAddress, TRUE, pidClient, &status);
190          }
191       }
192
193    if (rc)
194       StartPingThread (*pidClient);
195    if (rc)
196       StartCallbackThread();
197    if (!rc && pStatus)
198       *pStatus = status;
199    return rc;
200 }
201
202
203 BOOL ADMINAPI asc_AdminServerClose (DWORD idClient, ULONG *pStatus)
204 {
205    BOOL rc = TRUE;
206    ULONG status = 0;
207
208    StopCallbackThread();
209    StopPingThread (idClient);
210
211    if (l.cReqForAdminServer && ((--l.cReqForAdminServer) == 0))
212       {
213       UnbindFromAdminServer (idClient, &status);
214       }
215
216    if (!rc && pStatus)
217       *pStatus = status;
218    return rc;
219 }
220
221
222
223 BOOL ADMINAPI asc_CredentialsCrack (DWORD idClient, PVOID hCreds, LPTSTR pszCell, LPTSTR pszUser, SYSTEMTIME *pstExpiration, ULONG *pStatus)
224 {
225    BOOL rc = FALSE;
226    ULONG status = 0;
227
228    RpcTryExcept
229       {
230       STRING szCell = TEXT("");
231       STRING szUser = TEXT("");
232
233       if ((rc = AfsAdmSvr_CrackCredentials (idClient, (DWORD)hCreds, szCell, szUser, pstExpiration, &status)) != FALSE)
234          {
235          lstrcpy (pszCell, szCell);
236          lstrcpy (pszUser, szUser);
237          }
238       }
239    RpcExcept(1)
240       {
241       rc = FALSE;
242       status = RPC_S_CALL_FAILED_DNE;
243       }
244    RpcEndExcept
245
246    if (!rc && pStatus)
247       *pStatus = status;
248    return rc;
249 }
250
251
252 PVOID ADMINAPI asc_CredentialsGet (DWORD idClient, LPCTSTR pszCell, ULONG *pStatus)
253 {
254    PVOID rc = NULL;
255    ULONG status = 0;
256
257    RpcTryExcept
258       {
259       if (pszCell)
260          {
261          STRING szCell;
262          lstrcpy (szCell, pszCell);
263
264          rc = (PVOID)AfsAdmSvr_GetCredentials (idClient, szCell, &status);
265          }
266       }
267    RpcExcept(1)
268       {
269       rc = FALSE;
270       status = RPC_S_CALL_FAILED_DNE;
271       }
272    RpcEndExcept
273
274    if (!rc && pStatus)
275       *pStatus = status;
276    return rc;
277 }
278
279
280 PVOID ADMINAPI asc_CredentialsSet (DWORD idClient, LPCTSTR pszCell, LPCTSTR pszUser, LPCTSTR pszPassword, ULONG *pStatus)
281 {
282    PVOID rc = NULL;
283    ULONG status = 0;
284
285    RpcTryExcept
286       {
287       STRING szCell;
288       lstrcpy (szCell, pszCell);
289
290       STRING szUser;
291       lstrcpy (szUser, pszUser);
292
293       STRING szPassword;
294       lstrcpy (szPassword, pszPassword);
295
296       // TODO: Ensure we do some encryption here, or using an
297       // encrypted socket, or something... can't just be pushing
298       // the user's unencrypted password across the wire.
299
300       rc = (PVOID)AfsAdmSvr_SetCredentials (idClient, szCell, szUser, szPassword, &status);
301       }
302    RpcExcept(1)
303       {
304       rc = FALSE;
305       status = RPC_S_CALL_FAILED_DNE;
306       }
307    RpcEndExcept
308
309    if (!rc && pStatus)
310       *pStatus = status;
311    return rc;
312 }
313
314
315 BOOL ADMINAPI asc_CredentialsPush (DWORD idClient, PVOID hCreds, ASID idCell, ULONG *pStatus)
316 {
317    BOOL rc = TRUE;
318    ULONG status = 0;
319
320    RpcTryExcept
321       {
322       rc = AfsAdmSvr_PushCredentials (idClient, (DWORD)hCreds, idCell, &status);
323       }
324    RpcExcept(1)
325       {
326       rc = FALSE;
327       status = RPC_S_CALL_FAILED_DNE;
328       }
329    RpcEndExcept
330
331    if (!rc && pStatus)
332       *pStatus = status;
333    return rc;
334 }
335
336
337 BOOL ADMINAPI asc_LocalCellGet (DWORD idClient, LPTSTR pszCell, ULONG *pStatus)
338 {
339    BOOL rc = TRUE;
340    ULONG status = 0;
341
342    RpcTryExcept
343       {
344       STRING szCell;
345       if ((rc = AfsAdmSvr_GetLocalCell (idClient, szCell, &status)) != FALSE)
346          {
347          lstrcpy (pszCell, szCell);
348          }
349       }
350    RpcExcept(1)
351       {
352       rc = FALSE;
353       status = RPC_S_CALL_FAILED_DNE;
354       }
355    RpcEndExcept
356
357    if (!rc && pStatus)
358       *pStatus = status;
359    return rc;
360 }
361
362
363 BOOL ADMINAPI asc_ErrorCodeTranslate (DWORD idClient, ULONG code, LANGID idLanguage, STRING pszErrorText, ULONG *pStatus)
364 {
365    BOOL rc = TRUE;
366    ULONG status = 0;
367
368    RpcTryExcept
369       {
370       STRING szText;
371       if ((rc = AfsAdmSvr_ErrorCodeTranslate (idClient, code, idLanguage, szText, &status)) != FALSE)
372          {
373          lstrcpy (pszErrorText, szText);
374          }
375       }
376    RpcExcept(1)
377       {
378       rc = FALSE;
379       status = RPC_S_CALL_FAILED_DNE;
380       }
381    RpcEndExcept
382
383    if (!rc && pStatus)
384       *pStatus = status;
385    return rc;
386 }
387
388
389 BOOL ADMINAPI asc_CellOpen (DWORD idClient, PVOID hCreds, LPCTSTR pszCell, DWORD dwScope, ASID *pidCell, ULONG *pStatus)
390 {
391    BOOL rc = TRUE;
392    ULONG status = 0;
393
394    RpcTryExcept
395       {
396       STRING szCell;
397       lstrcpy (szCell, pszCell);
398
399       if ((rc = AfsAdmSvr_OpenCell (idClient, (DWORD)hCreds, szCell, dwScope, pidCell, &status)) != FALSE)
400          {
401          if (!CreateCellCache (*pidCell))
402             {
403             (void)AfsAdmSvr_CloseCell (idClient, *pidCell, &status);
404             rc = FALSE;
405             status = ERROR_NOT_ENOUGH_MEMORY;
406             }
407          else // get rudimentary properties about the cell
408             {
409             rc = RefreshCachedProperties (idClient, *pidCell, *pidCell, GET_RUDIMENTARY_DATA, &status);
410             }
411          }
412       }
413    RpcExcept(1)
414       {
415       rc = FALSE;
416       status = RPC_S_CALL_FAILED_DNE;
417       }
418    RpcEndExcept
419
420    if (!rc && pStatus)
421       *pStatus = status;
422    return rc;
423 }
424
425
426 BOOL ADMINAPI asc_CellClose (DWORD idClient, ASID idCell, ULONG *pStatus)
427 {
428    BOOL rc = TRUE;
429    ULONG status = 0;
430
431    RpcTryExcept
432       {
433       rc = AfsAdmSvr_CloseCell (idClient, idCell, &status);
434       DestroyCellCache (idCell);
435       }
436    RpcExcept(1)
437       {
438       rc = FALSE;
439       status = RPC_S_CALL_FAILED_DNE;
440       }
441    RpcEndExcept
442
443    if (!rc && pStatus)
444       *pStatus = status;
445    return rc;
446 }
447
448
449 BOOL ADMINAPI asc_ObjectFind (DWORD idClient, ASID idSearchScope, ASOBJTYPE ObjectType, LPCTSTR pszName, ASID *pidObject, ULONG *pStatus)
450 {
451    BOOL rc = TRUE;
452    ULONG status = 0;
453
454    RpcTryExcept
455       {
456       STRING szName = TEXT("");
457       if (pszName)
458          lstrcpy (szName, pszName);
459       rc = AfsAdmSvr_FindObject (idClient, idSearchScope, ObjectType, SEARCH_ALL_OBJECTS, szName, pidObject, &status);
460       }
461    RpcExcept(1)
462       {
463       rc = FALSE;
464       status = RPC_S_CALL_FAILED_DNE;
465       }
466    RpcEndExcept
467
468    if (!rc && pStatus)
469       *pStatus = status;
470    return rc;
471 }
472
473
474 BOOL ADMINAPI asc_ObjectFindMultiple (DWORD idClient, ASID idSearchScope, ASOBJTYPE ObjectType, LPCTSTR pszPattern, LPAFSADMSVR_SEARCH_PARAMS pSearchParams, LPASIDLIST *ppList, ULONG *pStatus)
475 {
476    BOOL rc = TRUE;
477    ULONG status = 0;
478
479    RpcTryExcept
480       {
481       *ppList = NULL;
482
483       STRING szPattern = TEXT("");
484       if (pszPattern)
485          lstrcpy (szPattern, pszPattern);
486
487       AFSADMSVR_SEARCH_PARAMS SearchParams;
488       if (pSearchParams)
489          memcpy (&SearchParams, pSearchParams, sizeof(AFSADMSVR_SEARCH_PARAMS));
490       else
491          {
492          memset (&SearchParams, 0x00, sizeof(AFSADMSVR_SEARCH_PARAMS));
493          SearchParams.SearchType = SEARCH_NO_LIMITATIONS;
494          }
495
496       rc = AfsAdmSvr_FindObjects (idClient, idSearchScope, ObjectType, SEARCH_ALL_OBJECTS, szPattern, &SearchParams, ppList, &status);
497       }
498    RpcExcept(1)
499       {
500       rc = FALSE;
501       status = RPC_S_CALL_FAILED_DNE;
502       }
503    RpcEndExcept
504
505    if (!rc && pStatus)
506       *pStatus = status;
507    return rc;
508 }
509
510
511 BOOL ADMINAPI asc_ObjectPropertiesGet (DWORD idClient, AFSADMSVR_GET_LEVEL GetLevel, ASID idCell, ASID idObject, LPASOBJPROP pProperties, ULONG *pStatus)
512 {
513    BOOL rc = TRUE;
514    ULONG status = 0;
515
516    if (!RefreshCachedProperties (idClient, idCell, idObject, GetLevel, &status))
517       {
518       rc = FALSE;
519       }
520    else
521       {
522       LPASOBJPROP pFound;
523       if ((pFound = GetCachedProperties (idCell, idObject)) == NULL)
524          {
525          status = ERROR_NOT_ENOUGH_MEMORY;
526          rc = FALSE;
527          }
528       else
529          {
530          memcpy (pProperties, pFound, sizeof(ASOBJPROP));
531          }
532       }
533
534    if (!rc && pStatus)
535       *pStatus = status;
536    return rc;
537 }
538
539
540 BOOL ADMINAPI asc_ObjectPropertiesGetMultiple (DWORD idClient, AFSADMSVR_GET_LEVEL GetLevel, ASID idCell, LPASIDLIST pAsidList, LPASOBJPROPLIST *ppPropertiesList, ULONG *pStatus)
541 {
542    BOOL rc = TRUE;
543    ULONG status = 0;
544
545    if (!RefreshCachedProperties (idClient, idCell, pAsidList, GetLevel, &status))
546       {
547       rc = FALSE;
548       }
549    else
550       {
551       *ppPropertiesList = NULL;
552       for (size_t iAsidList = 0; iAsidList < pAsidList->cEntries; ++iAsidList)
553          {
554          LPASOBJPROP pFound;
555          if ((pFound = GetCachedProperties (idCell, pAsidList->aEntries[ iAsidList ].idObject)) != NULL)
556             {
557             if (!*ppPropertiesList)
558                asc_ObjPropListCreate(ppPropertiesList);
559             if (*ppPropertiesList)
560                AfsAdmSvr_AddToObjPropList (ppPropertiesList, pFound, pAsidList->aEntries[ iAsidList ].lParam);
561             }
562          }
563       }
564
565    if (!rc && *ppPropertiesList)
566       AfsAdmSvr_FreeObjPropList (ppPropertiesList);
567    if (!rc && pStatus)
568       *pStatus = status;
569    return rc;
570 }
571
572
573 BOOL ADMINAPI asc_ObjectListen (DWORD idClient, ASID idCell, ASID idObject, HWND hNotify, ULONG *pStatus)
574 {
575    if (!idObject)
576       {
577       if (*pStatus)
578          *pStatus = ERROR_INVALID_PARAMETER;
579       return FALSE;
580       }
581
582    if (!AddObjectNotification (hNotify, idCell, idObject))
583       {
584       if (*pStatus)
585          *pStatus = ERROR_NOT_ENOUGH_MEMORY;
586       return FALSE;
587       }
588
589    TestForNotifications (idClient, idCell, idObject);
590    return TRUE;
591 }
592
593
594 BOOL ADMINAPI asc_ObjectListenClear (DWORD idClient, HWND hNotify, ULONG *pStatus)
595 {
596    ClearObjectNotifications (hNotify);
597    return TRUE;
598 }
599
600
601 BOOL ADMINAPI asc_ObjectListenMultiple (DWORD idClient, ASID idCell, LPASIDLIST pAsidList, HWND hNotify, ULONG *pStatus)
602 {
603    if (!pAsidList)
604       {
605       if (*pStatus)
606          *pStatus = ERROR_INVALID_PARAMETER;
607       return FALSE;
608       }
609
610    for (size_t ii = 0; ii < pAsidList->cEntriesAllocated; ++ii)
611       {
612       if (!pAsidList->aEntries[ ii ].idObject)
613          continue;
614
615       if (!AddObjectNotification (hNotify, idCell, pAsidList->aEntries[ ii ].idObject))
616          {
617          if (*pStatus)
618             *pStatus = ERROR_NOT_ENOUGH_MEMORY;
619          return FALSE;
620          }
621
622       TestForNotifications (idClient, idCell, pAsidList->aEntries[ ii ].idObject);
623       }
624
625    return TRUE;
626 }
627
628
629 BOOL ADMINAPI asc_ObjectRefresh (DWORD idClient, ASID idCell, ASID idObject, ULONG *pStatus)
630 {
631    BOOL rc = TRUE;
632    ULONG status = 0;
633
634    // First have the server invalidate its cache of information; regardless
635    // of the name, this is actually just an Invalidate call, not a Refresh call
636    //
637    RpcTryExcept
638       {
639       rc = AfsAdmSvr_RefreshObject (idClient, idObject, &status);
640       }
641    RpcExcept(1)
642       {
643       rc = FALSE;
644       status = RPC_S_CALL_FAILED_DNE;
645       }
646    RpcEndExcept
647
648    // If that suceeded, see if there is anyone listening for changes
649    // in this object or any of its children. If so, this call
650    // will requery the server for the latest properties for all
651    // listened-for objects, which will make us post notifications if
652    // we get new data back.
653    //
654    if (rc)
655       {
656       TestForNotifications (idClient, idCell);
657       }
658
659    if (!rc && pStatus)
660       *pStatus = status;
661    return rc;
662 }
663
664
665 BOOL ADMINAPI asc_ObjectRefreshMultiple (DWORD idClient, ASID idCell, LPASIDLIST pAsidList, ULONG *pStatus)
666 {
667    BOOL rc = TRUE;
668    ULONG status = 0;
669
670    // First have the server invalidate its cache of information; regardless
671    // of the name, this is actually just an Invalidate call, not a Refresh call
672    //
673    RpcTryExcept
674       {
675       rc = AfsAdmSvr_RefreshObjects (idClient, pAsidList, &status);
676       }
677    RpcExcept(1)
678       {
679       rc = FALSE;
680       status = RPC_S_CALL_FAILED_DNE;
681       }
682    RpcEndExcept
683
684    // If that suceeded, see if there is anyone listening for changes
685    // in any of these objects or their children. If so, this call
686    // will requery the server for the latest properties for all
687    // listened-for objects, which will make us post notifications if
688    // we get new data back.
689    //
690    if (rc)
691       {
692       TestForNotifications (idClient, idCell);
693       }
694
695    if (!rc && pStatus)
696       *pStatus = status;
697    return rc;
698 }
699
700
701 BOOL ADMINAPI asc_RandomKeyGet (DWORD idClient, ASID idCell, PBYTE key, ULONG *pStatus)
702 {
703    BOOL rc = TRUE;
704    ULONG status = 0;
705
706    RpcTryExcept
707       {
708       memset (key, 0x00, sizeof(BYTE) * ENCRYPTIONKEYLENGTH);
709       rc = AfsAdmSvr_GetRandomKey (idClient, idCell, key, &status);
710       }
711    RpcExcept(1)
712       {
713       rc = FALSE;
714       status = RPC_S_CALL_FAILED_DNE;
715       }
716    RpcEndExcept
717
718    if (!rc && pStatus)
719       *pStatus = status;
720    return rc;
721 }
722
723
724 BOOL ADMINAPI asc_CellNameGet_Fast (DWORD idClient, ASID idCell, LPTSTR pszCell, ULONG *pStatus)
725 {
726    return asc_ObjectNameGet_Fast (idClient, idCell, idCell, pszCell, pStatus);
727 }
728
729
730 BOOL ADMINAPI asc_ObjectNameGet_Fast (DWORD idClient, ASID idCell, ASID idObject, LPTSTR pszObject, ULONG *pStatus)
731 {
732    BOOL rc = TRUE;
733    ULONG status = 0;
734
735    LPASOBJPROP pProperties;
736    if ((pProperties = GetCachedProperties (idCell, idObject)) == NULL)
737       {
738       rc = FALSE;
739       status = ERROR_NO_DATA;
740       }
741    else if (pProperties->verProperties == verPROP_NO_OBJECT)
742       {
743       rc = FALSE;
744       status = ERROR_NO_DATA;
745       }
746    else
747       {
748       lstrcpy (pszObject, pProperties->szName);
749       }
750
751    if (!rc && pStatus)
752       *pStatus = status;
753    return rc;
754 }
755
756
757 BOOL ADMINAPI asc_ObjectTypeGet_Fast (DWORD idClient, ASID idCell, ASID idObject, ASOBJTYPE *pObjectType, ULONG *pStatus)
758 {
759    BOOL rc = TRUE;
760    ULONG status = 0;
761
762    LPASOBJPROP pProperties;
763    if ((pProperties = GetCachedProperties (idCell, idObject)) == NULL)
764       {
765       rc = FALSE;
766       status = ERROR_NO_DATA;
767       }
768    else if (pProperties->verProperties == verPROP_NO_OBJECT)
769       {
770       rc = FALSE;
771       status = ERROR_NO_DATA;
772       }
773    else
774       {
775       *pObjectType = pProperties->Type;
776       }
777
778    if (!rc && pStatus)
779       *pStatus = status;
780    return rc;
781 }
782
783
784 BOOL ADMINAPI asc_ObjectPropertiesGet_Fast (DWORD idClient, ASID idCell, ASID idObject, LPASOBJPROP pProperties, ULONG *pStatus)
785 {
786    BOOL rc = TRUE;
787    ULONG status = 0;
788
789    LPASOBJPROP pPropFound;
790    if ((pPropFound = GetCachedProperties (idCell, idObject)) == NULL)
791       {
792       rc = FALSE;
793       status = ERROR_NO_DATA;
794       }
795    else if (pPropFound->verProperties == verPROP_NO_OBJECT)
796       {
797       rc = FALSE;
798       status = ERROR_NO_DATA;
799       }
800    else if (pProperties)
801       {
802       memcpy (pProperties, pPropFound, sizeof(ASOBJPROP));
803       }
804
805    if (!rc && pStatus)
806       *pStatus = status;
807    return rc;
808 }
809
810
811 BOOL ADMINAPI asc_ActionGet (DWORD idClient, DWORD idAction, LPASACTION pAction, ULONG *pStatus)
812 {
813    BOOL rc = TRUE;
814    ULONG status = 0;
815
816    RpcTryExcept
817       {
818       memset (pAction, 0x00, sizeof(ASACTION));
819       rc = AfsAdmSvr_GetAction (idClient, idAction, pAction, &status);
820       }
821    RpcExcept(1)
822       {
823       rc = FALSE;
824       status = RPC_S_CALL_FAILED_DNE;
825       }
826    RpcEndExcept
827
828    if (!rc && pStatus)
829       *pStatus = status;
830    return rc;
831 }
832
833
834 BOOL ADMINAPI asc_ActionGetMultiple (DWORD idClient, DWORD idClientSearch, ASID idCellSearch, LPASACTIONLIST *ppList, ULONG *pStatus)
835 {
836    BOOL rc = TRUE;
837    ULONG status = 0;
838
839    RpcTryExcept
840       {
841       *ppList = NULL;
842       rc = AfsAdmSvr_GetActions (idClient, idClientSearch, idCellSearch, ppList, &status);
843       }
844    RpcExcept(1)
845       {
846       rc = FALSE;
847       status = RPC_S_CALL_FAILED_DNE;
848       }
849    RpcEndExcept
850
851    if (!rc && pStatus)
852       *pStatus = status;
853    return rc;
854 }
855
856
857 BOOL ADMINAPI asc_ActionListen (DWORD idClient, HWND hNotify, ULONG *pStatus)
858 {
859    if (!SetActionNotification (hNotify, TRUE))
860       {
861       if (*pStatus)
862          *pStatus = ERROR_NOT_ENOUGH_MEMORY;
863       return FALSE;
864       }
865    return TRUE;
866 }
867
868
869 BOOL ADMINAPI asc_ActionListenClear (DWORD idClient, HWND hNotify, ULONG *pStatus)
870 {
871    if (!SetActionNotification (hNotify, FALSE))
872       {
873       if (*pStatus)
874          *pStatus = ERROR_NOT_ENOUGH_MEMORY;
875       return FALSE;
876       }
877    return TRUE;
878 }
879
880
881       // AfsAdmSvrCallback_Action
882       // ...called by the server in the context of the CallbackHost() routine;
883       //    this routine is used to notify the client whenever an action is
884       //    initiated or completed.
885       //
886 extern "C" void AfsAdmSvrCallback_Action (LPASACTION pAction, BOOL fFinished)
887 {
888    NotifyActionListeners (pAction, fFinished);
889 }
890