📄 sidcache.c
字号:
}
scm->QueueLookingUp = QueueEntry;
LeaveCriticalSection(&scm->Lock);
if (QueueEntry != NULL)
{
PSIDREQRESULT ReqResult, FoundReqResult;
PSID pSid = (PSID)(QueueEntry + 1);
/* lookup the SID information */
if (!LookupSidInformation(scm,
pSid,
&ReqResult))
{
ReqResult = NULL;
}
EnterCriticalSection(&scm->Lock);
/* see if the SID was added to the cache in the meanwhile */
if (!FindSidInCache(scm,
pSid,
&FoundReqResult))
{
if (ReqResult != NULL)
{
/* cache the results */
CacheLookupResults(scm,
pSid,
ReqResult);
}
}
else
{
if (ReqResult != NULL)
{
/* free the information of our lookup and use the cached
information*/
DereferenceSidReqResult(scm,
ReqResult);
}
ReqResult = FoundReqResult;
}
/* notify the callers unless the lookup was cancelled */
if (scm->QueueLookingUp != NULL)
{
ULONG i = 0;
while (scm->QueueLookingUp != NULL &&
i < QueueEntry->CallbackCount)
{
PVOID Context;
PSIDREQCOMPLETIONPROC CompletionProc;
Context = QueueEntry->Callbacks[i].Context;
CompletionProc = QueueEntry->Callbacks[i].CompletionProc;
LeaveCriticalSection(&scm->Lock);
/* call the completion proc without holding the lock! */
CompletionProc(ScmToHandle(scm),
pSid,
ReqResult,
Context);
EnterCriticalSection(&scm->Lock);
i++;
}
scm->QueueLookingUp = NULL;
}
LeaveCriticalSection(&scm->Lock);
/* free the queue item */
FreeQueueEntry(scm,
QueueEntry);
}
}
CleanupSidCacheMgr(scm);
HeapFree(scm->Heap,
0,
scm);
if (hModule != NULL)
{
/* dereference the library and exit */
FreeLibraryAndExitThread(hModule,
0);
}
return 0;
}
HANDLE
CreateSidCacheMgr(IN HANDLE Heap,
IN LPCWSTR SystemName)
{
PSIDCACHEMGR scm;
if (SystemName == NULL)
SystemName = L"";
scm = HeapAlloc(Heap,
0,
FIELD_OFFSET(SIDCACHEMGR,
SystemName[wcslen(SystemName) + 1]));
if (scm != NULL)
{
/* zero the static part of the structure */
ZeroMemory(scm,
FIELD_OFFSET(SIDCACHEMGR,
SystemName));
scm->RefCount = 1;
scm->Heap = Heap;
wcscpy(scm->SystemName,
SystemName);
InitializeCriticalSection(&scm->Lock);
InitializeListHead(&scm->QueueListHead);
InitializeListHead(&scm->CacheListHead);
scm->LookupEvent = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (scm->LookupEvent == NULL)
{
goto Cleanup;
}
if (!OpenLSAPolicyHandle(scm->SystemName,
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
&scm->LsaHandle))
{
goto Cleanup;
}
scm->LookupThread = CreateThread(NULL,
0,
LookupThreadProc,
scm,
0,
NULL);
if (scm->LookupThread == NULL)
{
Cleanup:
if (scm->LookupEvent != NULL)
{
CloseHandle(scm->LookupEvent);
}
if (scm->LsaHandle != NULL)
{
LsaClose(scm->LsaHandle);
}
HeapFree(Heap,
0,
scm);
scm = NULL;
}
}
else
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return (HANDLE)scm;
}
VOID
DestroySidCacheMgr(IN HANDLE SidCacheMgr)
{
PSIDCACHEMGR scm = HandleToScm(SidCacheMgr);
if (scm != NULL)
{
/* remove the keep-alive reference */
DereferenceSidCacheMgr(scm);
}
}
static BOOL
QueueSidLookup(IN PSIDCACHEMGR scm,
IN PSID pSid,
IN PSIDREQCOMPLETIONPROC CompletionProc,
IN PVOID Context)
{
PLIST_ENTRY CurrentEntry;
PSIDQUEUEENTRY QueueEntry, FoundEntry = NULL;
BOOL Ret = FALSE;
/* NOTE: assumes the lists are locked! */
if (scm->QueueLookingUp != NULL &&
EqualSid(pSid,
(PSID)(scm->QueueLookingUp + 1)))
{
FoundEntry = scm->QueueLookingUp;
}
else
{
CurrentEntry = &scm->QueueListHead;
while (CurrentEntry != &scm->QueueListHead)
{
QueueEntry = CONTAINING_RECORD(CurrentEntry,
SIDQUEUEENTRY,
ListEntry);
if (EqualSid(pSid,
(PSID)(QueueEntry + 1)))
{
FoundEntry = QueueEntry;
break;
}
CurrentEntry = CurrentEntry->Flink;
}
}
if (FoundEntry == NULL)
{
DWORD SidLength = GetLengthSid(pSid);
FoundEntry = HeapAlloc(scm->Heap,
0,
sizeof(SIDQUEUEENTRY) + SidLength);
if (FoundEntry != NULL)
{
CopySid(SidLength,
(PSID)(FoundEntry + 1),
pSid);
FoundEntry->CallbackCount = 1;
FoundEntry->Callbacks = HeapAlloc(scm->Heap,
0,
sizeof(SIDCACHECALLBACKINFO));
if (FoundEntry->Callbacks != NULL)
{
FoundEntry->Callbacks[0].CompletionProc = CompletionProc;
FoundEntry->Callbacks[0].Context = Context;
/* append it to the queue */
InsertTailList(&scm->QueueListHead,
&FoundEntry->ListEntry);
/* signal the lookup event */
SetEvent(scm->LookupEvent);
Ret = TRUE;
}
else
{
/* unable to queue it because we couldn't allocate the callbacks
array, free the memory and return */
HeapFree(scm->Heap,
0,
FoundEntry);
}
}
}
else
{
PSIDCACHECALLBACKINFO Sidccb;
/* add the callback */
Sidccb = HeapReAlloc(scm->Heap,
0,
FoundEntry->Callbacks,
(FoundEntry->CallbackCount + 1) * sizeof(SIDCACHECALLBACKINFO));
if (Sidccb != NULL)
{
FoundEntry->Callbacks = Sidccb;
FoundEntry->Callbacks[FoundEntry->CallbackCount].CompletionProc = CompletionProc;
FoundEntry->Callbacks[FoundEntry->CallbackCount++].Context = Context;
Ret = TRUE;
}
}
return Ret;
}
VOID
DequeueSidLookup(IN HANDLE SidCacheMgr,
IN PSID pSid)
{
PLIST_ENTRY CurrentEntry;
PSIDQUEUEENTRY QueueEntry;
PSIDCACHEMGR scm;
scm = ReferenceSidCacheMgr(SidCacheMgr);
if (scm != NULL)
{
EnterCriticalSection(&scm->Lock);
if (scm->QueueLookingUp != NULL &&
EqualSid(pSid,
(PSID)(scm->QueueLookingUp + 1)))
{
/* don't free the queue lookup item! this will be
done in the lookup thread */
scm->QueueLookingUp = NULL;
}
else
{
CurrentEntry = &scm->QueueListHead;
while (CurrentEntry != &scm->QueueListHead)
{
QueueEntry = CONTAINING_RECORD(CurrentEntry,
SIDQUEUEENTRY,
ListEntry);
if (EqualSid(pSid,
(PSID)(QueueEntry + 1)))
{
FreeQueueEntry(scm,
QueueEntry);
break;
}
CurrentEntry = CurrentEntry->Flink;
}
}
LeaveCriticalSection(&scm->Lock);
DereferenceSidCacheMgr(scm);
}
}
VOID
ReferenceSidReqResult(IN HANDLE SidCacheMgr,
IN PSIDREQRESULT ReqResult)
{
PSIDCACHEMGR scm;
scm = ReferenceSidCacheMgr(SidCacheMgr);
if (scm != NULL)
{
InterlockedIncrement(&ReqResult->RefCount);
DereferenceSidCacheMgr(scm);
}
}
VOID
DereferenceSidReqResult(IN HANDLE SidCacheMgr,
IN PSIDREQRESULT ReqResult)
{
PSIDCACHEMGR scm;
scm = ReferenceSidCacheMgr(SidCacheMgr);
if (scm != NULL)
{
if (InterlockedDecrement(&ReqResult->RefCount) == 0)
{
HeapFree(scm->Heap,
0,
ReqResult);
}
DereferenceSidCacheMgr(scm);
}
}
BOOL
LookupSidCache(IN HANDLE SidCacheMgr,
IN PSID pSid,
IN PSIDREQCOMPLETIONPROC CompletionProc,
IN PVOID Context)
{
BOOL Found = FALSE;
PSIDREQRESULT ReqResult = NULL;
PSIDCACHEMGR scm;
scm = ReferenceSidCacheMgr(SidCacheMgr);
if (scm != NULL)
{
EnterCriticalSection(&scm->Lock);
/* search the cache */
Found = FindSidInCache(scm,
pSid,
&ReqResult);
if (!Found)
{
/* the sid is not in the cache, queue it if not already queued */
if (!QueueSidLookup(scm,
pSid,
CompletionProc,
Context))
{
PSIDREQRESULT FoundReqResult = NULL;
/* unable to queue it, look it up now */
LeaveCriticalSection(&scm->Lock);
/* lookup everything we need */
if (!LookupSidInformation(scm,
pSid,
&ReqResult))
{
ReqResult = NULL;
}
EnterCriticalSection(&scm->Lock);
/* see if the SID was added to the cache in the meanwhile */
if (!FindSidInCache(scm,
pSid,
&FoundReqResult))
{
if (ReqResult != NULL)
{
/* cache the results */
CacheLookupResults(scm,
pSid,
ReqResult);
}
}
else
{
if (ReqResult != NULL)
{
/* free the information of our lookup and use the cached
information*/
DereferenceSidReqResult(scm,
ReqResult);
}
ReqResult = FoundReqResult;
}
Found = (ReqResult != NULL);
}
}
LeaveCriticalSection(&scm->Lock);
/* call the completion callback */
if (Found)
{
CompletionProc(SidCacheMgr,
pSid,
ReqResult,
Context);
if (ReqResult != NULL)
{
HeapFree(scm->Heap,
0,
ReqResult);
}
}
DereferenceSidCacheMgr(scm);
}
return Found;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -