ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sidcache.c
Go to the documentation of this file.
00001 /*
00002  * ReactOS Access Control List Editor
00003  * Copyright (C) 2004-2005 ReactOS Team
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 /* $Id: aclui.c 19715 2005-11-28 01:10:49Z weiden $
00020  *
00021  * PROJECT:         ReactOS Access Control List Editor
00022  * FILE:            lib/aclui/sidcache.c
00023  * PURPOSE:         Access Control List Editor
00024  * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
00025  *
00026  * UPDATE HISTORY:
00027  *      12/10/2005  Created
00028  */
00029 #include <precomp.h>
00030 
00031 #define NDEBUG
00032 #include <debug.h>
00033 
00034 #define HandleToScm(Handle) (PSIDCACHEMGR)(Handle)
00035 #define ScmToHandle(Scm) (HANDLE)(Scm)
00036 
00037 typedef struct _SIDCACHEMGR
00038 {
00039     volatile LONG RefCount;
00040     LSA_HANDLE LsaHandle;
00041     CRITICAL_SECTION Lock;
00042     LIST_ENTRY QueueListHead;
00043     struct _SIDQUEUEENTRY *QueueLookingUp;
00044     LIST_ENTRY CacheListHead;
00045     HANDLE Heap;
00046     HANDLE LookupEvent;
00047     HANDLE LookupThread;
00048     WCHAR SystemName[1];
00049 } SIDCACHEMGR, *PSIDCACHEMGR;
00050 
00051 
00052 typedef struct _SIDCACHECALLBACKINFO
00053 {
00054     PSIDREQCOMPLETIONPROC CompletionProc;
00055     PVOID Context;
00056 } SIDCACHECALLBACKINFO, *PSIDCACHECALLBACKINFO;
00057 
00058 
00059 typedef struct _SIDQUEUEENTRY
00060 {
00061     LIST_ENTRY ListEntry;
00062     ULONG CallbackCount;
00063     PSIDCACHECALLBACKINFO Callbacks;
00064     /* the SID is appended to this structure */
00065 } SIDQUEUEENTRY, *PSIDQUEUEENTRY;
00066 
00067 
00068 typedef struct _SIDCACHEENTRY
00069 {
00070     LIST_ENTRY ListEntry;
00071     SID_NAME_USE SidNameUse;
00072     PWSTR AccountName;
00073     PWSTR DomainName;
00074     /* the SID and strings are appended to this structure */
00075 } SIDCACHEENTRY, *PSIDCACHEENTRY;
00076 
00077 
00078 static VOID
00079 FreeQueueEntry(IN PSIDCACHEMGR scm,
00080                IN PSIDQUEUEENTRY QueueEntry)
00081 {
00082     if (QueueEntry->ListEntry.Flink != NULL)
00083     {
00084         RemoveEntryList(&QueueEntry->ListEntry);
00085     }
00086 
00087     HeapFree(scm->Heap,
00088              0,
00089              QueueEntry->Callbacks);
00090 
00091     HeapFree(scm->Heap,
00092              0,
00093              QueueEntry);
00094 }
00095 
00096 
00097 static VOID
00098 FreeCacheEntry(IN PSIDCACHEMGR scm,
00099                IN PSIDCACHEENTRY CacheEntry)
00100 {
00101     RemoveEntryList(&CacheEntry->ListEntry);
00102 
00103     HeapFree(scm->Heap,
00104              0,
00105              CacheEntry);
00106 }
00107 
00108 
00109 static VOID
00110 CleanupSidCacheMgr(IN PSIDCACHEMGR scm)
00111 {
00112     LsaClose(scm->LsaHandle);
00113     CloseHandle(scm->LookupEvent);
00114     CloseHandle(scm->LookupThread);
00115 
00116     /* delete the queue */
00117     while (!IsListEmpty(&scm->QueueListHead))
00118     {
00119         PSIDQUEUEENTRY QueueEntry;
00120 
00121         QueueEntry = CONTAINING_RECORD(scm->QueueListHead.Flink,
00122                                        SIDQUEUEENTRY,
00123                                        ListEntry);
00124         FreeQueueEntry(scm,
00125                        QueueEntry);
00126     }
00127 
00128     /* delete the cache */
00129     while (!IsListEmpty(&scm->CacheListHead))
00130     {
00131         PSIDCACHEENTRY CacheEntry;
00132 
00133         CacheEntry = CONTAINING_RECORD(scm->CacheListHead.Flink,
00134                                        SIDCACHEENTRY,
00135                                        ListEntry);
00136         FreeCacheEntry(scm,
00137                        CacheEntry);
00138     }
00139 
00140     DeleteCriticalSection(&scm->Lock);
00141 }
00142 
00143 
00144 static PSIDCACHEMGR
00145 ReferenceSidCacheMgr(IN HANDLE SidCacheMgr)
00146 {
00147     PSIDCACHEMGR scm = HandleToScm(SidCacheMgr);
00148 
00149     if (InterlockedIncrement(&scm->RefCount) != 1)
00150     {
00151         return scm;
00152     }
00153 
00154     return NULL;
00155 }
00156 
00157 
00158 static VOID
00159 DereferenceSidCacheMgr(IN PSIDCACHEMGR scm)
00160 {
00161     if (InterlockedDecrement(&scm->RefCount) == 0)
00162     {
00163         /* Signal the lookup thread so it can terminate */
00164         SetEvent(scm->LookupEvent);
00165     }
00166 }
00167 
00168 
00169 static BOOL
00170 OpenLSAPolicyHandle(IN LPWSTR SystemName,
00171                     IN ACCESS_MASK DesiredAccess,
00172                     OUT PLSA_HANDLE PolicyHandle)
00173 {
00174     LSA_OBJECT_ATTRIBUTES LsaObjectAttributes = {0};
00175     LSA_UNICODE_STRING LsaSystemName, *psn;
00176     NTSTATUS Status;
00177 
00178     if (SystemName != NULL && SystemName[0] != L'\0')
00179     {
00180         LsaSystemName.Buffer = SystemName;
00181         LsaSystemName.Length = wcslen(SystemName) * sizeof(WCHAR);
00182         LsaSystemName.MaximumLength = LsaSystemName.Length + sizeof(WCHAR);
00183         psn = &LsaSystemName;
00184     }
00185     else
00186     {
00187         psn = NULL;
00188     }
00189 
00190     Status = LsaOpenPolicy(psn,
00191                            &LsaObjectAttributes,
00192                            DesiredAccess,
00193                            PolicyHandle);
00194     if (!NT_SUCCESS(Status))
00195     {
00196         SetLastError(LsaNtStatusToWinError(Status));
00197         return FALSE;
00198     }
00199 
00200     return TRUE;
00201 }
00202 
00203 
00204 static BOOL
00205 LookupSidInformation(IN PSIDCACHEMGR scm,
00206                      IN PSID pSid,
00207                      OUT PSIDREQRESULT *ReqResult)
00208 {
00209     PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain;
00210     PLSA_TRANSLATED_NAME Names;
00211     PLSA_TRUST_INFORMATION Domain;
00212     PLSA_UNICODE_STRING DomainName;
00213     SID_NAME_USE SidNameUse = SidTypeUnknown;
00214     PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo = NULL;
00215     NTSTATUS Status;
00216     DWORD SidLength, AccountNameSize, DomainNameSize = 0;
00217     PSIDREQRESULT ReqRet = NULL;
00218     BOOL Ret = FALSE;
00219 
00220     Status = LsaLookupSids(scm->LsaHandle,
00221                            1,
00222                            &pSid,
00223                            &ReferencedDomain,
00224                            &Names);
00225     if (NT_SUCCESS(Status))
00226     {
00227         SidLength = GetLengthSid(pSid);
00228         SidNameUse = Names->Use;
00229 
00230         if (ReferencedDomain != NULL &&
00231             Names->DomainIndex >= 0)
00232         {
00233             Domain = &ReferencedDomain->Domains[Names->DomainIndex];
00234             DomainName = &Domain->Name;
00235         }
00236         else
00237         {
00238             Domain = NULL;
00239             DomainName = NULL;
00240         }
00241 
00242         switch (SidNameUse)
00243         {
00244             case SidTypeAlias:
00245             {
00246                 if (Domain != NULL)
00247                 {
00248                     /* query the domain name for BUILTIN accounts */
00249                     Status = LsaQueryInformationPolicy(scm->LsaHandle,
00250                                                        PolicyAccountDomainInformation,
00251                                                        (PVOID*)&PolicyAccountDomainInfo);
00252                     if (NT_SUCCESS(Status))
00253                     {
00254                         DomainName = &PolicyAccountDomainInfo->DomainName;
00255 
00256                         /* make the user believe this is a group */
00257                         SidNameUse = (PolicyAccountDomainInfo != NULL ? SidTypeGroup : SidTypeUser);
00258                     }
00259                 }
00260                 break;
00261             }
00262 
00263             default:
00264             {
00265                 DPRINT("Unhandled SID type: 0x%x\n", Names->Use);
00266                 break;
00267             }
00268         }
00269 
00270         AccountNameSize = Names->Name.Length;
00271         if (DomainName != NULL)
00272         {
00273             DomainNameSize = DomainName->Length;
00274         }
00275 
00276         ReqRet = HeapAlloc(scm->Heap,
00277                            0,
00278                            sizeof(SIDREQRESULT) +
00279                                (((AccountNameSize + DomainNameSize) + 2) * sizeof(WCHAR)));
00280         if (ReqRet != NULL)
00281         {
00282             ReqRet->RefCount = 1;
00283             ReqRet->AccountName = (LPWSTR)(ReqRet + 1);
00284             ReqRet->DomainName = ReqRet->AccountName + (AccountNameSize / sizeof(WCHAR)) + 1;
00285 
00286             CopyMemory(ReqRet->AccountName,
00287                        Names->Name.Buffer,
00288                        Names->Name.Length);
00289 
00290             if (DomainName != NULL)
00291             {
00292                 CopyMemory(ReqRet->DomainName,
00293                            DomainName->Buffer,
00294                            DomainName->Length);
00295             }
00296 
00297             ReqRet->AccountName[AccountNameSize / sizeof(WCHAR)] = L'\0';
00298             ReqRet->DomainName[DomainNameSize / sizeof(WCHAR)] = L'\0';
00299 
00300             ReqRet->SidNameUse = SidNameUse;
00301         }
00302 
00303         if (PolicyAccountDomainInfo != NULL)
00304         {
00305             LsaFreeMemory(PolicyAccountDomainInfo);
00306         }
00307 
00308         LsaFreeMemory(ReferencedDomain);
00309         LsaFreeMemory(Names);
00310 
00311         Ret = TRUE;
00312     }
00313     else if (Status == STATUS_NONE_MAPPED)
00314     {
00315         Ret = TRUE;
00316     }
00317 
00318     if (Ret)
00319     {
00320         *ReqResult = ReqRet;
00321     }
00322 
00323     return Ret;
00324 }
00325 
00326 
00327 static BOOL
00328 FindSidInCache(IN PSIDCACHEMGR scm,
00329                IN PSID pSid,
00330                OUT PSIDREQRESULT *ReqResult)
00331 {
00332     PSIDCACHEENTRY CacheEntry;
00333     PLIST_ENTRY CurrentEntry;
00334     PSIDREQRESULT ReqRes;
00335     BOOL Ret = FALSE;
00336 
00337     /* NOTE: assumes the lists are locked! */
00338 
00339     CurrentEntry = &scm->CacheListHead;
00340     while (CurrentEntry != &scm->CacheListHead)
00341     {
00342         CacheEntry = CONTAINING_RECORD(CurrentEntry,
00343                                        SIDCACHEENTRY,
00344                                        ListEntry);
00345 
00346         if (EqualSid(pSid,
00347                      (PSID)(CacheEntry + 1)))
00348         {
00349             SIZE_T ReqResultSize;
00350             ULONG AccountNameLen, DomainNameLen;
00351 
00352             Ret = TRUE;
00353 
00354             AccountNameLen = wcslen(CacheEntry->AccountName);
00355             DomainNameLen = wcslen(CacheEntry->DomainName);
00356 
00357             ReqResultSize = sizeof(SIDREQRESULT) +
00358                                 (((AccountNameLen + 1) +
00359                                   (DomainNameLen + 1)) * sizeof(WCHAR));
00360 
00361             ReqRes = HeapAlloc(scm->Heap,
00362                                0,
00363                                ReqResultSize);
00364             if (ReqRes != NULL)
00365             {
00366                 PWSTR Buffer = (PWSTR)(ReqRes + 1);
00367 
00368                 ReqRes->RefCount = 1;
00369 
00370                 ReqRes->AccountName = Buffer;
00371                 wcscpy(ReqRes->AccountName,
00372                        CacheEntry->AccountName);
00373                 Buffer += AccountNameLen + 1;
00374 
00375                 ReqRes->DomainName = Buffer;
00376                 wcscpy(ReqRes->DomainName,
00377                        CacheEntry->DomainName);
00378             }
00379 
00380             /* return the result, even if we weren't unable to
00381                allocate enough memory! */
00382             *ReqResult = ReqRes;
00383             break;
00384         }
00385 
00386         CurrentEntry = CurrentEntry->Flink;
00387     }
00388 
00389     return Ret;
00390 }
00391 
00392 
00393 static VOID
00394 CacheLookupResults(IN PSIDCACHEMGR scm,
00395                    IN PSID pSid,
00396                    IN PSIDREQRESULT ReqResult)
00397 {
00398     PSIDCACHEENTRY CacheEntry;
00399     DWORD SidLen;
00400     SIZE_T AccountNameLen = 0;
00401     SIZE_T DomainNameLen = 0;
00402     SIZE_T CacheEntrySize = sizeof(SIDCACHEENTRY);
00403 
00404     /* NOTE: assumes the lists are locked! */
00405 
00406     SidLen = GetLengthSid(pSid);
00407     CacheEntrySize += SidLen;
00408 
00409     AccountNameLen = wcslen(ReqResult->AccountName);
00410     CacheEntrySize += (AccountNameLen + 1) * sizeof(WCHAR);
00411 
00412     DomainNameLen = wcslen(ReqResult->DomainName);
00413     CacheEntrySize += (wcslen(ReqResult->DomainName) + 1) * sizeof(WCHAR);
00414 
00415     CacheEntry = HeapAlloc(scm->Heap,
00416                            0,
00417                            CacheEntrySize);
00418     if (CacheEntry != NULL)
00419     {
00420         PWSTR lpBuf = (PWSTR)((ULONG_PTR)(CacheEntry + 1) + SidLen);
00421 
00422         CacheEntry->SidNameUse = ReqResult->SidNameUse;
00423 
00424         /* append the SID */
00425         CopySid(SidLen,
00426                 (PSID)(CacheEntry + 1),
00427                 pSid);
00428 
00429         /* append the strings */
00430         CacheEntry->AccountName = lpBuf;
00431         wcscpy(lpBuf,
00432                ReqResult->AccountName);
00433         lpBuf += AccountNameLen + 1;
00434 
00435         CacheEntry->DomainName = lpBuf;
00436         wcscpy(lpBuf,
00437                ReqResult->DomainName);
00438         lpBuf += DomainNameLen + 1;
00439 
00440         /* add the entry to the cache list */
00441         InsertTailList(&scm->CacheListHead,
00442                        &CacheEntry->ListEntry);
00443     }
00444 }
00445 
00446 
00447 static DWORD WINAPI
00448 LookupThreadProc(IN LPVOID lpParameter)
00449 {
00450     HMODULE hModule;
00451     PSIDCACHEMGR scm = (PSIDCACHEMGR)lpParameter;
00452 
00453     /* Reference the dll to avoid problems in case of accidental
00454        FreeLibrary calls... */
00455     if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
00456                             (LPCWSTR)hDllInstance,
00457                             &hModule))
00458     {
00459         hModule = NULL;
00460     }
00461 
00462     while (scm->RefCount != 0)
00463     {
00464         PSIDQUEUEENTRY QueueEntry = NULL;
00465 
00466         EnterCriticalSection(&scm->Lock);
00467 
00468         /* get the first item of the queue */
00469         if (scm->QueueListHead.Flink != &scm->QueueListHead)
00470         {
00471             QueueEntry = CONTAINING_RECORD(scm->QueueListHead.Flink,
00472                                            SIDQUEUEENTRY,
00473                                            ListEntry);
00474             RemoveEntryList(&QueueEntry->ListEntry);
00475             QueueEntry->ListEntry.Flink = NULL;
00476         }
00477         else
00478         {
00479             LeaveCriticalSection(&scm->Lock);
00480 
00481             /* wait for the next asynchronous lookup queued */
00482             WaitForSingleObject(scm->LookupEvent,
00483                                 INFINITE);
00484             continue;
00485         }
00486 
00487         scm->QueueLookingUp = QueueEntry;
00488 
00489         LeaveCriticalSection(&scm->Lock);
00490 
00491         if (QueueEntry != NULL)
00492         {
00493             PSIDREQRESULT ReqResult, FoundReqResult;
00494             PSID pSid = (PSID)(QueueEntry + 1);
00495 
00496             /* lookup the SID information */
00497             if (!LookupSidInformation(scm,
00498                                       pSid,
00499                                       &ReqResult))
00500             {
00501                 ReqResult = NULL;
00502             }
00503 
00504             EnterCriticalSection(&scm->Lock);
00505 
00506             /* see if the SID was added to the cache in the meanwhile */
00507             if (!FindSidInCache(scm,
00508                                 pSid,
00509                                 &FoundReqResult))
00510             {
00511                 if (ReqResult != NULL)
00512                 {
00513                     /* cache the results */
00514                     CacheLookupResults(scm,
00515                                        pSid,
00516                                        ReqResult);
00517                 }
00518             }
00519             else
00520             {
00521                 if (ReqResult != NULL)
00522                 {
00523                     /* free the information of our lookup and use the cached
00524                        information*/
00525                     DereferenceSidReqResult(scm,
00526                                             ReqResult);
00527                 }
00528 
00529                 ReqResult = FoundReqResult;
00530             }
00531 
00532             /* notify the callers unless the lookup was cancelled */
00533             if (scm->QueueLookingUp != NULL)
00534             {
00535                 ULONG i = 0;
00536 
00537                 while (scm->QueueLookingUp != NULL &&
00538                        i < QueueEntry->CallbackCount)
00539                 {
00540                     PVOID Context;
00541                     PSIDREQCOMPLETIONPROC CompletionProc;
00542 
00543                     Context = QueueEntry->Callbacks[i].Context;
00544                     CompletionProc = QueueEntry->Callbacks[i].CompletionProc;
00545 
00546                     LeaveCriticalSection(&scm->Lock);
00547 
00548                     /* call the completion proc without holding the lock! */
00549                     CompletionProc(ScmToHandle(scm),
00550                                    pSid,
00551                                    ReqResult,
00552                                    Context);
00553 
00554                     EnterCriticalSection(&scm->Lock);
00555 
00556                     i++;
00557                 }
00558 
00559                 scm->QueueLookingUp = NULL;
00560             }
00561 
00562             LeaveCriticalSection(&scm->Lock);
00563 
00564             /* free the queue item */
00565             FreeQueueEntry(scm,
00566                            QueueEntry);
00567         }
00568     }
00569 
00570     CleanupSidCacheMgr(scm);
00571 
00572     HeapFree(scm->Heap,
00573              0,
00574              scm);
00575 
00576     if (hModule != NULL)
00577     {
00578         /* dereference the library and exit */
00579         FreeLibraryAndExitThread(hModule,
00580                                  0);
00581     }
00582 
00583     return 0;
00584 }
00585 
00586 
00587 
00588 HANDLE
00589 CreateSidCacheMgr(IN HANDLE Heap,
00590                   IN LPCWSTR SystemName)
00591 {
00592     PSIDCACHEMGR scm;
00593 
00594     if (SystemName == NULL)
00595         SystemName = L"";
00596 
00597     scm = HeapAlloc(Heap,
00598                     0,
00599                     FIELD_OFFSET(SIDCACHEMGR,
00600                                  SystemName[wcslen(SystemName) + 1]));
00601     if (scm != NULL)
00602     {
00603         /* zero the static part of the structure */
00604         ZeroMemory(scm,
00605                    FIELD_OFFSET(SIDCACHEMGR,
00606                                 SystemName));
00607 
00608         scm->RefCount = 1;
00609         scm->Heap = Heap;
00610 
00611         wcscpy(scm->SystemName,
00612                SystemName);
00613 
00614         InitializeCriticalSection(&scm->Lock);
00615         InitializeListHead(&scm->QueueListHead);
00616         InitializeListHead(&scm->CacheListHead);
00617 
00618         scm->LookupEvent = CreateEvent(NULL,
00619                                        FALSE,
00620                                        FALSE,
00621                                        NULL);
00622         if (scm->LookupEvent == NULL)
00623         {
00624             goto Cleanup;
00625         }
00626 
00627         if (!OpenLSAPolicyHandle(scm->SystemName,
00628                                  POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
00629                                  &scm->LsaHandle))
00630         {
00631             goto Cleanup;
00632         }
00633 
00634         scm->LookupThread = CreateThread(NULL,
00635                                          0,
00636                                          LookupThreadProc,
00637                                          scm,
00638                                          0,
00639                                          NULL);
00640         if (scm->LookupThread == NULL)
00641         {
00642 Cleanup:
00643             if (scm->LookupEvent != NULL)
00644             {
00645                 CloseHandle(scm->LookupEvent);
00646             }
00647 
00648             if (scm->LsaHandle != NULL)
00649             {
00650                 LsaClose(scm->LsaHandle);
00651             }
00652 
00653             HeapFree(Heap,
00654                      0,
00655                      scm);
00656             scm = NULL;
00657         }
00658     }
00659     else
00660     {
00661         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00662     }
00663 
00664     return (HANDLE)scm;
00665 }
00666 
00667 
00668 VOID
00669 DestroySidCacheMgr(IN HANDLE SidCacheMgr)
00670 {
00671     PSIDCACHEMGR scm = HandleToScm(SidCacheMgr);
00672 
00673     if (scm != NULL)
00674     {
00675         /* remove the keep-alive reference */
00676         DereferenceSidCacheMgr(scm);
00677     }
00678 }
00679 
00680 
00681 static BOOL
00682 QueueSidLookup(IN PSIDCACHEMGR scm,
00683                IN PSID pSid,
00684                IN PSIDREQCOMPLETIONPROC CompletionProc,
00685                IN PVOID Context)
00686 {
00687     PLIST_ENTRY CurrentEntry;
00688     PSIDQUEUEENTRY QueueEntry, FoundEntry = NULL;
00689     BOOL Ret = FALSE;
00690 
00691     /* NOTE: assumes the lists are locked! */
00692 
00693     if (scm->QueueLookingUp != NULL &&
00694         EqualSid(pSid,
00695                  (PSID)(scm->QueueLookingUp + 1)))
00696     {
00697         FoundEntry = scm->QueueLookingUp;
00698     }
00699     else
00700     {
00701         CurrentEntry = &scm->QueueListHead;
00702         while (CurrentEntry != &scm->QueueListHead)
00703         {
00704             QueueEntry = CONTAINING_RECORD(CurrentEntry,
00705                                            SIDQUEUEENTRY,
00706                                            ListEntry);
00707 
00708             if (EqualSid(pSid,
00709                          (PSID)(QueueEntry + 1)))
00710             {
00711                 FoundEntry = QueueEntry;
00712                 break;
00713             }
00714 
00715             CurrentEntry = CurrentEntry->Flink;
00716         }
00717     }
00718 
00719     if (FoundEntry == NULL)
00720     {
00721         DWORD SidLength = GetLengthSid(pSid);
00722 
00723         FoundEntry = HeapAlloc(scm->Heap,
00724                                0,
00725                                sizeof(SIDQUEUEENTRY) + SidLength);
00726         if (FoundEntry != NULL)
00727         {
00728             CopySid(SidLength,
00729                     (PSID)(FoundEntry + 1),
00730                     pSid);
00731 
00732             FoundEntry->CallbackCount = 1;
00733             FoundEntry->Callbacks = HeapAlloc(scm->Heap,
00734                                               0,
00735                                               sizeof(SIDCACHECALLBACKINFO));
00736 
00737             if (FoundEntry->Callbacks != NULL)
00738             {
00739                 FoundEntry->Callbacks[0].CompletionProc = CompletionProc;
00740                 FoundEntry->Callbacks[0].Context = Context;
00741 
00742                 /* append it to the queue */
00743                 InsertTailList(&scm->QueueListHead,
00744                                &FoundEntry->ListEntry);
00745 
00746                 /* signal the lookup event */
00747                 SetEvent(scm->LookupEvent);
00748 
00749                 Ret = TRUE;
00750             }
00751             else
00752             {
00753                 /* unable to queue it because we couldn't allocate the callbacks
00754                    array, free the memory and return */
00755                 HeapFree(scm->Heap,
00756                          0,
00757                          FoundEntry);
00758             }
00759         }
00760     }
00761     else
00762     {
00763         PSIDCACHECALLBACKINFO Sidccb;
00764 
00765         /* add the callback */
00766         Sidccb = HeapReAlloc(scm->Heap,
00767                              0,
00768                              FoundEntry->Callbacks,
00769                              (FoundEntry->CallbackCount + 1) * sizeof(SIDCACHECALLBACKINFO));
00770         if (Sidccb != NULL)
00771         {
00772             FoundEntry->Callbacks = Sidccb;
00773             FoundEntry->Callbacks[FoundEntry->CallbackCount].CompletionProc = CompletionProc;
00774             FoundEntry->Callbacks[FoundEntry->CallbackCount++].Context = Context;
00775 
00776             Ret = TRUE;
00777         }
00778     }
00779 
00780     return Ret;
00781 }
00782 
00783 
00784 VOID
00785 DequeueSidLookup(IN HANDLE SidCacheMgr,
00786                  IN PSID pSid)
00787 {
00788     PLIST_ENTRY CurrentEntry;
00789     PSIDQUEUEENTRY QueueEntry;
00790     PSIDCACHEMGR scm;
00791 
00792     scm = ReferenceSidCacheMgr(SidCacheMgr);
00793     if (scm != NULL)
00794     {
00795         EnterCriticalSection(&scm->Lock);
00796 
00797         if (scm->QueueLookingUp != NULL &&
00798             EqualSid(pSid,
00799                      (PSID)(scm->QueueLookingUp + 1)))
00800         {
00801             /* don't free the queue lookup item! this will be
00802                done in the lookup thread */
00803             scm->QueueLookingUp = NULL;
00804         }
00805         else
00806         {
00807             CurrentEntry = &scm->QueueListHead;
00808             while (CurrentEntry != &scm->QueueListHead)
00809             {
00810                 QueueEntry = CONTAINING_RECORD(CurrentEntry,
00811                                                SIDQUEUEENTRY,
00812                                                ListEntry);
00813 
00814                 if (EqualSid(pSid,
00815                              (PSID)(QueueEntry + 1)))
00816                 {
00817                     FreeQueueEntry(scm,
00818                                    QueueEntry);
00819                     break;
00820                 }
00821 
00822                 CurrentEntry = CurrentEntry->Flink;
00823             }
00824         }
00825 
00826         LeaveCriticalSection(&scm->Lock);
00827 
00828         DereferenceSidCacheMgr(scm);
00829     }
00830 }
00831 
00832 
00833 VOID
00834 ReferenceSidReqResult(IN HANDLE SidCacheMgr,
00835                       IN PSIDREQRESULT ReqResult)
00836 {
00837     PSIDCACHEMGR scm;
00838 
00839     scm = ReferenceSidCacheMgr(SidCacheMgr);
00840     if (scm != NULL)
00841     {
00842         InterlockedIncrement(&ReqResult->RefCount);
00843 
00844         DereferenceSidCacheMgr(scm);
00845     }
00846 }
00847 
00848 
00849 VOID
00850 DereferenceSidReqResult(IN HANDLE SidCacheMgr,
00851                         IN PSIDREQRESULT ReqResult)
00852 {
00853     PSIDCACHEMGR scm;
00854 
00855     scm = ReferenceSidCacheMgr(SidCacheMgr);
00856     if (scm != NULL)
00857     {
00858         if (InterlockedDecrement(&ReqResult->RefCount) == 0)
00859         {
00860             HeapFree(scm->Heap,
00861                      0,
00862                      ReqResult);
00863         }
00864 
00865         DereferenceSidCacheMgr(scm);
00866     }
00867 }
00868 
00869 
00870 BOOL
00871 LookupSidCache(IN HANDLE SidCacheMgr,
00872                IN PSID pSid,
00873                IN PSIDREQCOMPLETIONPROC CompletionProc,
00874                IN PVOID Context)
00875 {
00876     BOOL Found = FALSE;
00877     PSIDREQRESULT ReqResult = NULL;
00878     PSIDCACHEMGR scm;
00879 
00880     scm = ReferenceSidCacheMgr(SidCacheMgr);
00881     if (scm != NULL)
00882     {
00883         EnterCriticalSection(&scm->Lock);
00884 
00885         /* search the cache */
00886         Found = FindSidInCache(scm,
00887                                pSid,
00888                                &ReqResult);
00889 
00890         if (!Found)
00891         {
00892             /* the sid is not in the cache, queue it if not already queued */
00893             if (!QueueSidLookup(scm,
00894                                 pSid,
00895                                 CompletionProc,
00896                                 Context))
00897             {
00898                 PSIDREQRESULT FoundReqResult = NULL;
00899 
00900                 /* unable to queue it, look it up now */
00901 
00902                 LeaveCriticalSection(&scm->Lock);
00903 
00904                 /* lookup everything we need */
00905                 if (!LookupSidInformation(scm,
00906                                           pSid,
00907                                           &ReqResult))
00908                 {
00909                     ReqResult = NULL;
00910                 }
00911 
00912                 EnterCriticalSection(&scm->Lock);
00913 
00914                 /* see if the SID was added to the cache in the meanwhile */
00915                 if (!FindSidInCache(scm,
00916                                     pSid,
00917                                     &FoundReqResult))
00918                 {
00919                     if (ReqResult != NULL)
00920                     {
00921                         /* cache the results */
00922                         CacheLookupResults(scm,
00923                                            pSid,
00924                                            ReqResult);
00925                     }
00926                 }
00927                 else
00928                 {
00929                     if (ReqResult != NULL)
00930                     {
00931                         /* free the information of our lookup and use the cached
00932                            information*/
00933                         DereferenceSidReqResult(scm,
00934                                                 ReqResult);
00935                     }
00936 
00937                     ReqResult = FoundReqResult;
00938                 }
00939 
00940                 Found = (ReqResult != NULL);
00941             }
00942         }
00943 
00944         LeaveCriticalSection(&scm->Lock);
00945 
00946         /* call the completion callback */
00947         if (Found)
00948         {
00949             CompletionProc(SidCacheMgr,
00950                            pSid,
00951                            ReqResult,
00952                            Context);
00953 
00954             if (ReqResult != NULL)
00955             {
00956                 HeapFree(scm->Heap,
00957                          0,
00958                          ReqResult);
00959             }
00960         }
00961 
00962         DereferenceSidCacheMgr(scm);
00963     }
00964 
00965     return Found;
00966 }

Generated on Sat May 26 2012 04:21:06 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.