Files
mirror-processhacker/2.x/trunk/ProcessHacker/include/phbase.h
T
wj32 61b09313eb * almost completed thread provider
* added generic module enumeration functions

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@2561 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2010-01-05 05:18:19 +00:00

800 lines
16 KiB
C

#ifndef PHBASE_H
#define PHBASE_H
#include <ntimport.h>
#include <ref.h>
#include <fastlock.h>
#define PH_APP_NAME (L"Process Hacker")
#ifndef MAIN_PRIVATE
struct _PH_STRING;
typedef struct _PH_STRING *PPH_STRING;
struct _PH_PROVIDER_THREAD;
typedef struct _PH_PROVIDER_THREAD PH_PROVIDER_THREAD;
extern PPH_STRING PhApplicationDirectory;
extern PPH_STRING PhApplicationFileName;
extern HFONT PhApplicationFont;
extern HANDLE PhHeapHandle;
extern HINSTANCE PhInstanceHandle;
extern HANDLE PhKphHandle;
extern PWSTR PhWindowClassName;
extern ULONG WindowsVersion;
extern PH_PROVIDER_THREAD PhPrimaryProviderThread;
extern PH_PROVIDER_THREAD PhSecondaryProviderThread;
extern ACCESS_MASK ProcessQueryAccess;
extern ACCESS_MASK ProcessAllAccess;
extern ACCESS_MASK ThreadQueryAccess;
extern ACCESS_MASK ThreadSetAccess;
extern ACCESS_MASK ThreadAllAccess;
#endif
#define WINDOWS_ANCIENT 0
#define WINDOWS_XP 51
#define WINDOWS_SERVER_2003 52
#define WINDOWS_VISTA 60
#define WINDOWS_7 61
#define WINDOWS_NEW MAXLONG
// basesup
struct _PH_OBJECT_TYPE;
typedef struct _PH_OBJECT_TYPE *PPH_OBJECT_TYPE;
BOOLEAN PhInitializeBase();
// heap
PVOID PhAllocate(
__in SIZE_T Size
);
VOID PhFree(
__in PVOID Memory
);
PVOID PhReAlloc(
__in PVOID Memory,
__in SIZE_T Size
);
// mutex
typedef RTL_CRITICAL_SECTION PH_MUTEX, *PPH_MUTEX;
FORCEINLINE VOID PhInitializeMutex(
__out PPH_MUTEX Mutex
)
{
InitializeCriticalSection(Mutex);
}
FORCEINLINE VOID PhDeleteMutex(
__inout PPH_MUTEX Mutex
)
{
DeleteCriticalSection(Mutex);
}
FORCEINLINE VOID PhAcquireMutex(
__inout PPH_MUTEX Mutex
)
{
EnterCriticalSection(Mutex);
}
FORCEINLINE VOID PhReleaseMutex(
__inout PPH_MUTEX Mutex
)
{
LeaveCriticalSection(Mutex);
}
// event
#define PH_EVENT_SET 0x1
#define PH_EVENT_REFCOUNT_SHIFT 1
#define PH_EVENT_REFCOUNT_INC 0x2
typedef struct _PH_EVENT
{
ULONG Value;
HANDLE EventHandle;
} PH_EVENT, *PPH_EVENT;
VOID PhInitializeEvent(
__out PPH_EVENT Event
);
VOID PhSetEvent(
__inout PPH_EVENT Event
);
BOOLEAN PhWaitForEvent(
__inout PPH_EVENT Event,
__in ULONG Timeout
);
VOID PhResetEvent(
__inout PPH_EVENT Event
);
FORCEINLINE BOOLEAN PhTestEvent(
__in PPH_EVENT Event
)
{
return !!(Event->Value & PH_EVENT_SET);
}
// string
#ifndef BASESUP_PRIVATE
extern PPH_OBJECT_TYPE PhStringType;
#endif
#define PH_STRING_MAXLEN MAXUINT16
typedef struct _PH_STRING
{
union
{
UNICODE_STRING us;
struct
{
USHORT Length;
USHORT MaximumLength;
PWSTR Pointer;
};
};
WCHAR Buffer[1];
} PH_STRING, *PPH_STRING;
PPH_STRING PhCreateString(
__in PWSTR Buffer
);
PPH_STRING PhCreateStringEx(
__in_opt PWSTR Buffer,
__in SIZE_T Length
);
PPH_STRING PhCreateStringFromAnsi(
__in PCHAR Buffer
);
PPH_STRING PhCreateStringFromAnsiEx(
__in PCHAR Buffer,
__in SIZE_T Length
);
PPH_STRING PhConcatStrings(
__in ULONG Count,
...
);
FORCEINLINE PWSTR PhGetString(
__in_opt PPH_STRING String
)
{
if (String)
return String->Buffer;
else
return NULL;
}
FORCEINLINE PPH_STRING PhConcatStrings2(
__in PWSTR String1,
__in PWSTR String2
)
{
PPH_STRING string;
SIZE_T length1;
SIZE_T length2;
length1 = wcslen(String1) * sizeof(WCHAR);
length2 = wcslen(String2) * sizeof(WCHAR);
string = PhCreateStringEx(NULL, length1 + length2);
memcpy(
string->Buffer,
String1,
length1
);
memcpy(
&string->Buffer[length1 / sizeof(WCHAR)],
String2,
length2
);
return string;
}
FORCEINLINE BOOLEAN PhStringEquals(
__in PPH_STRING String1,
__in PPH_STRING String2,
__in BOOLEAN IgnoreCase
)
{
if (!IgnoreCase)
return wcscmp(String1->Buffer, String2->Buffer) == 0;
else
return wcsicmp(String1->Buffer, String2->Buffer) == 0;
}
FORCEINLINE BOOLEAN PhStringEquals2(
__in PPH_STRING String1,
__in PWSTR String2,
__in BOOLEAN IgnoreCase
)
{
if (!IgnoreCase)
return wcscmp(String1->Buffer, String2) == 0;
else
return wcsicmp(String1->Buffer, String2) == 0;
}
FORCEINLINE BOOLEAN PhStringStartsWith(
__in PPH_STRING String1,
__in PPH_STRING String2,
__in BOOLEAN IgnoreCase
)
{
if (!IgnoreCase)
return wcsncmp(String1->Buffer, String2->Buffer, String2->Length / sizeof(WCHAR)) == 0;
else
return wcsnicmp(String1->Buffer, String2->Buffer, String2->Length / sizeof(WCHAR)) == 0;
}
FORCEINLINE BOOLEAN PhStringStartsWith2(
__in PPH_STRING String1,
__in PWSTR String2,
__in BOOLEAN IgnoreCase
)
{
if (!IgnoreCase)
return wcsncmp(String1->Buffer, String2, wcslen(String2)) == 0;
else
return wcsnicmp(String1->Buffer, String2, wcslen(String2)) == 0;
}
FORCEINLINE BOOLEAN PhStringEndsWith(
__in PPH_STRING String1,
__in PPH_STRING String2,
__in BOOLEAN IgnoreCase
)
{
if (String2->Length > String1->Length)
return FALSE;
if (!IgnoreCase)
{
return wcsncmp(
&String1->Buffer[(String1->Length - String2->Length) / sizeof(WCHAR)],
String2->Buffer,
String2->Length / sizeof(WCHAR)
) == 0;
}
else
{
return wcsnicmp(
&String1->Buffer[(String1->Length - String2->Length) / sizeof(WCHAR)],
String2->Buffer,
String2->Length / sizeof(WCHAR)
) == 0;
}
}
FORCEINLINE BOOLEAN PhStringEndsWith2(
__in PPH_STRING String1,
__in PWSTR String2,
__in BOOLEAN IgnoreCase
)
{
SIZE_T length = wcslen(String2);
if (length * sizeof(WCHAR) > String1->Length)
return FALSE;
if (!IgnoreCase)
{
return wcsncmp(
&String1->Buffer[String1->Length / sizeof(WCHAR) - length],
String2,
length
) == 0;
}
else
{
return wcsnicmp(
&String1->Buffer[String1->Length / sizeof(WCHAR) - length],
String2,
length
) == 0;
}
}
FORCEINLINE ULONG PhStringIndexOfChar(
__in PPH_STRING String1,
__in ULONG StartIndex,
__in WCHAR Char
)
{
PWSTR location;
location = wcschr(&String1->Buffer[StartIndex], Char);
if (location)
return (ULONG)(location - String1->Buffer);
else
return -1;
}
FORCEINLINE ULONG PhStringIndexOfString(
__in PPH_STRING String1,
__in ULONG StartIndex,
__in PWSTR String2
)
{
PWSTR location;
location = wcsstr(&String1->Buffer[StartIndex], String2);
if (location)
return (ULONG)(location - String1->Buffer);
else
return -1;
}
FORCEINLINE ULONG PhStringLastIndexOfChar(
__in PPH_STRING String1,
__in ULONG StartIndex,
__in WCHAR Char
)
{
PWSTR location;
location = wcsrchr(&String1->Buffer[StartIndex], Char);
if (location)
return (ULONG)(location - String1->Buffer);
else
return -1;
}
FORCEINLINE PPH_STRING PhSubstring(
__in PPH_STRING String,
__in ULONG StartIndex,
__in ULONG Count
)
{
return PhCreateStringEx(&String->Buffer[StartIndex], Count * sizeof(WCHAR));
}
// ansi string
#ifndef BASESUP_PRIVATE
extern PPH_OBJECT_TYPE PhAnsiStringType;
#endif
typedef struct _PH_ANSI_STRING
{
union
{
ANSI_STRING as;
struct
{
USHORT Length;
USHORT MaximumLength;
PSTR Pointer;
};
};
CHAR Buffer[1];
} PH_ANSI_STRING, *PPH_ANSI_STRING;
PPH_ANSI_STRING PhCreateAnsiString(
__in PSTR Buffer
);
PPH_ANSI_STRING PhCreateAnsiStringEx(
__in_opt PSTR Buffer,
__in SIZE_T Length
);
PPH_ANSI_STRING PhCreateAnsiStringFromUnicode(
__in PWSTR Buffer
);
PPH_ANSI_STRING PhCreateAnsiStringFromUnicodeEx(
__in PWSTR Buffer,
__in SIZE_T Length
);
// stringbuilder
#ifndef BASESUP_PRIVATE
extern PPH_OBJECT_TYPE PhStringBuilderType;
#endif
typedef struct _PH_STRING_BUILDER
{
// Allocated length of the string.
ULONG AllocatedLength;
// String will be allocated for AllocatedLength,
// but we will modify the Length field to be the
// correct length.
PPH_STRING String;
} PH_STRING_BUILDER, *PPH_STRING_BUILDER;
PPH_STRING_BUILDER PhCreateStringBuilder(
__in ULONG InitialCapacity
);
PPH_STRING PhReferenceStringBuilderString(
__in PPH_STRING_BUILDER StringBuilder
);
VOID PhStringBuilderAppend(
__inout PPH_STRING_BUILDER StringBuilder,
__in PPH_STRING String
);
VOID PhStringBuilderAppend2(
__inout PPH_STRING_BUILDER StringBuilder,
__in PWSTR String
);
VOID PhStringBuilderAppendEx(
__inout PPH_STRING_BUILDER StringBuilder,
__in PWSTR String,
__in ULONG Length
);
VOID PhStringBuilderInsert(
__inout PPH_STRING_BUILDER StringBuilder,
__in ULONG Index,
__in PPH_STRING String
);
VOID PhStringBuilderInsert2(
__inout PPH_STRING_BUILDER StringBuilder,
__in ULONG Index,
__in PWSTR String
);
VOID PhStringBuilderInsertEx(
__inout PPH_STRING_BUILDER StringBuilder,
__in ULONG Index,
__in PWSTR String,
__in ULONG Length
);
VOID PhStringBuilderRemove(
__inout PPH_STRING_BUILDER StringBuilder,
__in ULONG StartIndex,
__in ULONG Length
);
// list
#ifndef BASESUP_PRIVATE
extern PPH_OBJECT_TYPE PhListType;
#endif
typedef struct _PH_LIST
{
ULONG Count;
ULONG AllocatedCount;
PPVOID Items;
} PH_LIST, *PPH_LIST;
PPH_LIST PhCreateList(
__in ULONG InitialCapacity
);
VOID PhAddListItem(
__in PPH_LIST List,
__in PVOID Item
);
VOID PhClearList(
__inout PPH_LIST List
);
ULONG PhIndexOfListItem(
__in PPH_LIST List,
__in PVOID Item
);
VOID PhRemoveListItem(
__in PPH_LIST List,
__in ULONG Index
);
VOID PhRemoveListItems(
__in PPH_LIST List,
__in ULONG StartIndex,
__in ULONG Count
);
typedef INT (NTAPI *PPH_LIST_COMPARE_FUNCTION)(
__in PVOID Item1,
__in PVOID Item2,
__in PVOID Context
);
VOID PhSortList(
__in PPH_LIST List,
__in PPH_LIST_COMPARE_FUNCTION CompareFunction,
__in PVOID Context
);
// queue
#ifndef BASESUP_PRIVATE
extern PPH_OBJECT_TYPE PhQueueType;
#endif
typedef struct _PH_QUEUE
{
ULONG Count;
ULONG AllocatedCount;
PPVOID Items;
ULONG Head;
ULONG Tail;
} PH_QUEUE, *PPH_QUEUE;
PPH_QUEUE PhCreateQueue(
__in ULONG InitialCapacity
);
VOID PhEnqueueQueueItem(
__inout PPH_QUEUE Queue,
__in PVOID Item
);
BOOLEAN PhDequeueQueueItem(
__inout PPH_QUEUE Queue,
__out PPVOID Item
);
BOOLEAN PhPeekQueueItem(
__in PPH_QUEUE Queue,
__out PPVOID Item
);
// hashtable
#ifndef BASESUP_PRIVATE
extern PPH_OBJECT_TYPE PhHashtableType;
#endif
typedef struct _PH_HASHTABLE_ENTRY
{
/* Hash code of the entry. -1 if entry is unused. */
ULONG HashCode;
/* Either the index of the next entry in the bucket,
* the index of the next free entry, or -1 for invalid.
*/
ULONG Next;
QUAD Body;
} PH_HASHTABLE_ENTRY, *PPH_HASHTABLE_ENTRY;
typedef BOOLEAN (NTAPI *PPH_HASHTABLE_COMPARE_FUNCTION)(
__in PVOID Entry1,
__in PVOID Entry2
);
typedef ULONG (NTAPI *PPH_HASHTABLE_HASH_FUNCTION)(
__in PVOID Entry
);
// Enables collection of statistics
#define PH_HASHTABLE_ENABLE_STATS
// Enables 2^32-1 possible hash codes instead of only 2^31
#define PH_HASHTABLE_ENABLE_FULL_HASH
typedef struct _PH_HASHTABLE
{
/* Size of user data in each entry. */
ULONG EntrySize;
PPH_HASHTABLE_COMPARE_FUNCTION CompareFunction;
PPH_HASHTABLE_HASH_FUNCTION HashFunction;
ULONG AllocatedBuckets;
PULONG Buckets;
ULONG AllocatedEntries;
PVOID Entries;
/* Number of entries in the hashtable. */
ULONG Count;
/* Index into entry array for free list. */
ULONG FreeEntry;
/* Index of next usable index into entry array, a.k.a the
* count of entries that were ever allocated.
*/
ULONG NextEntry;
#ifdef PH_HASHTABLE_ENABLE_STATS
ULONG TotalCollisions;
#endif
} PH_HASHTABLE, *PPH_HASHTABLE;
#define PH_HASHTABLE_ENTRY_SIZE(InnerSize) (sizeof(PH_HASHTABLE_ENTRY) + (InnerSize))
#define PH_HASHTABLE_GET_ENTRY(Hashtable, Index) \
((PPH_HASHTABLE_ENTRY)PTR_ADD_OFFSET((Hashtable)->Entries, \
PH_HASHTABLE_ENTRY_SIZE((Hashtable)->EntrySize) * (Index)))
#define PH_HASHTABLE_GET_ENTRY_INDEX(Hashtable, Entry) \
((ULONG)(PTR_ADD_OFFSET(Entry, -(Hashtable)->Entries) / \
PH_HASHTABLE_ENTRY_SIZE((Hashtable)->EntrySize)))
PPH_HASHTABLE PhCreateHashtable(
__in ULONG EntrySize,
__in PPH_HASHTABLE_COMPARE_FUNCTION CompareFunction,
__in PPH_HASHTABLE_HASH_FUNCTION HashFunction,
__in ULONG InitialCapacity
);
PVOID PhAddHashtableEntry(
__inout PPH_HASHTABLE Hashtable,
__in PVOID Entry
);
VOID PhClearHashtable(
__inout PPH_HASHTABLE Hashtable
);
BOOLEAN PhEnumHashtable(
__in PPH_HASHTABLE Hashtable,
__out PPVOID Entry,
__inout PULONG EnumerationKey
);
PVOID PhGetHashtableEntry(
__in PPH_HASHTABLE Hashtable,
__in PVOID Entry
);
BOOLEAN PhRemoveHashtableEntry(
__inout PPH_HASHTABLE Hashtable,
__in PVOID Entry
);
ULONG PhHashBytes(
__in PUCHAR Bytes,
__in ULONG Length
);
ULONG PhHashBytesSdbm(
__in PUCHAR Bytes,
__in ULONG Length
);
FORCEINLINE ULONG PhHashInt32(
__in ULONG Value
)
{
// Java style.
Value ^= (Value >> 20) ^ (Value >> 12);
return Value ^ (Value >> 7) ^ (Value >> 4);
}
FORCEINLINE ULONG PhHashInt64(
__in ULONGLONG Value
)
{
// http://www.concentric.net/~Ttwang/tech/inthash.htm
Value = ~Value + (Value << 18);
Value ^= Value >> 31;
Value *= 21;
Value ^= Value >> 11;
Value += Value << 6;
Value ^= Value >> 22;
return (ULONG)Value;
}
// callback
typedef VOID (NTAPI *PPH_CALLBACK_FUNCTION)(
__in PVOID Parameter,
__in PVOID Context
);
typedef struct _PH_CALLBACK_REGISTRATION
{
LIST_ENTRY ListEntry;
PPH_CALLBACK_FUNCTION Function;
PVOID Context;
BOOLEAN Unregistering;
} PH_CALLBACK_REGISTRATION, *PPH_CALLBACK_REGISTRATION;
typedef struct _PH_CALLBACK
{
LIST_ENTRY ListHead;
PH_FAST_LOCK ListLock;
} PH_CALLBACK, *PPH_CALLBACK;
VOID PhInitializeCallback(
__out PPH_CALLBACK Callback
);
VOID PhDeleteCallback(
__inout PPH_CALLBACK Callback
);
VOID PhRegisterCallback(
__inout PPH_CALLBACK Callback,
__in PPH_CALLBACK_FUNCTION Function,
__in PVOID Context,
__out PPH_CALLBACK_REGISTRATION Registration
);
VOID PhUnregisterCallback(
__inout PPH_CALLBACK Callback,
__inout PPH_CALLBACK_REGISTRATION Registration
);
VOID PhInvokeCallback(
__in PPH_CALLBACK Callback,
__in PVOID Parameter
);
FORCEINLINE VOID PhInvokeCallbackRegistration(
__in PPH_CALLBACK_REGISTRATION Registration,
__in PVOID Parameter
)
{
Registration->Function(
Parameter,
Registration->Context
);
}
// workqueue
typedef struct _PH_WORK_QUEUE
{
PPH_QUEUE Queue;
PH_MUTEX QueueLock;
ULONG MaximumThreads;
ULONG MinimumThreads;
ULONG NoWorkTimeout;
PH_MUTEX StateLock;
HANDLE SemaphoreHandle;
ULONG CurrentThreads;
ULONG BusyThreads;
} PH_WORK_QUEUE, *PPH_WORK_QUEUE;
VOID PhWorkQueueInitialization();
VOID PhInitializeWorkQueue(
__out PPH_WORK_QUEUE WorkQueue,
__in ULONG MinimumThreads,
__in ULONG MaximumThreads,
__in ULONG NoWorkTimeout
);
VOID PhDeleteWorkQueue(
__inout PPH_WORK_QUEUE WorkQueue
);
VOID PhQueueWorkQueueItem(
__inout PPH_WORK_QUEUE WorkQueue,
__in PTHREAD_START_ROUTINE Function,
__in PVOID Context
);
VOID PhQueueGlobalWorkQueueItem(
__in PTHREAD_START_ROUTINE Function,
__in PVOID Context
);
#endif