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