예제 #1
0
파일: cmsubs.c 프로젝트: chunhualiu/OpenNT
VOID
CmpDereferenceNameControlBlockWithLock(
    PCM_NAME_CONTROL_BLOCK   Ncb
    )
{
    PCM_NAME_HASH *Prev;
    PCM_NAME_HASH Current;

    if (--Ncb->RefCount == 0) {

        //
        // Remove it from the the Hash Table
        //
        Prev = &(GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey));
        
        while (TRUE) {
            Current = *Prev;
            ASSERT(Current != NULL);
            if (Current == &(Ncb->NameHash)) {
                *Prev = Current->NextHash;
                break;
            }
            Prev = &Current->NextHash;
        }

        //
        // Free storage
        //
        ExFreePoolWithTag(Ncb, CM_NAME_TAG | PROTECTED_POOL);
    }
    return;
}
예제 #2
0
VOID
NTAPI
CmpRemoveKeyHash(IN PCM_KEY_HASH KeyHash)
{
    PCM_KEY_HASH *Prev;
    PCM_KEY_HASH Current;
    ASSERT_VALID_HASH(KeyHash);

    /* Lookup all the keys in this index entry */
    Prev = &GET_HASH_ENTRY(CmpCacheTable, KeyHash->ConvKey).Entry;
    while (TRUE)
    {
        /* Save the current one and make sure it's valid */
        Current = *Prev;
        ASSERT(Current != NULL);
        ASSERT_VALID_HASH(Current);

        /* Check if it matches */
        if (Current == KeyHash)
        {
            /* Then write the previous one */
            *Prev = Current->NextHash;
            if (*Prev) ASSERT_VALID_HASH(*Prev);
            break;
        }

        /* Otherwise, keep going */
        Prev = &Current->NextHash;
    }
}
예제 #3
0
VOID
NTAPI
CmpDereferenceNameControlBlockWithLock(IN PCM_NAME_CONTROL_BLOCK Ncb)
{
    PCM_NAME_HASH Current, *Next;
    ULONG ConvKey = Ncb->ConvKey;

    /* Lock the NCB */
    CmpAcquireNcbLockExclusiveByKey(ConvKey);

    /* Decrease the reference count */
    ASSERT(Ncb->RefCount >= 1);
    if (!(--Ncb->RefCount))
    {
        /* Find the NCB in the table */
        Next = &GET_HASH_ENTRY(CmpNameCacheTable, Ncb->ConvKey).Entry;
        while (TRUE)
        {
            /* Check the current entry */
            Current = *Next;
            ASSERT(Current != NULL);
            if (Current == &Ncb->NameHash)
            {
                /* Unlink it */
                *Next = Current->NextHash;
                break;
            }

            /* Get to the next one */
            Next = &Current->NextHash;
        }

        /* Found it, now free it */
        CmpFree(Ncb, 0);
    }

    /* Release the lock */
    CmpReleaseNcbLockByKey(ConvKey);
}
예제 #4
0
PCM_NAME_CONTROL_BLOCK
NTAPI
CmpGetNameControlBlock(IN PUNICODE_STRING NodeName)
{
    PCM_NAME_CONTROL_BLOCK Ncb = NULL;
    ULONG ConvKey = 0;
    PWCHAR p, pp;
    ULONG i;
    BOOLEAN IsCompressed = TRUE, Found = FALSE;
    PCM_NAME_HASH HashEntry;
    ULONG Length, NcbSize;

    /* Loop the name */
    p = NodeName->Buffer;
    for (i = 0; i < NodeName->Length; i += sizeof(WCHAR))
    {
        /* Make sure it's not a slash */
        if (*p != OBJ_NAME_PATH_SEPARATOR)
        {
            /* Add it to the hash */
            ConvKey = 37 * ConvKey + RtlUpcaseUnicodeChar(*p);
        }

        /* Next character */
        p++;
    }

    /* Set assumed lengh and loop to check */
    Length = NodeName->Length / sizeof(WCHAR);
    for (i = 0; i < (NodeName->Length / sizeof(WCHAR)); i++)
    {
        /* Check if this is a 16-bit character */
        if (NodeName->Buffer[i] > (UCHAR)-1)
        {
            /* This is the actual size, and we know we're not compressed */
            Length = NodeName->Length;
            IsCompressed = FALSE;
            break;
        }
    }

    /* Lock the NCB entry */
    CmpAcquireNcbLockExclusiveByKey(ConvKey);

    /* Get the hash entry */
    HashEntry = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
    while (HashEntry)
    {
        /* Get the current NCB */
        Ncb = CONTAINING_RECORD(HashEntry, CM_NAME_CONTROL_BLOCK, NameHash);

        /* Check if the hash matches */
        if ((ConvKey == HashEntry->ConvKey) && (Length == Ncb->NameLength))
        {
            /* Assume success */
            Found = TRUE;

            /* If the NCB is compressed, do a compressed name compare */
            if (Ncb->Compressed)
            {
                /* Compare names */
                if (CmpCompareCompressedName(NodeName, Ncb->Name, Length))
                {
                    /* We failed */
                    Found = FALSE;
                }
            }
            else
            {
                /* Do a manual compare */
                p = NodeName->Buffer;
                pp = Ncb->Name;
                for (i = 0; i < Ncb->NameLength; i += sizeof(WCHAR))
                {
                    /* Compare the character */
                    if (RtlUpcaseUnicodeChar(*p) != RtlUpcaseUnicodeChar(*pp))
                    {
                        /* Failed */
                        Found = FALSE;
                        break;
                    }

                    /* Next chars */
                    p++;
                    pp++;
                }
            }

            /* Check if we found a name */
            if (Found)
            {
                /* Reference it */
                ASSERT(Ncb->RefCount != 0xFFFF);
                Ncb->RefCount++;
                break;
            }
        }

        /* Go to the next hash */
        HashEntry = HashEntry->NextHash;
    }

    /* Check if we didn't find it */
    if (!Found)
    {
        /* Allocate one */
        NcbSize = FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name) + Length;
        Ncb = CmpAllocate(NcbSize, TRUE, TAG_CM);
        if (!Ncb)
        {
            /* Release the lock and fail */
            CmpReleaseNcbLockByKey(ConvKey);
            return NULL;
        }

        /* Clear it out */
        RtlZeroMemory(Ncb, NcbSize);

        /* Check if the name was compressed */
        if (IsCompressed)
        {
            /* Copy the compressed name */
            for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
            {
                /* Copy Unicode to ANSI */
                ((PCHAR)Ncb->Name)[i] = (CHAR)RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
            }
        }
        else
        {
            /* Copy the name directly */
            for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
            {
                /* Copy each unicode character */
                Ncb->Name[i] = RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
            }
        }

        /* Setup the rest of the NCB */
        Ncb->Compressed = IsCompressed;
        Ncb->ConvKey = ConvKey;
        Ncb->RefCount++;
        Ncb->NameLength = Length;

        /* Insert the name in the hash table */
        HashEntry = &Ncb->NameHash;
        HashEntry->NextHash = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
        GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry = HashEntry;
    }

    /* Release NCB lock */
    CmpReleaseNcbLockByKey(ConvKey);

    /* Return the NCB found */
    return Ncb;
}