⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sidcache.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
        {
            LeaveCriticalSection(&scm->Lock);

            /* wait for the next asynchronous lookup queued */
            WaitForSingleObject(scm->LookupEvent,
                                INFINITE);
            continue;
        }

        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);
        }
    }

    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,
                   sizeof(SIDCACHEMGR));

        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 + -