You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
3.2 KiB
129 lines
3.2 KiB
/*
|
|
* GUIDHASH.C
|
|
*
|
|
* RSM Service : RSM Object Hash (by GUID)
|
|
*
|
|
* Author: ErvinP
|
|
*
|
|
* (c) 2001 Microsoft Corporation
|
|
*
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <wtypes.h>
|
|
|
|
#include <ntmsapi.h>
|
|
#include "internal.h"
|
|
#include "resource.h"
|
|
#include "debug.h"
|
|
|
|
|
|
/*
|
|
* Our HASH is indexed by a function on an object's GUID.
|
|
* There is a linked list at each hash table entry to resolve collisions.
|
|
*/
|
|
#define HASH_SIZE 256
|
|
#define HASH_FUNC(lpGuid) (UINT)(UCHAR)(*(PUCHAR)(lpGuid) + *((PUCHAR)(lpGuid)+sizeof(NTMS_GUID)-1))
|
|
LIST_ENTRY guidHashTable[HASH_SIZE];
|
|
|
|
|
|
VOID InitGuidHash()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < HASH_SIZE; i++){
|
|
InitializeListHead(&guidHashTable[i]);
|
|
}
|
|
}
|
|
|
|
|
|
VOID InsertObjectInGuidHash(OBJECT_HEADER *obj)
|
|
{
|
|
UINT index = HASH_FUNC(&obj->guid);
|
|
|
|
/*
|
|
* Unfortunately, have to use a global spinlock for the hash table.
|
|
*/
|
|
EnterCriticalSection(&g_globalServiceLock);
|
|
ASSERT(IsEmptyList(&obj->hashListEntry));
|
|
ASSERT(!obj->isDeleted);
|
|
InsertTailList(&guidHashTable[index], &obj->hashListEntry);
|
|
LeaveCriticalSection(&g_globalServiceLock);
|
|
}
|
|
|
|
|
|
VOID RemoveObjectFromGuidHash(OBJECT_HEADER *obj)
|
|
{
|
|
|
|
/*
|
|
* Unfortunately, have to use a global spinlock for the hash table.
|
|
*/
|
|
EnterCriticalSection(&g_globalServiceLock);
|
|
ASSERT(!IsEmptyList(&obj->hashListEntry));
|
|
ASSERT(!IsEmptyList(&guidHashTable[HASH_FUNC(obj->guid)]));
|
|
RemoveEntryList(&obj->hashListEntry);
|
|
InitializeListHead(&obj->hashListEntry);
|
|
LeaveCriticalSection(&g_globalServiceLock);
|
|
}
|
|
|
|
|
|
OBJECT_HEADER *FindObjectInGuidHash(NTMS_GUID *guid)
|
|
{
|
|
UINT index = HASH_FUNC(guid);
|
|
OBJECT_HEADER *foundObj = NULL;
|
|
LIST_ENTRY *listEntry;
|
|
|
|
/*
|
|
* Unfortunately, have to use a global spinlock for the hash table.
|
|
*/
|
|
EnterCriticalSection(&g_globalServiceLock);
|
|
listEntry = &guidHashTable[index];
|
|
while ((listEntry = listEntry->Flink) != &guidHashTable[index]){
|
|
OBJECT_HEADER *thisObj = CONTAINING_RECORD(listEntry, OBJECT_HEADER, hashListEntry);
|
|
if (RtlEqualMemory(&thisObj->guid, guid, sizeof(NTMS_GUID))){
|
|
if (!foundObj->isDeleted){
|
|
foundObj = thisObj;
|
|
RefObject(thisObj);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
LeaveCriticalSection(&g_globalServiceLock);
|
|
|
|
return foundObj;
|
|
}
|
|
|
|
|
|
/*
|
|
* RefObject
|
|
*
|
|
* Add a reference to the object.
|
|
* An object's refCount is incremented when:
|
|
* 1. a pointer to it is returned from a guid hash lookup
|
|
* or
|
|
* 2. its handle or GUID is returned to an RSM client app
|
|
*
|
|
*/
|
|
VOID RefObject(PVOID objectPtr)
|
|
{
|
|
OBJECT_HEADER *objHdr = (OBJECT_HEADER *)objectPtr;
|
|
InterlockedIncrement(&objHdr->refCount);
|
|
}
|
|
|
|
|
|
VOID DerefObject(PVOID objectPtr)
|
|
{
|
|
OBJECT_HEADER *objHdr = (OBJECT_HEADER *)objectPtr;
|
|
LONG newRefCount;
|
|
|
|
newRefCount = InterlockedDecrement(&objHdr->refCount);
|
|
ASSERT(newRefCount >= 0);
|
|
if (newRefCount == 0){
|
|
ASSERT(objHdr->isDeleted);
|
|
|
|
// BUGBUG FINISH
|
|
}
|
|
|
|
}
|
|
|