Windows2003-3790/sdktools/trace/tracectr/process.c
2020-09-30 16:53:55 +02:00

2555 lines
66 KiB
C

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
process.c
Abstract:
Manipulation routines for cpdata structures.
Author:
Melur Raghuraman (mraghu) 03-Oct-1997
Environment:
Revision History:
--*/
#include <stdio.h>
#include <stdlib.h>
#include "cpdata.h"
#include "tracectr.h"
#include "item.h"
extern PTRACE_CONTEXT_BLOCK TraceContext;
extern PWCHAR CpdiGuidToString(PWCHAR s, ULONG len, LPGUID piid);
extern LIST_ENTRY g_ValueMapTable;
VOID
Aggregate(
IN PTHREAD_RECORD pThread
);
ULONG
CPDAPI
GetTempName( LPTSTR strFile, size_t cchSize )
{
HRESULT hr;
DWORD dwStatus;
GUID guid;
WCHAR strGUID[128];
DWORD nChar = 0;
dwStatus = UuidCreate( &guid );
if( dwStatus == RPC_S_OK || dwStatus == RPC_S_UUID_LOCAL_ONLY ){
nChar = StringFromGUID2( (const GUID*)&guid, strGUID, 128 );
dwStatus = ERROR_SUCCESS;
}
if( 0 == nChar ){
hr = StringCchPrintf( strGUID, 128, L"{d41c99ea-c303-4d06-b779-f9e8e20acb8f}.%08d", rand() );
}
nChar = GetTempPath( cchSize, strFile );
if( 0 == nChar ){
dwStatus = GetLastError();
}
if( ERROR_SUCCESS == dwStatus ){
hr = StringCchCat( strFile, cchSize, strGUID );
}
return dwStatus;
}
__inline
USHORT
UrlHashKey(
PUCHAR UrlStr,
ULONG StrSize
)
{
USHORT i, l, key = 0;
i = (USHORT)(StrSize - 1);
// Use only the last 25 chars
l = (StrSize > 25) ? (USHORT)(StrSize - 25) : 0;
// UrlStr cannot be NULL when this function is called.
for ( ; i >= l; i--) {
key = 37 * key + (USHORT)(*(UrlStr + i));
if (i == 0) {
break;
}
}
key = key % (URL_HASH_TABLESIZE);
return key;
}
VOID
InitDiskRecord(
PTDISK_RECORD pDisk,
ULONG DiskNumber
)
{
PWCHAR name;
if (pDisk == NULL){
return;
}
memset(pDisk, 0, sizeof(TDISK_RECORD));
InitializeListHead(&pDisk->ProcessListHead);
InitializeListHead(&pDisk->FileListHead);
pDisk->DiskNumber = DiskNumber;
name = (PWCHAR)malloc(16 * sizeof(WCHAR));
if (name != NULL) {
StringCbPrintfW(name, 16 * sizeof(WCHAR), L"Disk%d", DiskNumber);
}
pDisk->DiskName = name;
}
VOID
InitFileRecord(
PFILE_RECORD pFile
)
{
if (pFile == NULL){
return;
}
memset(pFile, 0, sizeof(FILE_RECORD));
InitializeListHead(&pFile->ProtoProcessListHead);
}
VOID
InitThreadRecord(
PTHREAD_RECORD pThread
)
{
if (pThread == NULL)
return;
memset(pThread, 0, sizeof(THREAD_RECORD));
InitializeListHead( &pThread->DiskListHead );
InitializeListHead( &pThread->TransListHead );
InitializeListHead( &pThread->HPFReadListHead );
InitializeListHead( &pThread->HPFWriteListHead );
}
PTRANS_RECORD
CreateTransRecord()
{
PLIST_ENTRY Head, Next;
PTRANS_RECORD pTrans = NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.FreeTransListHead;
Next = Head->Flink;
if (Next != Head) {
pTrans = CONTAINING_RECORD ( Next, TRANS_RECORD, Entry );
RemoveEntryList( &pTrans->Entry );
}
LeaveTracelibCritSection();
if (pTrans == NULL) {
pTrans = malloc(sizeof(TRANS_RECORD));
if (pTrans == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
}
memset(pTrans, 0, sizeof(TRANS_RECORD));
InitializeListHead(&pTrans->SubTransListHead);
return pTrans;
}
VOID
InitMofData(
PMOF_DATA pMofData
)
{
if (pMofData == NULL)
return;
memset(pMofData, 0, sizeof(MOF_DATA));
pMofData->MaxKCpu = -1;
pMofData->MinKCpu = -1;
pMofData->MaxUCpu = -1;
pMofData->MinUCpu = -1;
}
VOID
InitProcessRecord(
PPROCESS_RECORD pProcess
)
{
if (pProcess == NULL)
return;
memset(pProcess, 0, sizeof(PROCESS_RECORD));
InitializeListHead( &pProcess->ThreadListHead );
InitializeListHead( &pProcess->DiskListHead );
InitializeListHead( &pProcess->FileListHead );
InitializeListHead( &pProcess->ModuleListHead );
InitializeListHead( &pProcess->HPFListHead );
}
BOOLEAN AddModuleRecord(PMODULE_RECORD * ppModule,
ULONG lBaseAddress,
ULONG lModuleSize,
WCHAR * strModuleName)
{
PMODULE_RECORD pModule;
if ( (ppModule == NULL) || (strModuleName == NULL) ) {
return FALSE;
}
pModule = (PMODULE_RECORD)malloc(sizeof(MODULE_RECORD));
if(NULL != pModule){
memset(pModule, 0, sizeof(MODULE_RECORD));
pModule->strModuleName =
malloc(sizeof(WCHAR) * (lstrlenW(strModuleName) + 1));
if (pModule->strModuleName == NULL)
{
free(pModule);
pModule = NULL;
}
else
{
StringCchCopyW(pModule->strModuleName, (lstrlenW(strModuleName) + 1), strModuleName);
pModule->lBaseAddress = lBaseAddress;
pModule->lModuleSize = lModuleSize;
}
}
* ppModule = pModule;
return (BOOLEAN) (* ppModule != NULL);
}
BOOLEAN AddHPFFileRecord(
PHPF_FILE_RECORD * ppHPFFileRecord,
ULONG RecordID,
ULONG IrpFlags,
ULONG DiskNumber,
ULONGLONG ByteOffset,
ULONG BytesCount,
PVOID fDO
)
{
PHPF_FILE_RECORD pHPFFileRecord = malloc(sizeof(HPF_FILE_RECORD));
if (pHPFFileRecord)
{
pHPFFileRecord->RecordID = RecordID;
pHPFFileRecord->IrpFlags = IrpFlags;
pHPFFileRecord->DiskNumber = DiskNumber;
pHPFFileRecord->ByteOffset = ByteOffset;
pHPFFileRecord->BytesCount = BytesCount;
pHPFFileRecord->fDO = fDO;
}
* ppHPFFileRecord = pHPFFileRecord;
return (BOOLEAN) (* ppHPFFileRecord != NULL);
}
BOOLEAN AddHPFRecord(
PHPF_RECORD * ppHPFRecord,
ULONG lFaultAddress,
PVOID fDO,
LONG ByteCount,
LONGLONG ByteOffset
)
{
PHPF_RECORD pHPFRecord = malloc(sizeof(HPF_RECORD));
if (pHPFRecord)
{
pHPFRecord->fDO = fDO;
pHPFRecord->lFaultAddress = lFaultAddress;
pHPFRecord->lByteCount = ByteCount;
pHPFRecord->lByteOffset = ByteOffset;
InitializeListHead(& pHPFRecord->HPFReadListHead);
}
* ppHPFRecord = pHPFRecord;
return (BOOLEAN) (* ppHPFRecord != NULL);
}
void DeleteHPFRecord(
PHPF_RECORD pHPFRecord
)
{
PLIST_ENTRY pHead;
PLIST_ENTRY pNext;
PHPF_FILE_RECORD pHPFFileRecord;
if (!pHPFRecord)
return;
RemoveEntryList(& pHPFRecord->Entry);
pHead = & pHPFRecord->HPFReadListHead;
pNext = pHead->Flink;
while (pNext != pHead)
{
pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pHPFFileRecord->Entry);
free(pHPFFileRecord);
}
free(pHPFRecord);
return;
}
VOID
InitWorkloadRecord(
PWORKLOAD_RECORD pWorkload
)
{
if (pWorkload == NULL)
return;
memset(pWorkload, 0, sizeof(WORKLOAD_RECORD));
InitializeListHead( &pWorkload->DiskListHead );
}
VOID
DeleteWorkloadRecord(
PWORKLOAD_RECORD pWorkload
)
{
if (pWorkload == NULL)
return;
}
PPROTO_PROCESS_RECORD
AddProtoProcess(
PFILE_RECORD pFile,
PPROCESS_RECORD pProcess
)
{
PPROTO_PROCESS_RECORD pProto;
if (pFile == NULL || pProcess == NULL)
return NULL;
pProto = malloc(sizeof(PROTO_PROCESS_RECORD));
if (pProto == NULL) {
return NULL;
}
memset(pProto, 0, sizeof(PROTO_PROCESS_RECORD));
pProto->ProcessRecord = pProcess;
InsertHeadList( &pFile->ProtoProcessListHead, &pProto->Entry );
return pProto;
}
PPROTO_PROCESS_RECORD
FindProtoProcessRecord(
PFILE_RECORD pFile,
PPROCESS_RECORD pProcess
)
{
PLIST_ENTRY Next, Head;
PPROTO_PROCESS_RECORD pProto;
if (pFile == NULL || pProcess == NULL)
return NULL;
Head = &pFile->ProtoProcessListHead;
Next = Head->Flink;
while (Next != Head) {
pProto = CONTAINING_RECORD(Next, PROTO_PROCESS_RECORD, Entry);
if (pProcess == pProto->ProcessRecord)
return pProto;
Next = Next->Flink;
}
return (AddProtoProcess(pFile, pProcess));
}
BOOLEAN
AddProcess(
ULONG ProcessId,
PPROCESS_RECORD *ReturnedProcess
)
{
PPROCESS_RECORD Process;
PMODULE_RECORD pModule = NULL;
Process = malloc(sizeof(PROCESS_RECORD));
if (Process == NULL) {
return FALSE;
}
InitProcessRecord( Process );
Process->PID = ProcessId;
if (!AddModuleRecord(& pModule, 0, 0, L"other")) {
free(Process);
return FALSE;
}
pModule->pProcess = Process;
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.ProcessListHead, &Process->Entry );
InsertHeadList(& Process->ModuleListHead, & pModule->Entry);
LeaveTracelibCritSection();
*ReturnedProcess = Process;
return TRUE;
}
BOOLEAN
DeleteProcess(
PPROCESS_RECORD Process
)
{
PLIST_ENTRY Next, Head;
PTHREAD_RECORD Thread;
PTDISK_RECORD Disk;
PFILE_RECORD pFile;
PMODULE_RECORD pModule;
PHPF_RECORD pHPFRecord;
if (Process == NULL)
return FALSE;
EnterTracelibCritSection();
RemoveEntryList( &Process->Entry );
LeaveTracelibCritSection();
Head = &Process->ThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
Next = Next->Flink;
DeleteThread( Thread );
}
Head = &Process->DiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
Next = Next->Flink;
DeleteDisk( Disk );
}
Head = &Process->HPFListHead;
Next = Head->Flink;
while (Next != Head) {
pHPFRecord = CONTAINING_RECORD(Next, HPF_RECORD, Entry);
Next = Next->Flink;
DeleteHPFRecord(pHPFRecord);
}
Head = &Process->FileListHead;
Next = Head->Flink;
while (Next != Head) {
pFile = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList( &pFile->Entry );
if (pFile->FileName != NULL)
free(pFile->FileName);
free(pFile);
}
Head = &Process->ModuleListHead;
Next = Head->Flink;
while (Next != Head)
{
pModule = CONTAINING_RECORD(Next, MODULE_RECORD, Entry);
Next = Next->Flink;
RemoveEntryList(& pModule->Entry);
if(pModule->strModuleName)
{
free(pModule->strModuleName);
}
free(pModule);
}
if (Process->ImageName != NULL)
free(Process->ImageName);
if (Process->UserName != NULL)
free(Process->UserName);
free( Process );
return TRUE;
}
BOOLEAN
AddThread(
ULONG ThreadId,
PEVENT_TRACE pEvent,
PTHREAD_RECORD * ResultThread
)
{
PTHREAD_RECORD Thread = NULL;
PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
int i;
Thread = malloc(sizeof(THREAD_RECORD));
if (Thread == NULL) {
return FALSE;
}
InitThreadRecord(Thread);
Thread->TimeStart = Thread->TimeEnd
= (ULONGLONG) pHeader->TimeStamp.QuadPart;
Thread->TID = ThreadId;
Thread->ProcessorID = pEvent->ClientContext & 0x000000FF;
i = (int)Thread->TID;
i = i % THREAD_HASH_TABLESIZE;
InsertHeadList(&CurrentSystem.ThreadHashList[i], &Thread->Entry);
*ResultThread = Thread;
return TRUE;
}
BOOLEAN
DeleteThread(
PTHREAD_RECORD Thread
)
{
PLIST_ENTRY pHead;
PLIST_ENTRY pNext;
PHPF_FILE_RECORD pHPFFileRecord;
if (Thread == NULL) {
return FALSE;
}
RemoveEntryList( &Thread->Entry );
DeleteTransList( &Thread->TransListHead, 0 );
pHead = & Thread->HPFReadListHead;
pNext = pHead->Flink;
while (pNext != pHead)
{
pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pHPFFileRecord->Entry);
free(pHPFFileRecord);
}
pHead = & Thread->HPFWriteListHead;
pNext = pHead->Flink;
while (pNext != pHead)
{
pHPFFileRecord = CONTAINING_RECORD(pNext, HPF_FILE_RECORD, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pHPFFileRecord->Entry);
free(pHPFFileRecord);
}
free( Thread );
return TRUE;
}
PTRANS_RECORD
FindTransByList(
PLIST_ENTRY Head,
LPGUID pGuid,
ULONG level
)
{
PLIST_ENTRY Next;
PTRANS_RECORD pTrans = NULL;
// Recursively look for the list that does
// not contain a running guid
//
if (level <= MAX_TRANS_LEVEL && Head != NULL)
{
Next = Head->Flink;
while (Next != Head)
{
pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
if (pTrans->bStarted)
{
if ( (level == 0 || level == 1)
&& IsEqualGUID(pTrans->pGuid, pGuid))
{
return pTrans;
}
else if (level > 0)
{
return FindTransByList(& pTrans->SubTransListHead,
pGuid,
level - 1);
}
}
Next = Next->Flink;
}
}
// Found the correct list; now find
// the matching transaction
//
if (level == 0 && Head != NULL)
{
Next = Head->Flink;
while (Next != Head)
{
pTrans = CONTAINING_RECORD(Next, TRANS_RECORD, Entry);
if (IsEqualGUID( pTrans->pGuid, pGuid))
{
return pTrans;
}
Next = Next->Flink;
}
//
// If not Found, go ahead and add it.
//
pTrans = CreateTransRecord();
if (pTrans != NULL) {
pTrans->pGuid = pGuid;
InsertHeadList( Head, &pTrans->Entry );
}
}
return pTrans;
}
PMOF_DATA
FindMofData(
PMOF_INFO pMofInfo,
PWCHAR strSortKey
)
{
PLIST_ENTRY Next;
PLIST_ENTRY Head;
PMOF_DATA pMofData = NULL;
if (pMofInfo == NULL) {
return NULL;
}
Head = &pMofInfo->DataListHead;
if (Head != NULL)
{
Next = Head->Flink;
while (Next != Head)
{
pMofData = CONTAINING_RECORD(Next, MOF_DATA, Entry);
if (strSortKey == NULL && pMofData->strSortKey == NULL)
{
return pMofData;
}
else if ( strSortKey != NULL
&& pMofData->strSortKey != NULL
&& !wcscmp(pMofData->strSortKey, strSortKey))
{
return pMofData;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
pMofData = (PMOF_DATA)malloc(sizeof(MOF_DATA));
if (pMofData == NULL)
{
return NULL;
}
InitMofData(pMofData);
if (strSortKey != NULL)
{
pMofData->strSortKey =
(PWCHAR) malloc((lstrlenW(strSortKey) + 1) * sizeof(WCHAR));
if (pMofData->strSortKey != NULL) {
StringCchCopyW(pMofData->strSortKey, (lstrlenW(strSortKey) + 1), strSortKey);
}
}
InsertHeadList(Head, &pMofData->Entry);
}
return pMofData;
}
BOOLEAN
DeleteTrans(
PTRANS_RECORD Trans
)
{
if (Trans == NULL)
return FALSE;
EnterTracelibCritSection();
RemoveEntryList( &Trans->Entry );
InsertHeadList( &CurrentSystem.FreeTransListHead, &Trans->Entry );
LeaveTracelibCritSection();
return TRUE;
}
BOOLEAN
DeleteTransList(
PLIST_ENTRY Head,
ULONG level
)
{
PLIST_ENTRY Next;
PTRANS_RECORD pTrans;
if( Head == NULL || level > MAX_TRANS_LEVEL )
return FALSE;
Next = Head->Flink;
while(Next != Head){
pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
Next = Next->Flink;
DeleteTransList( &pTrans->SubTransListHead, level+1);
DeleteTrans( pTrans );
}
return TRUE;
}
PPROCESS_RECORD
FindProcessById(
ULONG Id,
BOOLEAN CheckAlive
)
{
PLIST_ENTRY Next, Head;
PPROCESS_RECORD Process=NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
if (Process->PID == Id) {
LeaveTracelibCritSection();
if ((Process->DeadFlag) && (CheckAlive))
return NULL;
else
return Process;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
PTHREAD_RECORD
FindGlobalThreadById(
ULONG ThreadId,
PEVENT_TRACE pEvent
)
{
PLIST_ENTRY Next,
Head;
PTHREAD_RECORD Thread;
PEVENT_TRACE_HEADER pHeader = (PEVENT_TRACE_HEADER) & pEvent->Header;
ULONG i = ThreadId;
ULONG Depth = 0;
i = i % THREAD_HASH_TABLESIZE;
Head = &CurrentSystem.ThreadHashList[i];
Next = Head->Flink;
while (Next != Head)
{
Thread = CONTAINING_RECORD(Next, THREAD_RECORD, Entry);
Next = Next->Flink;
Depth++;
if (Thread->TID == ThreadId)
{
if (ThreadId == 0)
{
ULONG ProcessorId = pEvent->ClientContext & 0x000000FF;
if (ProcessorId != Thread->ProcessorID)
{
continue;
}
}
if (!Thread->DeadFlag)
{
if (Depth > 40) {
RemoveEntryList( &Thread->Entry );
InsertHeadList( Head, &Thread->Entry );
}
return Thread;
}
else if ( Thread->TimeEnd
== (ULONGLONG) pHeader->TimeStamp.QuadPart)
{
if (Depth > 40) {
RemoveEntryList( &Thread->Entry );
InsertHeadList( Head, &Thread->Entry );
}
return Thread;
}
else
{
// The alive thead must be at the head of the list
// otherwise bail
//
return NULL;
}
}
}
return NULL;
}
PWORKLOAD_RECORD
FindWorkloadById(
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PWORKLOAD_RECORD Workload = NULL;
Head = &CurrentSystem.WorkloadListHead;
Next = Head->Flink;
while (Next != Head) {
Workload = CONTAINING_RECORD( Next, WORKLOAD_RECORD, Entry );
if (Workload->ClassNumber == Id) {
return Workload;
}
Next = Next->Flink;
}
return NULL;
}
BOOLEAN
AddDisk(
ULONG DiskNumber,
PTDISK_RECORD *ReturnedDisk
)
{
PTDISK_RECORD Disk;
Disk = malloc(sizeof(TDISK_RECORD));
if (Disk == NULL) {
return FALSE;
}
InitDiskRecord(Disk, DiskNumber);
Disk->DiskNumber = DiskNumber;
InsertHeadList( &CurrentSystem.GlobalDiskListHead, &Disk->Entry );
*ReturnedDisk = Disk;
return TRUE;
}
BOOLEAN
DeleteDisk(
PTDISK_RECORD Disk
)
{
PLIST_ENTRY Head, Next;
PPROCESS_RECORD Process;
PFILE_RECORD File;
if (Disk == NULL)
return FALSE;
RemoveEntryList( &Disk->Entry );
if (Disk->DiskName != NULL)
free(Disk->DiskName);
Head = &Disk->ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
DeleteProcess( Process );
}
Head = &Disk->FileListHead;
Next = Head->Flink;
while (Next != Head) {
File = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
Next = Next->Flink;
DeleteFileRecord( File );
}
free( Disk );
return TRUE;
}
PTDISK_RECORD
FindLocalDiskById(
PLIST_ENTRY Head,
ULONG Id
)
{
PLIST_ENTRY Next;
PTDISK_RECORD Disk = NULL;
if (Head == NULL)
return NULL;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
if (Disk->DiskNumber == Id) {
return Disk;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
Disk = malloc(sizeof(TDISK_RECORD));
if (Disk == NULL) {
return FALSE;
}
InitDiskRecord(Disk, Id);
Disk->DiskNumber = Id;
InsertHeadList( Head, &Disk->Entry );
return Disk;
}
PTDISK_RECORD
FindProcessDiskById(
PPROCESS_RECORD pProcess,
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PTDISK_RECORD Disk = NULL;
if (pProcess == NULL)
return NULL;
Head = &pProcess->DiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
if (Disk->DiskNumber == Id) {
return Disk;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
Disk = malloc(sizeof(TDISK_RECORD));
if (Disk == NULL) {
return NULL;
}
InitDiskRecord(Disk, Id);
Disk->DiskNumber = Id;
InsertHeadList( &pProcess->DiskListHead, &Disk->Entry );
return Disk;
}
PPROCESS_RECORD
FindDiskProcessById(
PTDISK_RECORD pDisk,
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PPROCESS_RECORD Process = NULL;
PPROCESS_RECORD gProcess = NULL;
if (pDisk == NULL)
return NULL;
Head = &pDisk->ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
if (Process->PID == Id) {
return Process;
}
Next = Next->Flink;
}
// If not Found, go ahead and add it.
//
Process = malloc(sizeof(PROCESS_RECORD));
if (Process == NULL) {
return FALSE;
}
InitProcessRecord(Process);
Process->PID = Id;
// Find the global Process Record and copy the UserName and Image.
//
gProcess = FindProcessById(Id, FALSE);
if (gProcess != NULL) {
if ( IsNotEmpty( gProcess->UserName ) ) {
Process->UserName = (LPWSTR)malloc( (wcslen(gProcess->UserName) + 1) * sizeof(WCHAR) );
if (NULL != Process->UserName) {
StringCchCopyW(Process->UserName, (wcslen(gProcess->UserName) + 1), gProcess->UserName);
}
}
if ( IsNotEmpty( gProcess->ImageName ) ) {
Process->ImageName = (LPWSTR)malloc( (wcslen(gProcess->ImageName) + 1) * sizeof(WCHAR) );
if (NULL != Process->ImageName) {
StringCchCopyW(Process->ImageName, (wcslen(gProcess->ImageName) + 1), gProcess->ImageName);
}
}
}
InsertHeadList( &pDisk->ProcessListHead, &Process->Entry );
return Process;
}
PTDISK_RECORD
FindGlobalDiskById(
ULONG Id
)
{
PLIST_ENTRY Next, Head;
PTDISK_RECORD Disk = NULL;
Head = &CurrentSystem.GlobalDiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
if (Disk->DiskNumber == Id) {
return Disk;
}
Next = Next->Flink;
}
return NULL;
}
VOID
DeleteMofVersion(
PMOF_VERSION pMofVersion,
FILE* file
)
{
PLIST_ENTRY Next, Head;
PITEM_DESC pMofItem;
//
// Traverse through the MOF_VERSION list and
// delete each one
//
if (pMofVersion == NULL)
return;
if( NULL != file ){
fwprintf( file, L" %s (Type:%d Level:%d Version:%d)\n",
pMofVersion->strType ? pMofVersion->strType : L"Default",
pMofVersion->TypeIndex,
pMofVersion->Level,
pMofVersion->Version
);
}
Head = &pMofVersion->ItemHeader;
Next = Head->Flink;
while (Head != Next) {
pMofItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
Next = Next->Flink;
RemoveEntryList( &pMofItem->Entry );
if (pMofItem->strDescription != NULL){
if( NULL != file ){
fwprintf( file, L" %s\n",
pMofItem->strDescription
);
}
free (pMofItem->strDescription);
}
free (pMofItem);
}
}
VOID
DeleteMofInfo(
PMOF_INFO pMofInfo,
FILE* f
)
{
PLIST_ENTRY Next, Head;
PMOF_VERSION pMofVersion;
//
// Traverse through the MOF_VERSION list and
// delete each one
//
if (pMofInfo == NULL){
return;
}
if( NULL != f ){
WCHAR buffer[MAXSTR];
fwprintf( f, L"%s\n",
pMofInfo->strDescription ? pMofInfo->strDescription : CpdiGuidToString( buffer, MAXSTR, &pMofInfo->Guid ) );
}
Head = &pMofInfo->VersionHeader;
Next = Head->Flink;
while (Head != Next) {
pMofVersion = CONTAINING_RECORD(Next, MOF_VERSION, Entry);
Next = Next->Flink;
RemoveEntryList( &pMofVersion->Entry );
DeleteMofVersion( pMofVersion, f );
}
//
// Delete any strings allocated for this structure
//
if (pMofInfo->strDescription){
free(pMofInfo->strDescription);
}
//
// Finally delete the object
//
free(pMofInfo);
}
VOID
Cleanup()
{
PTDISK_RECORD Disk;
PTHREAD_RECORD Thread;
PPROCESS_RECORD Process;
PFILE_RECORD FileRec;
PWORKLOAD_RECORD pWorkload;
PMODULE_RECORD pModule;
PTRANS_RECORD pTrans;
PMOF_INFO pMofInfo;
PPRINT_JOB_RECORD pJob;
PHTTP_REQUEST_RECORD pReq;
PURL_RECORD pUrl;
PCLIENT_RECORD pClient;
PSITE_RECORD pSite;
PLOGICAL_DRIVE_RECORD pLogDrive;
PVALUEMAP pValueMap;
PLIST_ENTRY Next, Head;
PLIST_ENTRY EventListHead;
FILE* f = NULL;
ULONG i;
// Clean up the Global Disk List for now.
//
EventListHead = &CurrentSystem.EventListHead;
Head = EventListHead;
Next = Head->Flink;
if( (TraceContext->Flags & TRACE_INTERPRET) && NULL != TraceContext->CompFileName ){
f = _wfopen( TraceContext->CompFileName, L"w" );
}
while (Head != Next) {
pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
Next = Next->Flink;
RemoveEntryList( &pMofInfo->Entry );
DeleteMofInfo(pMofInfo, f);
}
if( NULL != f ){
fclose( f );
f = NULL;
}
Head = &CurrentSystem.GlobalDiskListHead;
Next = Head->Flink;
while (Next != Head) {
Disk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
Next = Next->Flink;
DeleteDisk( Disk );
}
// Clean up the Global Thread List for now.
//
Head = &CurrentSystem.GlobalThreadListHead;
Next = Head->Flink;
while (Next != Head) {
Thread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
Next = Next->Flink;
DeleteThread( Thread );
}
Head = &CurrentSystem.ProcessListHead;
Next = Head->Flink;
while (Next != Head) {
Process = CONTAINING_RECORD( Next, PROCESS_RECORD, Entry );
Next = Next->Flink;
DeleteProcess( Process );
}
Head = &CurrentSystem.GlobalModuleListHead;
Next = Head->Flink;
while (Next != Head)
{
pModule = CONTAINING_RECORD(Next, MODULE_RECORD, Entry);
Next = Next->Flink;
RemoveEntryList(& pModule->Entry);
if(pModule->strModuleName)
{
free(pModule->strModuleName);
}
free(pModule);
}
Head = &CurrentSystem.HotFileListHead;
Next = Head->Flink;
while (Next != Head) {
FileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
Next = Next->Flink;
DeleteFileRecord( FileRec );
}
// Cleanup workload structures
//
Head = &CurrentSystem.WorkloadListHead;
Next = Head->Flink;
while (Next != Head) {
pWorkload = CONTAINING_RECORD( Next, WORKLOAD_RECORD, Entry );
Next = Next->Flink;
DeleteWorkloadRecord( pWorkload );
}
//
// Cleanup the Print Job List structures
//
Head = &CurrentSystem.PrintJobListHead;
Next = Head->Flink;
while (Next != Head) {
pJob = CONTAINING_RECORD( Next, PRINT_JOB_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pJob->Entry);
free(pJob);
}
//
// Cleanup the Http Request List structures
//
Head = &CurrentSystem.HttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD( Next, HTTP_REQUEST_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pReq->Entry);
if (pReq->URL != NULL) {
free(pReq->URL);
}
free(pReq);
}
//
// Cleanup the Pending Http Request List structures
//
Head = &CurrentSystem.PendingHttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD( Next, HTTP_REQUEST_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pReq->Entry);
if (pReq->URL != NULL) {
free(pReq->URL);
}
free(pReq);
}
//
// Cleanup the URL List structures
//
for (i = 0; i < URL_HASH_TABLESIZE; i++) {
Head = &CurrentSystem.URLHashList[i];
Next = Head->Flink;
while (Next != Head) {
pUrl = CONTAINING_RECORD( Next, URL_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pUrl->Entry);
free(pUrl);
}
}
//
// Cleanup the Client List structures
//
Head = &CurrentSystem.ClientListHead;
Next = Head->Flink;
while (Next != Head) {
pClient = CONTAINING_RECORD( Next, CLIENT_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pClient->Entry);
free(pClient);
}
//
// Cleanup the Site List structures
//
Head = &CurrentSystem.SiteListHead;
Next = Head->Flink;
while (Next != Head) {
pSite = CONTAINING_RECORD( Next, SITE_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pSite->Entry);
free(pSite);
}
//
// Cleanup the Logical Drive structures
//
Head = &CurrentSystem.LogicalDriveHead;
Next = Head->Flink;
while (Next != Head) {
pLogDrive = CONTAINING_RECORD( Next, LOGICAL_DRIVE_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pLogDrive->Entry);
if (NULL != pLogDrive->DriveLetterString) {
free(pLogDrive->DriveLetterString);
}
free(pLogDrive);
}
//
// Clean up recyled memory structures
//
Head = &CurrentSystem.FreePrintJobListHead;
Next = Head->Flink;
while (Next != Head) {
pJob = CONTAINING_RECORD( Next, PRINT_JOB_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pJob->Entry);
free(pJob);
}
Head = &CurrentSystem.FreeTransListHead;
Next = Head->Flink;
while (Next != Head) {
pTrans = CONTAINING_RECORD( Next, TRANS_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pTrans->Entry);
free(pTrans);
}
Head = &CurrentSystem.FreeHttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD( Next, HTTP_REQUEST_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pReq->Entry);
free(pReq);
}
Head = &CurrentSystem.FreeURLListHead;
Next = Head->Flink;
while (Next != Head) {
pUrl = CONTAINING_RECORD( Next, URL_RECORD, Entry );
Next = Next->Flink;
RemoveEntryList(&pUrl->Entry);
free(pUrl);
}
Head = &g_ValueMapTable;
Next = Head->Flink;
while (Next != Head) {
pValueMap = CONTAINING_RECORD( Next, VALUEMAP, Entry );
Next = Next->Flink;
RemoveEntryList(&pValueMap->Entry);
if( NULL != pValueMap->saValueMap ){
SafeArrayDestroy( pValueMap->saValueMap );
}
if( NULL != pValueMap->saValues ){
SafeArrayDestroy( pValueMap->saValues );
}
free( pValueMap );
}
}
PLOGICAL_DRIVE_RECORD
FindLogicalDrive(
ULONGLONG AccessedOffset,
ULONG DiskNumber
)
{
PLOGICAL_DRIVE_RECORD pLogDrive = NULL;
PLIST_ENTRY Next, Head;
EnterTracelibCritSection();
// Find drive letter when logical drive info is available.
Head = &CurrentSystem.LogicalDriveHead;
Next = Head->Flink;
if (Next != Head) {
while (Next != Head) {
pLogDrive = CONTAINING_RECORD( Next, LOGICAL_DRIVE_RECORD, Entry );
if (DiskNumber == pLogDrive->DiskNumber &&
AccessedOffset < pLogDrive->StartOffset &&
Next->Blink != Head) {
pLogDrive = CONTAINING_RECORD( Next->Blink, LOGICAL_DRIVE_RECORD, Entry );
break;
}
Next = Next->Flink;
}
}
LeaveTracelibCritSection();
if (NULL != pLogDrive && DiskNumber == pLogDrive->DiskNumber) {
return pLogDrive;
}
else {
return NULL;
}
}
BOOLEAN
AddFile(
WCHAR* fileName,
PFILE_RECORD *ReturnedFile,
PLOGICAL_DRIVE_RECORD pLogDrive
)
{
PFILE_RECORD fileRec;
PLIST_ENTRY Next, Head;
if (fileName == NULL)
return FALSE;
fileRec = malloc(sizeof(FILE_RECORD));
if (fileRec == NULL) {
return FALSE;
}
InitFileRecord( fileRec );
fileRec->FileName = malloc( (lstrlenW(fileName)+ 1) * sizeof(WCHAR));
if (fileRec->FileName != NULL) {
StringCchCopyW(fileRec->FileName, (lstrlenW(fileName)+ 1), fileName);
}
if (NULL != pLogDrive) {
fileRec->DiskNumber = pLogDrive->DiskNumber;
if (NULL != pLogDrive->DriveLetterString) {
fileRec->Drive = malloc( (lstrlenW(pLogDrive->DriveLetterString)+ 1) * sizeof(WCHAR));
if (fileRec->Drive != NULL) {
StringCchCopyW(fileRec->Drive, lstrlenW(pLogDrive->DriveLetterString)+ 1, pLogDrive->DriveLetterString);
}
}
}
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.HotFileListHead, &fileRec->Entry );
LeaveTracelibCritSection();
*ReturnedFile = fileRec;
return TRUE;
}
BOOLEAN
DeleteFileRecord(
PFILE_RECORD fileRec
)
{
PLIST_ENTRY Next, Head;
PPROTO_PROCESS_RECORD pProto;
if (fileRec == NULL)
return FALSE;
EnterTracelibCritSection();
RemoveEntryList( &fileRec->Entry );
LeaveTracelibCritSection();
if (fileRec->FileName != NULL)
free(fileRec->FileName);
if (fileRec->Drive != NULL)
free(fileRec->Drive);
Head = &fileRec->ProtoProcessListHead;
Next = Head->Flink;
while (Head != Next) {
pProto = CONTAINING_RECORD( Next, PROTO_PROCESS_RECORD, Entry);
Next = Next->Flink;
RemoveEntryList( &pProto->Entry );
free(pProto);
}
free( fileRec );
return TRUE;
}
PFILE_RECORD
FindFileRecordByName(
WCHAR* fileName,
PLOGICAL_DRIVE_RECORD pLogDrive
)
{
PLIST_ENTRY Next, Head;
PFILE_RECORD fileRec = NULL;
if (fileName == NULL)
return NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.HotFileListHead;
Next = Head->Flink;
while (Next != Head) {
fileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
if (!wcscmp(fileName, fileRec->FileName)) {
if (NULL != pLogDrive && pLogDrive->DiskNumber == fileRec->DiskNumber) {
if (NULL != pLogDrive->DriveLetterString &&
NULL != fileRec->Drive &&
!wcscmp(pLogDrive->DriveLetterString, fileRec->Drive)) {
LeaveTracelibCritSection();
return fileRec;
}
else if (NULL == pLogDrive->DriveLetterString &&
NULL == fileRec->Drive) {
LeaveTracelibCritSection();
return fileRec;
}
}
else if (NULL == pLogDrive) {
LeaveTracelibCritSection();
return fileRec;
}
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
PFILE_RECORD
FindFileInProcess(
PPROCESS_RECORD pProcess,
WCHAR* fileName
)
{
PLIST_ENTRY Next, Head;
PFILE_RECORD fileRec = NULL;
if (pProcess == NULL || fileName == NULL)
return NULL;
EnterTracelibCritSection();
Head = &pProcess->FileListHead;
Next = Head->Flink;
while (Next != Head) {
fileRec = CONTAINING_RECORD( Next, FILE_RECORD, Entry );
if (!wcscmp(fileName, fileRec->FileName)) {
//ReleaseMutex(CurrentSystem.HotFileListMutex);
LeaveTracelibCritSection();
return fileRec;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
VOID
AddLogicalDrive(
ULONGLONG StartOffset,
ULONGLONG PartitionSize,
ULONG DiskNumber,
ULONG Size,
ULONG DriveType,
PWCHAR DriveLetterString
)
{
PLOGICAL_DRIVE_RECORD pLogDrive = NULL, pTempLogDrive = NULL;
PLIST_ENTRY Next, Head;
pLogDrive = malloc(sizeof(LOGICAL_DRIVE_RECORD));
if (pLogDrive == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return;
}
RtlZeroMemory(pLogDrive, sizeof(LOGICAL_DRIVE_RECORD));
pLogDrive->StartOffset = StartOffset;
pLogDrive->PartitionSize = PartitionSize;
pLogDrive->DiskNumber = DiskNumber;
pLogDrive->Size = Size;
pLogDrive->DriveType = DriveType;
if (DriveLetterString != NULL) {
pLogDrive->DriveLetterString = malloc( (lstrlenW(DriveLetterString)+ 1) * sizeof(WCHAR));
if (pLogDrive->DriveLetterString != NULL) {
StringCchCopyW(pLogDrive->DriveLetterString, lstrlenW(DriveLetterString)+ 1, DriveLetterString);
}
}
EnterTracelibCritSection();
// When inserting logical drives, do it in StartOffset order.
Head = &CurrentSystem.LogicalDriveHead;
Next = Head->Flink;
while (Next != Head) {
pTempLogDrive = CONTAINING_RECORD( Next, LOGICAL_DRIVE_RECORD, Entry );
if (pLogDrive->StartOffset < pTempLogDrive->StartOffset) {
break;
}
Next = Next->Flink;
}
InsertTailList( Next, &pLogDrive->Entry );
LeaveTracelibCritSection();
}
VOID
AssignClass(
PPROCESS_RECORD pProcess,
PTHREAD_RECORD pThread
)
{
UNREFERENCED_PARAMETER(pProcess);
pThread->ClassNumber = 1; // For the Time being make it single class.
}
VOID
Classify()
{
// Assign Class to each Thread or Process.
//
PLIST_ENTRY Head, Next;
PTHREAD_RECORD pThread;
Head = &CurrentSystem.GlobalThreadListHead;
Next = Head->Flink;
while (Next != Head) {
pThread = CONTAINING_RECORD( Next, THREAD_RECORD, Entry );
AssignClass(NULL, pThread);
Aggregate(pThread);
Next = Next->Flink;
}
}
// Given the number of classes this routine
// creates and initializes the workload object
//
VOID
InitClass()
{
PWORKLOAD_RECORD pWorkload;
ULONG nclass;
ULONG i;
// Create the Class records here.
//
nclass = 1;
CurrentSystem.NumberOfWorkloads = 1;
for (i = 1; i <= nclass; i++) {
pWorkload = malloc(sizeof(WORKLOAD_RECORD));
if (pWorkload == NULL) {
return;
}
InitWorkloadRecord( pWorkload );
pWorkload->ClassNumber = i;
InsertHeadList( &CurrentSystem.WorkloadListHead, &pWorkload->Entry );
}
}
PTDISK_RECORD
FindDiskInList(
IN PLIST_ENTRY Head,
IN ULONG Id
)
{
PLIST_ENTRY Next;
PTDISK_RECORD pDisk = NULL;
if (Head != NULL) {
Next = Head->Flink;
while (Next != Head) {
pDisk = CONTAINING_RECORD ( Next, TDISK_RECORD, Entry );
if (pDisk->DiskNumber == Id) {
return pDisk;
}
Next = Next->Flink;
}
pDisk = malloc(sizeof(TDISK_RECORD));
if (pDisk == NULL) {
return NULL;
}
InitDiskRecord( pDisk, Id );
InsertHeadList( Head, &pDisk->Entry );
}
return pDisk;
}
VOID
Aggregate(
IN PTHREAD_RECORD pThread
)
{
PWORKLOAD_RECORD pWorkload;
PTDISK_RECORD pDisk, pClassDisk;
PLIST_ENTRY Next, Head;
// Aggregate the metrics over each class.
//
if ((pWorkload = FindWorkloadById(pThread->ClassNumber)) != NULL) {
pWorkload->UserCPU += (pThread->UCPUEnd - pThread->UCPUStart)
* CurrentSystem.TimerResolution;
pWorkload->KernelCPU += (pThread->KCPUEnd - pThread->KCPUStart)
* CurrentSystem.TimerResolution;
//
// Walk through the Thread Disk records and aggregate them
// to the class
Head = &pThread->DiskListHead;
Next = Head->Flink;
while (Next != Head) {
pDisk = CONTAINING_RECORD( Next, TDISK_RECORD, Entry );
Next = Next->Flink;
pClassDisk = FindDiskInList(&pWorkload->DiskListHead,
pDisk->DiskNumber) ;
if (pClassDisk != NULL) {
pClassDisk->ReadCount += pDisk->ReadCount;
pClassDisk->WriteCount += pDisk->WriteCount;
pClassDisk->ReadSize += (pDisk->ReadCount * pDisk->ReadSize);
pClassDisk->WriteSize += (pDisk->WriteCount * pDisk->WriteSize);
pWorkload->ReadCount += pDisk->ReadCount;
}
}
}
}
ULONGLONG
CalculateProcessLifeTime(
PPROCESS_RECORD pProcess
)
{
BOOLEAN fFirst = TRUE;
ULONGLONG TimeStart = 0;
ULONGLONG TimeEnd = 0;
PLIST_ENTRY pHead = &pProcess->ThreadListHead;
PLIST_ENTRY pNext = pHead->Flink;
PTHREAD_RECORD pThread;
while (pNext != pHead)
{
pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
pNext = pNext->Flink;
if (fFirst)
{
TimeStart = pThread->TimeStart;
TimeEnd = pThread->TimeEnd;
fFirst = FALSE;
}
else if (pThread->TimeStart < TimeStart)
{
TimeStart = pThread->TimeStart;
}
else if (pThread->TimeEnd > TimeEnd)
{
TimeEnd = pThread->TimeEnd;
}
}
return (TimeEnd - TimeStart);
}
ULONG
CalculateProcessKCPU(
PPROCESS_RECORD pProcess
)
{
ULONG KCPUTotal = 0;
ULONG KCPUMissing = 0;
PLIST_ENTRY pHead = &pProcess->ThreadListHead;
PLIST_ENTRY pNext = pHead->Flink;
PTHREAD_RECORD pThread;
while (pNext != pHead)
{
pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
pNext = pNext->Flink;
if (pThread->KCPUEnd > pThread->KCPUStart)
{
if ((pProcess->PID != 0) ||
((pProcess->PID == 0) && (pThread->TID == 0)) ){
KCPUTotal += pThread->KCPUEnd - pThread->KCPUStart;
}
else {
KCPUMissing += pThread->KCPUEnd - pThread->KCPUStart;
}
}
}
return (ULONG) (KCPUTotal * CurrentSystem.TimerResolution);
}
ULONG
CalculateProcessUCPU(
PPROCESS_RECORD pProcess
)
{
ULONG UCPUTotal = 0;
ULONG UCPUMissing = 0;
PLIST_ENTRY pHead = &pProcess->ThreadListHead;
PLIST_ENTRY pNext = pHead->Flink;
PTHREAD_RECORD pThread;
while (pNext != pHead)
{
pThread = CONTAINING_RECORD(pNext, THREAD_RECORD, Entry);
pNext = pNext->Flink;
if (pThread->UCPUEnd > pThread->UCPUStart)
{
if ((pProcess->PID != 0) ||
((pProcess->PID == 0) && (pThread->TID == 0)) ) {
UCPUTotal += pThread->UCPUEnd - pThread->UCPUStart;
}
else {
UCPUMissing += pThread->UCPUEnd - pThread->UCPUStart;
}
}
}
return (ULONG) (UCPUTotal * CurrentSystem.TimerResolution);
}
PPRINT_JOB_RECORD
FindPrintJobRecord(
ULONG JobId
)
{
PLIST_ENTRY Head, Next;
PPRINT_JOB_RECORD pJob;
EnterTracelibCritSection();
Head = &CurrentSystem.PrintJobListHead;
Next = Head->Flink;
while (Next != Head) {
pJob = CONTAINING_RECORD ( Next, PRINT_JOB_RECORD, Entry );
if (pJob->JobId == JobId) {
LeaveTracelibCritSection();
return pJob;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
PHTTP_REQUEST_RECORD
FindHttpReqRecord(
ULONGLONG RequestId
)
{
PLIST_ENTRY Head, Next;
PHTTP_REQUEST_RECORD pReq;
ULONG Depth = 0;
EnterTracelibCritSection();
Head = &CurrentSystem.HttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
if (pReq->RequestId == RequestId) {
if (Depth > 40) {
RemoveEntryList( &pReq->Entry );
InsertHeadList( Head, &pReq->Entry );
}
LeaveTracelibCritSection();
return pReq;
}
Next = Next->Flink;
Depth++;
}
LeaveTracelibCritSection();
return NULL;
}
PHTTP_REQUEST_RECORD
FindHttpReqRecordByConId(
ULONGLONG ConId,
PHTTP_REQUEST_RECORD pPrevReq
)
{
PLIST_ENTRY Head, Next;
PHTTP_REQUEST_RECORD pReq;
ULONG Depth = 0;
EnterTracelibCritSection();
Head = &CurrentSystem.HttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
if (pReq->ConId == ConId) {
if (pPrevReq == NULL || pPrevReq != pReq) {
if (Depth > 40) {
RemoveEntryList( &pReq->Entry );
InsertHeadList( Head, &pReq->Entry );
}
LeaveTracelibCritSection();
return pReq;
}
}
Next = Next->Flink;
Depth++;
}
Depth = 0;
Head = &CurrentSystem.PendingHttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
if (pReq->ConId == ConId) {
if (pPrevReq == NULL || pPrevReq != pReq) {
if (Depth > 40) {
RemoveEntryList( &pReq->Entry );
InsertHeadList( Head, &pReq->Entry );
}
LeaveTracelibCritSection();
return pReq;
}
}
Next = Next->Flink;
Depth++;
}
LeaveTracelibCritSection();
return NULL;
}
PHTTP_REQUEST_RECORD
FindPendingHttpReqRecord(
ULONGLONG RequestId
)
{
PLIST_ENTRY Head, Next;
PHTTP_REQUEST_RECORD pReq;
ULONG Depth = 0;
EnterTracelibCritSection();
Head = &CurrentSystem.PendingHttpReqListHead;
Next = Head->Flink;
while (Next != Head) {
pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
if (pReq->RequestId == RequestId) {
if (Depth > 40) {
RemoveEntryList( &pReq->Entry );
InsertHeadList( Head, &pReq->Entry );
}
LeaveTracelibCritSection();
return pReq;
}
Next = Next->Flink;
Depth++;
}
LeaveTracelibCritSection();
return NULL;
}
PURL_RECORD
FindUrlRecord(
PUCHAR Url
)
{
PLIST_ENTRY Head, Next;
PURL_RECORD pUrl;
ULONG Depth = 0;
ULONG UrlStrSize;
PUCHAR UrlChar;
BOOL bMatch;
UCHAR TempEndChar;
USHORT HashKey;
if (Url == NULL) {
return NULL;
}
UrlStrSize = 0;
UrlChar = Url;
while (*UrlChar != '\0' && *UrlChar != '?') {
UrlStrSize++;
UrlChar++;
}
// No URL will end with '/'
if (*(UrlChar - 1) == '/') {
UrlStrSize--;
}
TempEndChar = *(Url + UrlStrSize);
*(Url + UrlStrSize) = '\0';
HashKey = UrlHashKey(Url, UrlStrSize);
EnterTracelibCritSection();
Head = &CurrentSystem.URLHashList[HashKey];
Next = Head->Flink;
while (Next != Head) {
pUrl = CONTAINING_RECORD ( Next, URL_RECORD, Entry );
// pUrl->URL cannot be NULL. If it is, it shouldn't even be created.
if ( _stricmp( Url, pUrl->URL ) == 0 ) {
if (Depth > 20) {
RemoveEntryList( &pUrl->Entry );
InsertHeadList( Head, &pUrl->Entry );
}
LeaveTracelibCritSection();
return pUrl;
}
Next = Next->Flink;
Depth++;
}
LeaveTracelibCritSection();
*(Url + UrlStrSize) = TempEndChar;
return NULL;
}
PCLIENT_RECORD
FindClientRecord(
USHORT IpAddrType,
ULONG IpAddrV4,
USHORT *IpAddrV6
)
{
PLIST_ENTRY Head, Next;
PCLIENT_RECORD pClient;
if (IpAddrV6 == NULL) {
return NULL;
}
EnterTracelibCritSection();
Head = &CurrentSystem.ClientListHead;
Next = Head->Flink;
while (Next != Head) {
pClient = CONTAINING_RECORD ( Next, CLIENT_RECORD, Entry );
if (pClient->IpAddrType == IpAddrType &&
pClient->IpAddrV4 == IpAddrV4 &&
RtlCompareMemory(IpAddrV6, pClient->IpAddrV6, sizeof(USHORT) * 8) == sizeof(USHORT) * 8) {
LeaveTracelibCritSection();
return pClient;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
PSITE_RECORD
FindSiteRecord(
ULONG SiteId
)
{
PLIST_ENTRY Head, Next;
PSITE_RECORD pSite;
EnterTracelibCritSection();
Head = &CurrentSystem.SiteListHead;
Next = Head->Flink;
while (Next != Head) {
pSite = CONTAINING_RECORD ( Next, SITE_RECORD, Entry );
if (pSite->SiteId == SiteId) {
LeaveTracelibCritSection();
return pSite;
}
Next = Next->Flink;
}
LeaveTracelibCritSection();
return NULL;
}
//
// A New Job with a JobId has been found. This routine will create a
// new job record to track it through various threads in the system
//
PPRINT_JOB_RECORD
AddPrintJobRecord(
ULONG JobId
)
{
PLIST_ENTRY Head, Next;
PPRINT_JOB_RECORD pJob = NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.FreePrintJobListHead;
Next = Head->Flink;
if (Next != Head) {
pJob = CONTAINING_RECORD ( Next, PRINT_JOB_RECORD, Entry );
RemoveEntryList( &pJob->Entry );
}
LeaveTracelibCritSection();
if (pJob == NULL) {
pJob = malloc(sizeof(PRINT_JOB_RECORD));
if (pJob == NULL) {
SetLastError( ERROR_OUTOFMEMORY);
return NULL;
}
}
RtlZeroMemory(pJob, sizeof(PRINT_JOB_RECORD));
pJob->JobId = JobId;
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.PrintJobListHead, &pJob->Entry );
LeaveTracelibCritSection();
return pJob;
}
PHTTP_REQUEST_RECORD
AddHttpReqRecord(
ULONGLONG RequestId,
USHORT IpAddrType,
ULONG IpAddrV4,
USHORT *IpAddrV6
)
{
PLIST_ENTRY Head, Next;
PHTTP_REQUEST_RECORD pReq = NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.FreeHttpReqListHead;
Next = Head->Flink;
if (Next != Head) {
pReq = CONTAINING_RECORD ( Next, HTTP_REQUEST_RECORD, Entry );
RemoveEntryList( &pReq->Entry );
}
LeaveTracelibCritSection();
if (pReq == NULL) {
pReq = malloc(sizeof(HTTP_REQUEST_RECORD));
if (pReq == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
}
RtlZeroMemory(pReq, sizeof(HTTP_REQUEST_RECORD));
pReq->RequestId = RequestId;
pReq->IpAddrType = IpAddrType;
pReq->IpAddrV4 = IpAddrV4;
if (IpAddrV6 != NULL && IpAddrType == TDI_ADDRESS_TYPE_IP6) {
RtlCopyMemory(&pReq->IpAddrV6, IpAddrV6, sizeof(USHORT) * 8);
}
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.HttpReqListHead, &pReq->Entry );
LeaveTracelibCritSection();
return pReq;
}
PURL_RECORD
AddUrlRecord(
PUCHAR Url
)
{
PLIST_ENTRY Head, Next;
PUCHAR UrlStr = NULL, UrlChar;
PURL_RECORD pUrl = NULL;
ULONG UrlStrSize;
USHORT HashKey;
if (Url == NULL) {
return NULL;
}
EnterTracelibCritSection();
Head = &CurrentSystem.FreeURLListHead;
Next = Head->Flink;
if (Next != Head) {
pUrl = CONTAINING_RECORD ( Next, URL_RECORD, Entry );
RemoveEntryList( &pUrl->Entry );
}
LeaveTracelibCritSection();
if (pUrl == NULL) {
pUrl = malloc(sizeof(URL_RECORD));
if (pUrl == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
}
UrlStrSize = 0;
UrlChar = Url;
while (*UrlChar != '\0' && *UrlChar != '?') {
UrlStrSize++;
UrlChar++;
}
// No URL will end with '/'
if (*(UrlChar - 1) == '/') {
*(UrlChar - 1) = '\0';
UrlStrSize--;
}
RtlZeroMemory(pUrl, sizeof(URL_RECORD));
pUrl->URL = (PUCHAR)malloc(UrlStrSize + 1);
if (pUrl->URL == NULL) {
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.FreeURLListHead, &pUrl->Entry );
LeaveTracelibCritSection();
return NULL;
}
strncpy(pUrl->URL, Url, UrlStrSize);
*(pUrl->URL + UrlStrSize) = '\0';
HashKey = UrlHashKey(pUrl->URL, UrlStrSize);
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.URLHashList[HashKey], &pUrl->Entry );
LeaveTracelibCritSection();
return pUrl;
}
PURL_RECORD
FindOrAddUrlRecord(
PUCHAR Url
)
{
PURL_RECORD pUrl = NULL;
pUrl = FindUrlRecord(Url);
if (pUrl == NULL) {
pUrl = AddUrlRecord(Url);
}
return pUrl;
}
PCLIENT_RECORD
AddClientRecord(
USHORT IpAddrType,
ULONG IpAddrV4,
USHORT *IpAddrV6
)
{
PCLIENT_RECORD pClient = NULL;
pClient = malloc(sizeof(CLIENT_RECORD));
if (pClient == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
RtlZeroMemory(pClient, sizeof(CLIENT_RECORD));
pClient->IpAddrType = IpAddrType;
pClient->IpAddrV4 = IpAddrV4;
if (IpAddrV6 != NULL && IpAddrType == TDI_ADDRESS_TYPE_IP6) {
RtlCopyMemory(pClient->IpAddrV6, IpAddrV6, sizeof(USHORT) * 8);
}
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.ClientListHead, &pClient->Entry );
LeaveTracelibCritSection();
return pClient;
}
PCLIENT_RECORD
FindOrAddClientRecord(
USHORT IpAddrType,
ULONG IpAddrV4,
USHORT *IpAddrV6
)
{
PCLIENT_RECORD pClient = NULL;
pClient = FindClientRecord(IpAddrType, IpAddrV4, IpAddrV6);
if (pClient == NULL) {
pClient = AddClientRecord(IpAddrType, IpAddrV4, IpAddrV6);
}
return pClient;
}
PSITE_RECORD
AddSiteRecord(
ULONG SiteId
)
{
PSITE_RECORD pSite = NULL;
pSite = malloc(sizeof(SITE_RECORD));
if (pSite == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
RtlZeroMemory(pSite, sizeof(SITE_RECORD));
pSite->SiteId = SiteId;
EnterTracelibCritSection();
InsertHeadList( &CurrentSystem.SiteListHead, &pSite->Entry );
LeaveTracelibCritSection();
return pSite;
}
PSITE_RECORD
FindOrAddSiteRecord(
ULONG SiteId
)
{
PSITE_RECORD pSite = NULL;
pSite = FindSiteRecord(SiteId);
if (pSite == NULL) {
pSite = AddSiteRecord(SiteId);
}
return pSite;
}
PURL_RECORD
GetHeadUrlRecord(
ULONG index
)
{
PLIST_ENTRY Head, Next;
PURL_RECORD pUrl = NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.URLHashList[index];
Next = Head->Flink;
if (Next != Head) {
pUrl = CONTAINING_RECORD ( Next, URL_RECORD, Entry );
RemoveEntryList( &pUrl->Entry );
}
LeaveTracelibCritSection();
return pUrl;
}
PCLIENT_RECORD
GetHeadClientRecord()
{
PLIST_ENTRY Head, Next;
PCLIENT_RECORD pClient = NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.ClientListHead;
Next = Head->Flink;
if (Next != Head) {
pClient = CONTAINING_RECORD ( Next, CLIENT_RECORD, Entry );
RemoveEntryList( &pClient->Entry );
}
LeaveTracelibCritSection();
return pClient;
}
PSITE_RECORD
GetHeadSiteRecord()
{
PLIST_ENTRY Head, Next;
PSITE_RECORD pSite = NULL;
EnterTracelibCritSection();
Head = &CurrentSystem.SiteListHead;
Next = Head->Flink;
if (Next != Head) {
pSite = CONTAINING_RECORD ( Next, SITE_RECORD, Entry );
RemoveEntryList( &pSite->Entry );
}
LeaveTracelibCritSection();
return pSite;
}
//
// Deletes a Job record with the JobId. Before deleting the contents
// of the job record is dumped to a temp file for later reporting.
//
ULONG
DeletePrintJobRecord(
PPRINT_JOB_RECORD pJob,
ULONG bSave
)
{
if (pJob == NULL)
return ERROR_INVALID_PARAMETER;
//
// Print the Contents of pJob to file.
//
// If the -spooler option isn't given to the reducer this fprintf causes the
// program to crash. Maybe TRACE_SPOOLER should alway be set.
if (CurrentSystem.TempPrintFile != NULL && bSave) {
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->JobId);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->KCPUTime);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->UCPUTime);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->ReadIO);
fprintf(CurrentSystem.TempPrintFile, "%I64u, ", pJob->StartTime);
fprintf(CurrentSystem.TempPrintFile, "%I64u, ", pJob->EndTime);
fprintf(CurrentSystem.TempPrintFile, "%I64u, ", (pJob->ResponseTime - pJob->PauseTime));
fprintf(CurrentSystem.TempPrintFile, "%I64u, ", pJob->PrintJobTime);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->WriteIO);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->DataType);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->JobSize);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->Pages);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->PagesPerSide);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->FilesOpened);
fprintf(CurrentSystem.TempPrintFile, "%d, ", pJob->GdiJobSize);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->Color);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->XRes);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->YRes);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->Quality);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->Copies);
fprintf(CurrentSystem.TempPrintFile, "%hd, ", pJob->TTOption);
fprintf(CurrentSystem.TempPrintFile, "%d\n", pJob->NumberOfThreads);
}
EnterTracelibCritSection();
RemoveEntryList( &pJob->Entry );
InsertHeadList( &CurrentSystem.FreePrintJobListHead, &pJob->Entry );
LeaveTracelibCritSection();
return ERROR_SUCCESS;
}
ULONG
DeleteHttpReqRecord(
PHTTP_REQUEST_RECORD pReq,
ULONG bSave
)
{
if (pReq == NULL)
return ERROR_INVALID_PARAMETER;
//
// Print the Contents of pReq to file.
//
if (CurrentSystem.TempIisFile != NULL && bSave) {
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->RequestId);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->SiteId);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->KCPUTime);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->UCPUTime);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ReadIO);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->WriteIO);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULStartTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULEndTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULResponseTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULParseTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULDeliverTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ULReceiveTime);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->ULReceiveType);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->ULEndType);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->W3StartTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->W3EndTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->W3FilterResponseTime);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->W3ProcessType);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->W3EndType);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->FileReqTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->CGIStartTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->CGIEndTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ISAPIStartTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ISAPIEndTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ASPStartTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->ASPEndTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->SSLResponseTime);
fprintf(CurrentSystem.TempIisFile, "%I64u, ", pReq->StrmFltrResponseTime);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->HttpStatus);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IsapiExt);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrType);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->IpAddrV4);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[0]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[1]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[2]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[3]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[4]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[5]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[6]);
fprintf(CurrentSystem.TempIisFile, "%hd, ", pReq->IpAddrV6[7]);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->NumberOfThreads);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->BytesSent);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ULCPUTime);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->W3CPUTime);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->W3FltrCPUTime);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ISAPICPUTime);
fprintf(CurrentSystem.TempIisFile, "%d, ", pReq->ASPCPUTime);
fprintf(CurrentSystem.TempIisFile, "%d,", pReq->CGICPUTime);
if (pReq->URL != NULL) {
fprintf(CurrentSystem.TempIisFile, "%s\n", pReq->URL);
free(pReq->URL);
}
else {
fprintf(CurrentSystem.TempIisFile, "Unknown\n");
}
}
EnterTracelibCritSection();
RemoveEntryList( &pReq->Entry );
InsertHeadList( &CurrentSystem.FreeHttpReqListHead, &pReq->Entry );
LeaveTracelibCritSection();
return ERROR_SUCCESS;
}
ULONG
DeleteUrlRecord(
PURL_RECORD pUrl
)
{
if (pUrl == NULL)
return ERROR_INVALID_PARAMETER;
if (pUrl->URL != NULL) {
free(pUrl->URL);
}
EnterTracelibCritSection();
RemoveEntryList( &pUrl->Entry );
InsertHeadList( &CurrentSystem.FreeURLListHead, &pUrl->Entry );
LeaveTracelibCritSection();
return ERROR_SUCCESS;
}
ULONG
DeleteClientRecord(
PCLIENT_RECORD pClient
)
{
if (pClient == NULL)
return ERROR_INVALID_PARAMETER;
EnterTracelibCritSection();
RemoveEntryList( &pClient->Entry );
LeaveTracelibCritSection();
free(pClient);
return ERROR_SUCCESS;
}
ULONG
DeleteSiteRecord(
PSITE_RECORD pSite
)
{
if (pSite == NULL)
return ERROR_INVALID_PARAMETER;
EnterTracelibCritSection();
RemoveEntryList( &pSite->Entry );
LeaveTracelibCritSection();
free(pSite);
return ERROR_SUCCESS;
}