Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / WINNT / afsadmsvr / TaAfsAdmSvr.cpp
1
2 #include <afs/param.h>
3 #include <afs/stds.h>
4
5 #include "TaAfsAdmSvrInternal.h"
6
7
8 /*
9  * ROUTINES ___________________________________________________________________
10  *
11  */
12
13       // AfsAdmSvr_Connect
14       // ...obtains a cookie to represent the calling process. The cookie should
15       //    be freed with AfsAdmSvr_Disconnect when the process disconnects.
16       //
17 int AfsAdmSvr_Connect (STRING szClientAddress, DWORD *pidClient, ULONG *pStatus)
18 {
19    // Make sure AfsClass initialized properly. If it's already init'd,
20    // this won't hurt at all.
21    //
22    ULONG status;
23    if (!AfsClass_Initialize (&status))
24       {
25       Print (TEXT("Denying client %s due to AfsClass initialization failure"), szClientAddress);
26       return FALSE_(status, pStatus);
27       }
28
29    // Find a free CLIENTINFO structure for this caller
30    //
31    if (!AfsAdmSvr_AttachClient (szClientAddress, pidClient, pStatus))
32       return FALSE;
33
34    Print (TEXT("Connected to client %s (ID 0x%08lX)"), AfsAdmSvr_GetClientName (*pidClient), *pidClient);
35
36    return TRUE;
37 }
38
39
40       // AfsAdmSvr_Ping
41       // ...reminds the admin server that the specified client is still around.
42       //    this call should be made at least every csecAFSADMSVR_CLIENT_PING
43       //    seconds, lest the admin server think you've disconnected. (The
44       //    client library TaAfsAdmSvrClient.lib automatically handles this.)
45       //
46 int AfsAdmSvr_Ping (DWORD idClient, ULONG *pStatus)
47 {
48    AfsAdmSvr_Enter();
49
50    if (!AfsAdmSvr_fIsValidClient (idClient))
51       return Leave_FALSE_(ERROR_INVALID_PARAMETER, pStatus);
52
53    AfsAdmSvr_PingClient (idClient);
54    AfsAdmSvr_Leave();
55    return TRUE;
56 }
57
58
59       // AfsAdmSvr_Disconnect
60       // ...releases and invalidates the cookie representing the calling process.
61       //
62 int AfsAdmSvr_Disconnect (DWORD idClient, ULONG *pStatus)
63 {
64    AfsAdmSvr_Enter();
65
66    // Make sure this is a valid client, and free its l.aClients[] entry if so.
67    //
68    if (!AfsAdmSvr_fIsValidClient (idClient))
69       return Leave_FALSE_(ERROR_INVALID_PARAMETER, pStatus);
70
71    Print (TEXT("Disconnected from client %s (ID 0x%08lX)"), AfsAdmSvr_GetClientName (idClient), idClient);
72
73    AfsAdmSvr_DetachClient (idClient);
74    AfsAdmSvr_Leave();
75    return TRUE;
76 }
77
78
79       // AfsAdmSvr_CrackCredentials
80       // ...queries the specified AFS credentials token for its cell, user
81       //    and expiration date.
82       //
83 int AfsAdmSvr_CrackCredentials (DWORD idClient, DWORD hCreds, STRING pszCell, STRING pszUser, SYSTEMTIME *pstExpiration, ULONG *pStatus)
84 {
85    ULONG status;
86    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
87
88    if (!AfsAdmSvr_fIsValidClient (idClient))
89       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
90
91    Print (dlDETAIL, TEXT("Client 0x%08lX: CrackCredentials (0x%08lX)"), idClient, hCreds);
92
93    unsigned long dateExpirationQuery;
94    int fHasKasTokenQuery;
95    char szUser[ cchSTRING ];
96    char szUser2[ cchSTRING ];
97    char szCell[ cchSTRING ];
98    char *pszCellQuery = (pszCell) ? (char *)pszCell : szCell;
99    char *pszUserQuery = (pszUser) ? (char *)pszUser : szUser;
100    if (!afsclient_TokenQuery ((PVOID)hCreds, &dateExpirationQuery, pszUserQuery, szUser2, pszCellQuery, &fHasKasTokenQuery, (afs_status_p)&status))
101       return FALSE_(status, pStatus, iOp);
102
103    if (pstExpiration)
104       AfsAppLib_UnixTimeToSystemTime (pstExpiration, dateExpirationQuery);
105
106    AfsAdmSvr_EndOperation (iOp);
107    return TRUE;
108 }
109
110
111       // AfsAdmSvr_GetCredentials
112       // ...queries the user's current AFS credentials for the specified cell
113       //    if the user already has credentials in the cell, returns a nonzero
114       //    token {hCreds}, suitable for use in AfsAdmSvr_OpenCell().
115       //
116 DWORD AfsAdmSvr_GetCredentials (DWORD idClient, STRING pszCell, ULONG *pStatus)
117 {
118    ULONG status;
119    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
120
121    if (!AfsAdmSvr_fIsValidClient (idClient))
122       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
123
124    Print (dlDETAIL, TEXT("Client 0x%08lX: GetCredentials (%s)"), idClient, pszCell);
125
126    const char *pszCellTest = (pszCell && *pszCell) ? (const char *)pszCell : NULL;
127
128    PVOID hCreds = NULL;
129    if (!afsclient_TokenGetExisting (pszCellTest, &hCreds, (afs_status_p)&status))
130       return FALSE_(status, pStatus, iOp);
131
132    AfsAdmSvr_EndOperation (iOp);
133    return (DWORD)hCreds;
134 }
135
136
137       // AfsAdmSvr_SetCredentials
138       // ...obtains new AFS credentials within the administrative server process
139       //    on behalf of the specified user. if successful, returns a nonzero
140       //    token {hCreds}, suitable for use in AfsAdmSvr_OpenCell().
141       //
142 DWORD AfsAdmSvr_SetCredentials (DWORD idClient, STRING pszCell, STRING pszUser, STRING pszPassword, ULONG *pStatus)
143 {
144    ULONG status;
145    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
146
147    Print (dlDETAIL, TEXT("Client 0x%08lX: SetCredentials (%s,%s)"), idClient, pszCell, pszUser);
148
149    if (!AfsAdmSvr_fIsValidClient (idClient))
150       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
151
152    const char *pszCellSet = (pszCell && *pszCell) ? (const char *)pszCell : NULL;
153
154    PVOID hCreds;
155    if (!afsclient_TokenGetNew (pszCellSet, (const char *)pszUser, (const char *)pszPassword, &hCreds, (afs_status_p)&status))
156       return FALSE_(status,pStatus,iOp);
157
158    AfsAdmSvr_EndOperation (iOp);
159    return (DWORD)hCreds;
160 }
161
162
163       // AfsAdmSvr_PushCredentials
164       // ...requests that the specified AFS credentials be used hereafter
165       //    when manipulating the specified cell. You should follow this
166       //    call with a Refresh request if necessary.
167       //
168 int AfsAdmSvr_PushCredentials (DWORD idClient, DWORD hCreds, ASID idCell, ULONG *pStatus)
169 {
170    ULONG status;
171    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
172
173    Print (dlDETAIL, TEXT("Client 0x%08lX: PushCredentials (hCreds=0x%08lX, idCell=0x%08lX)"), idClient, hCreds, idCell);
174
175    if (!AfsAdmSvr_fIsValidClient (idClient))
176       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
177
178    if (GetAsidType (idCell) != itCELL)
179       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
180
181    LPCELL lpCell;
182    if ((lpCell = ((LPIDENT)idCell)->OpenCell (&status)) == NULL)
183       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
184
185    lpCell->SetCurrentCredentials ((PVOID)hCreds);
186    lpCell->Close();
187
188    AfsAdmSvr_EndOperation (iOp);
189    return TRUE;
190 }
191
192
193       // AfsAdmSvr_GetLocalCell
194       // ...obtains the name of the primary cell used by the admin server
195       //
196 int AfsAdmSvr_GetLocalCell (DWORD idClient, STRING pszCellName, ULONG *pStatus)
197 {
198    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
199
200    Print (dlDETAIL, TEXT("Client 0x%08lX: GetLocalCell"), idClient);
201
202    if (!AfsAdmSvr_fIsValidClient (idClient))
203       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
204
205    if (!CELL::GetDefaultCell (pszCellName, pStatus))
206       {
207       AfsAdmSvr_EndOperation (iOp);
208       return FALSE;
209       }
210
211    AfsAdmSvr_EndOperation (iOp);
212    return TRUE;
213 }
214
215
216       // AfsAdmSvr_ErrorCodeTranslate
217       // ...translates an error code into an English string
218       //
219 int AfsAdmSvr_ErrorCodeTranslate (DWORD idClient, ULONG code, LANGID idLanguage, STRING pszErrorText, ULONG *pStatus)
220 {
221    if (!AfsAppLib_TranslateError (pszErrorText, code, idLanguage))
222       return FALSE_(ERROR_INVALID_PARAMETER,pStatus);
223
224    LPTSTR pch;
225    if ((pch = (LPTSTR)lstrrchr (pszErrorText, TEXT('('))) != NULL)
226       *pch = TEXT('\0');
227    while (lstrlen(pszErrorText) && pszErrorText[ lstrlen(pszErrorText)-1 ] == TEXT(' '))
228       pszErrorText[ lstrlen(pszErrorText)-1 ] = TEXT('\0');
229    return TRUE;
230 }
231
232
233       // AfsAdmSvr_GetAction
234       // ...returns information about a particular operation in progress.
235       //
236 int AfsAdmSvr_GetAction (DWORD idClient, DWORD idAction, LPASACTION pAction, ULONG *pStatus)
237 {
238    Print (dlDETAIL, TEXT("Client 0x%08lX: GetAction (idAction=0x%08lX)"), idClient, idAction);
239
240    if (!AfsAdmSvr_fIsValidClient (idClient))
241       return FALSE_(ERROR_INVALID_PARAMETER,pStatus);
242
243    if (!AfsAdmSvr_GetOperation (idAction, pAction))
244       return FALSE_(ERROR_INVALID_PARAMETER,pStatus);
245
246    Print (dlERROR, TEXT("Client 0x%08lX: GetAction succeeded"));
247    return TRUE;
248 }
249
250
251       // AfsAdmSvr_GetActions
252       // ...returns a list of operations in progress. The list returned can
253       //    be constrained to only including those operations initiated by
254       //    a particular client and/or performed in a particular cell.
255       //
256 int AfsAdmSvr_GetActions (DWORD idClient, DWORD idClientSearch, ASID idCellSearch, LPASACTIONLIST *ppList, ULONG *pStatus)
257 {
258    Print (dlDETAIL, TEXT("Client 0x%08lX: GetActions (idClientSearch=0x%08lX, idCellSearch=0x%08lX)"), idClient, idClientSearch, idCellSearch);
259
260    if (!AfsAdmSvr_fIsValidClient (idClient))
261       return FALSE_(ERROR_INVALID_PARAMETER,pStatus);
262
263    if ((*ppList = AfsAdmSvr_GetOperations (idClientSearch, idCellSearch)) == NULL)
264       {
265       Print (dlERROR, TEXT("Client 0x%08lX: GetActions failed"), idClient);
266       return FALSE_(ERROR_NOT_ENOUGH_MEMORY,pStatus);
267       }
268
269    Print (dlERROR, TEXT("Client 0x%08lX: GetActions succeeded; %ld actions"), idClient, (*ppList) ? (*ppList)->cEntries : 0);
270    return TRUE;
271 }
272
273
274       // AfsAdmSvr_OpenCell
275       // ...opens a cell for administration.
276       //
277 int AfsAdmSvr_OpenCell (DWORD idClient, DWORD hCreds, STRING pszCellName, DWORD dwScopeFlags, ASID *pidCell, ULONG *pStatus)
278 {
279    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
280
281    if (!AfsAdmSvr_fIsValidClient (idClient))
282       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
283
284    Print (dlDETAIL, TEXT("Client 0x%08lX: OpenCell"), idClient);
285
286    AfsAdmSvr_AddToMinScope (dwScopeFlags);
287
288    LPIDENT lpiCell;
289    if ((lpiCell = CELL::OpenCell ((LPTSTR)pszCellName, (PVOID)hCreds, pStatus)) == NULL)
290       {
291       AfsAdmSvr_EndOperation (iOp);
292       return FALSE;
293       }
294
295    Print (dlDETAIL, TEXT("Client 0x%08lX: OpenCell succeeded (idCell=0x%08lX)"), idClient, (DWORD)lpiCell);
296
297    *pidCell = (ASID)lpiCell;
298    AfsAdmSvr_EndOperation (iOp);
299    return TRUE;
300 }
301
302
303       // AfsAdmSvr_CloseCell
304       // ...used by client to open a cell for administration.
305       //
306 int AfsAdmSvr_CloseCell (DWORD idClient, ASID idCell, ULONG *pStatus)
307 {
308    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
309
310    Print (dlDETAIL, TEXT("Client 0x%08lX: CloseCell (idCell=0x%08lX)"), idClient, idCell);
311
312    if (!AfsAdmSvr_fIsValidClient (idClient))
313       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
314
315    if (GetAsidType (idCell) != itCELL)
316       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
317
318    CELL::CloseCell ((LPIDENT)idCell);
319
320    AfsAdmSvr_EndOperation (iOp);
321    return TRUE;
322 }
323
324
325       // AfsAdmSvr_FindObject
326       // AfsAdmSvr_FindObjects
327       // ...used to search through all objects in the cell, obtaining a list
328       //    of those which match the specified criteria. For FindObjects, the
329       //    {*ppList} parameter will be filled in with an allocated list of
330       //    ASIDs, and should be freed using the AfsAdmSvr_FreeAsidList()
331       //    routine (clients using the TaAfsAdmSvrClient.lib library should
332       //    call asc_AsidListFree(), which is a wrapper for that routine).
333       //    The _FindObject routine can be used to find exactly one object--
334       //    for instance, finding the ASID for a particular user or volume--
335       //    while the _FindObjects routine returns a list of all objects
336       //    which match the specified criteria--all volumes on a partition,
337       //    or all users named "b*" within a cell.
338       //
339 int AfsAdmSvr_FindObject (DWORD idClient, ASID idSearchScope, ASOBJTYPE ObjectType, AFSADMSVR_SEARCH_REFRESH SearchRefresh, STRING szName, ASID *pidObject, ULONG *pStatus)
340 {
341    BOOL rc = TRUE;
342    ULONG status = 0;
343
344    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
345
346    Print (dlDETAIL, TEXT("Client 0x%08lX: FindObject (scope=0x%08lX, type=%lu, name='%s')"), idClient, idSearchScope, ObjectType, szName);
347
348    if (!AfsAdmSvr_fIsValidClient (idClient))
349       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
350
351    if (GetAsidType (idSearchScope) == itUNUSED)
352       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
353
354    // We've got a special case here: if possible, we don't want to have to
355    // refresh the contents of the entire cell. So if the client is looking
356    // for a user or group, we can just try to grab that object by its name;
357    // afsclass supports an interface for just this case.
358    //
359    switch (ObjectType)
360       {
361       case TYPE_USER:
362          rc = AfsAdmSvr_Search_OneUser (pidObject, idSearchScope, szName, &status);
363          break;
364
365       case TYPE_GROUP:
366          rc = AfsAdmSvr_Search_OneGroup (pidObject, idSearchScope, szName, &status);
367          break;
368
369       default:
370          // We'll have to do the search the hard way. First
371          // see if we need to refresh this cell/server.
372          //
373          if (!AfsAdmSvr_SearchRefresh (idSearchScope, ObjectType, SearchRefresh, &status))
374             return FALSE_(status,pStatus,iOp);
375
376          // Look for the specified object.
377          //
378          switch (GetAsidType (idSearchScope))
379             {
380             case itCELL:
381                if (ObjectType == TYPE_SERVER)
382                   rc = AfsAdmSvr_Search_ServerInCell (pidObject, idSearchScope, szName, &status);
383                else if (ObjectType == TYPE_SERVICE)
384                   rc = AfsAdmSvr_Search_ServiceInCell (pidObject, idSearchScope, szName, &status);
385                else if (ObjectType == TYPE_PARTITION)
386                   rc = AfsAdmSvr_Search_PartitionInCell (pidObject, idSearchScope, szName, &status);
387                else if (ObjectType == TYPE_VOLUME)
388                   rc = AfsAdmSvr_Search_VolumeInCell (pidObject, idSearchScope, szName, &status);
389                else if (ObjectType == TYPE_USER)
390                   rc = AfsAdmSvr_Search_UserInCell (pidObject, idSearchScope, szName, &status);
391                else if (ObjectType == TYPE_GROUP)
392                   rc = AfsAdmSvr_Search_GroupInCell (pidObject, idSearchScope, szName, &status);
393                else
394                   {
395                   rc = FALSE;
396                   status = ERROR_INVALID_PARAMETER;
397                   }
398                break;
399
400             case itSERVER:
401                if (ObjectType == TYPE_SERVICE)
402                   rc = AfsAdmSvr_Search_ServiceInServer (pidObject, idSearchScope, szName, &status);
403                else if (ObjectType == TYPE_PARTITION)
404                   rc = AfsAdmSvr_Search_PartitionInServer (pidObject, idSearchScope, szName, &status);
405                else if (ObjectType == TYPE_VOLUME)
406                   rc = AfsAdmSvr_Search_VolumeInServer (pidObject, idSearchScope, szName, &status);
407                else
408                   {
409                   rc = FALSE;
410                   status = ERROR_INVALID_PARAMETER;
411                   }
412                break;
413
414             case itAGGREGATE:
415                if (ObjectType == TYPE_VOLUME)
416                   rc = AfsAdmSvr_Search_VolumeInPartition (pidObject, idSearchScope, szName, &status);
417                else
418                   {
419                   rc = FALSE;
420                   status = ERROR_INVALID_PARAMETER;
421                   }
422                break;
423             }
424          break;
425       }
426
427    if (!rc && pStatus)
428       *pStatus = status;
429
430    if (!rc)
431       Print (dlERROR, TEXT("Client 0x%08lX: FindObject failed (status=0x%08lX)"), idClient, status);
432    else // (rc)
433       Print (dlDETAIL, TEXT("Client 0x%08lX: FindObject succeeded; returning idObject=0x%08lX"), idClient, *pidObject);
434
435    AfsAdmSvr_EndOperation (iOp);
436    return rc;
437 }
438
439
440 int AfsAdmSvr_FindObjects (DWORD idClient, ASID idSearchScope, ASOBJTYPE ObjectType, AFSADMSVR_SEARCH_REFRESH SearchRefresh, STRING szPattern, LPAFSADMSVR_SEARCH_PARAMS pSearchParams, LPASIDLIST *ppList, ULONG *pStatus)
441 {
442    BOOL rc = TRUE;
443    ULONG status = 0;
444
445    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
446
447    Print (dlDETAIL, TEXT("Client 0x%08lX: FindObjects (scope=0x%08lX, type=%lu, pat='%s')"), idClient, idSearchScope, ObjectType, szPattern);
448
449    if (!AfsAdmSvr_fIsValidClient (idClient))
450       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
451
452    if (GetAsidType (idSearchScope) == itUNUSED)
453       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
454
455    // First see if we need to refresh this cell/server
456    //
457    if (!AfsAdmSvr_SearchRefresh (idSearchScope, ObjectType, SearchRefresh, &status))
458       return FALSE_(status,pStatus,iOp);
459
460    // Prepare an ASIDLIST, and call whatever subroutine is necessary to
461    // perform the actual search.
462    //
463    if ((*ppList = AfsAdmSvr_CreateAsidList()) == NULL)
464       return FALSE_(ERROR_NOT_ENOUGH_MEMORY,pStatus,iOp);
465
466    LPTSTR pszPattern = (szPattern && szPattern[0]) ? (LPTSTR)szPattern : NULL;
467
468    switch (GetAsidType (idSearchScope))
469       {
470       case itCELL:
471          if (ObjectType == TYPE_ANY)
472             rc = AfsAdmSvr_Search_AllInCell (ppList, idSearchScope, pszPattern, &status);
473          else if (ObjectType == TYPE_SERVER)
474             rc = AfsAdmSvr_Search_ServersInCell (ppList, idSearchScope, pszPattern, &status);
475          else if (ObjectType == TYPE_SERVICE)
476             rc = AfsAdmSvr_Search_ServicesInCell (ppList, idSearchScope, pszPattern, &status);
477          else if (ObjectType == TYPE_PARTITION)
478             rc = AfsAdmSvr_Search_PartitionsInCell (ppList, idSearchScope, pszPattern, &status);
479          else if (ObjectType == TYPE_VOLUME)
480             rc = AfsAdmSvr_Search_VolumesInCell (ppList, idSearchScope, pszPattern, &status);
481          else if (ObjectType == TYPE_USER)
482             rc = AfsAdmSvr_Search_UsersInCell (ppList, idSearchScope, pszPattern, &status);
483          else if (ObjectType == TYPE_GROUP)
484             rc = AfsAdmSvr_Search_GroupsInCell (ppList, idSearchScope, pszPattern, &status);
485          else
486             {
487             rc = FALSE;
488             status = ERROR_INVALID_PARAMETER;
489             }
490          break;
491
492       case itSERVER:
493          if (ObjectType == TYPE_ANY)
494             rc = AfsAdmSvr_Search_AllInServer (ppList, idSearchScope, pszPattern, &status);
495          else if (ObjectType == TYPE_SERVICE)
496             rc = AfsAdmSvr_Search_ServicesInServer (ppList, idSearchScope, pszPattern, &status);
497          else if (ObjectType == TYPE_PARTITION)
498             rc = AfsAdmSvr_Search_PartitionsInServer (ppList, idSearchScope, pszPattern, &status);
499          else if (ObjectType == TYPE_VOLUME)
500             rc = AfsAdmSvr_Search_VolumesInServer (ppList, idSearchScope, pszPattern, &status);
501          else
502             {
503             rc = FALSE;
504             status = ERROR_INVALID_PARAMETER;
505             }
506          break;
507
508       case itAGGREGATE:
509          if (ObjectType == TYPE_ANY)
510             rc = AfsAdmSvr_Search_VolumesInPartition (ppList, idSearchScope, pszPattern, &status);
511          else if (ObjectType == TYPE_VOLUME)
512             rc = AfsAdmSvr_Search_VolumesInPartition (ppList, idSearchScope, pszPattern, &status);
513          else
514             {
515             rc = FALSE;
516             status = ERROR_INVALID_PARAMETER;
517             }
518          break;
519       }
520
521    if (rc && (*ppList) && (pSearchParams))
522       AfsAdmSvr_Search_Advanced (ppList, pSearchParams);
523
524    if (!rc && (*ppList))
525       AfsAdmSvr_FreeAsidList (ppList);
526    if (!rc && pStatus)
527       *pStatus = status;
528
529    if (!rc)
530       Print (dlERROR, TEXT("Client 0x%08lX: FindObjects failed (status=0x%08lX)"), idClient, status);
531    else // (rc)
532       Print (dlDETAIL, TEXT("Client 0x%08lX: FindObjects succeeded; returning %lu item(s)"), idClient, (*ppList)->cEntries);
533
534    AfsAdmSvr_EndOperation (iOp);
535    return rc;
536 }
537
538
539       // AfsAdmSvr_GetObject
540       // AfsAdmSvr_GetObjects
541       // ...returns server-cached information about the specified object (or
542       //    objects).
543       //
544 int AfsAdmSvr_GetObject (DWORD idClient, AFSADMSVR_GET_TYPE GetType, AFSADMSVR_GET_LEVEL GetLevel, ASID idObject, DWORD verProperties, LPASOBJPROP pProperties, ULONG *pStatus)
545 {
546    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
547
548    Print (dlDETAIL2, TEXT("Client 0x%08lX: GetObject (Type=%lu, Level=%lu, idObject=0x%08lX, ver=%ld)"), idClient, (LONG)GetType, (LONG)GetLevel, idObject, verProperties);
549
550    memset (pProperties, 0x00, sizeof(ASOBJPROP));
551
552    if (!AfsAdmSvr_fIsValidClient (idClient))
553       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
554
555    LPASOBJPROP pCurrentProperties;
556    if ((pCurrentProperties = AfsAdmSvr_GetCurrentProperties (idObject, pStatus)) == NULL)
557       {
558       Print (dlERROR, TEXT("Client 0x%08lX: GetObject failed; no properties"), idClient, idObject);
559       AfsAdmSvr_EndOperation (iOp);
560       return FALSE;
561       }
562
563    // At this point pCurrentProperties may just be rudimentary properties.
564    // If the user has requested GET_ALL_DATA, we'll have to get full properties.
565    //
566    if ( (GetLevel == GET_ALL_DATA) && (pCurrentProperties->verProperties < verPROP_FIRST_SCAN) )
567       {
568       if (!AfsAdmSvr_ObtainFullProperties (pCurrentProperties, pStatus))
569          {
570          Print (dlERROR, TEXT("Client 0x%08lX: GetObject failed; no full properties"), idClient, idObject);
571          AfsAdmSvr_EndOperation (iOp);
572          return FALSE;
573          }
574       }
575
576    // Now determine if we need to return anything at all; if the user specified
577    // RETURN_IF_OUT_OF_DATE, it's possible that there's no need to do so.
578    //
579    if ((pCurrentProperties->verProperties > verProperties) || (GetType == RETURN_DATA_ALWAYS))
580       {
581       memcpy (pProperties, pCurrentProperties, sizeof(ASOBJPROP));
582       }
583
584    Print (dlDETAIL2, TEXT("Client 0x%08lX: GetObject succeeded (idObject=0x%08lX)"), idClient, idObject);
585    AfsAdmSvr_EndOperation (iOp);
586    return TRUE;
587 }
588
589
590 int AfsAdmSvr_GetObjects (DWORD idClient, AFSADMSVR_GET_TYPE GetType, AFSADMSVR_GET_LEVEL GetLevel, LPASIDLIST pListObjects, LPASOBJPROPLIST *ppListObjectProperties, ULONG *pStatus)
591 {
592    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
593
594    Print (dlDETAIL, TEXT("Client 0x%08lX: GetObjects (Type=%lu, Level=%lu, nObjects=%lu)"), idClient, (LONG)GetType, (LONG)GetLevel, (pListObjects) ? (pListObjects->cEntries) : 0);
595
596    if (!AfsAdmSvr_fIsValidClient (idClient))
597       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
598
599    *ppListObjectProperties = NULL;
600    for (size_t iObject = 0; iObject < pListObjects->cEntries; ++iObject)
601       {
602       ASOBJPROP ObjectProperties;
603
604       ULONG status;
605       if (AfsAdmSvr_GetObject (idClient, GetType, GetLevel, pListObjects->aEntries[ iObject ].idObject, pListObjects->aEntries[ iObject ].lParam, &ObjectProperties, &status))
606          {
607          if (ObjectProperties.idObject == pListObjects->aEntries[ iObject ].idObject)
608             {
609             if (!*ppListObjectProperties)
610                *ppListObjectProperties = AfsAdmSvr_CreateObjPropList();
611
612             if (*ppListObjectProperties)
613                AfsAdmSvr_AddToObjPropList (ppListObjectProperties, &ObjectProperties, 0);
614             }
615          }
616       }
617
618    Print (dlDETAIL, TEXT("Client 0x%08lX: GetObjects succeeded; returning %lu properties"), idClient, (*ppListObjectProperties) ? ((*ppListObjectProperties)->cEntries) : 0);
619    AfsAdmSvr_EndOperation (iOp);
620    return TRUE;
621 }
622
623
624       // AfsAdmSvr_RefreshObject
625       // AfsAdmSvr_RefreshObjects
626       // ...invalidates the server's cache of information about the specified
627       //    object or objects.
628       //
629 int AfsAdmSvr_RefreshObject (DWORD idClient, ASID idObject, ULONG *pStatus)
630 {
631    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
632
633    Print (dlDETAIL, TEXT("Client 0x%08lX: RefreshObject (idObject=0x%08lX)"), idClient, idObject);
634
635    if (!AfsAdmSvr_fIsValidClient (idClient))
636       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
637
638    if (!AfsAdmSvr_InvalidateObjectProperties (idObject, pStatus))
639       {
640       AfsAdmSvr_EndOperation (iOp);
641       return FALSE;
642       }
643
644    AfsAdmSvr_EndOperation (iOp);
645    return TRUE;
646 }
647
648
649 int AfsAdmSvr_RefreshObjects (DWORD idClient, LPASIDLIST pListObjects, ULONG *pStatus)
650 {
651    size_t iOp = AfsAdmSvr_BeginOperation (idClient);
652
653    Print (dlDETAIL, TEXT("Client 0x%08lX: RefreshObjects (nObjects=%lu)"), idClient, (pListObjects) ? (pListObjects->cEntries) : 0);
654
655    if (!AfsAdmSvr_fIsValidClient (idClient))
656       return FALSE_(ERROR_INVALID_PARAMETER,pStatus,iOp);
657
658    for (size_t iObject = 0; iObject < pListObjects->cEntries; ++iObject)
659       {
660       ULONG status;
661       AfsAdmSvr_RefreshObject (idClient, pListObjects->aEntries[ iObject ].idObject, &status);
662       }
663
664    AfsAdmSvr_EndOperation (iOp);
665    return TRUE;
666 }
667
668
669       // AfsAdmSvr_CallbackHost
670       // ...provides a context in which the server can issue callback functions
671       //    via the AfsAdmSvrCallBack_* routines, which the client must implement.
672       //    This routine will only return if the server is shut down. It should
673       //    be called on a dedicated thread by the client. (TaAfsAdmSvrClient.lib
674       //    automatically handles this.)
675       //
676 void AfsAdmSvr_CallbackHost (void)
677 {
678    AfsAdmSvr_CallbackManager();
679 }
680
681
682
683       // AfsAdmSvr_GetRandomKey
684       // ...returns a randomly-generated 8-byte encryption key
685       //
686 int AfsAdmSvr_GetRandomKey (DWORD idClient, ASID idCell, BYTE keyData[ ENCRYPTIONKEYLENGTH ], ULONG *pStatus)
687 {
688    if (!AfsAdmSvr_fIsValidClient (idClient))
689       return FALSE_(ERROR_INVALID_PARAMETER,pStatus);
690
691    return AfsClass_GetRandomKey ((LPIDENT)idCell, (LPENCRYPTIONKEY)keyData, pStatus);
692 }
693