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