Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensidcache.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
1.7.6.1
|