727 lines
23 KiB
C
727 lines
23 KiB
C
|
//
|
||
|
// Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
|
||
|
//
|
||
|
// MODULE: server.c
|
||
|
//
|
||
|
// PURPOSE: Implements the body of the Relstat RPC service
|
||
|
//
|
||
|
// FUNCTIONS:
|
||
|
// Called by service.c:
|
||
|
// ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
|
||
|
// ServiceStop( );
|
||
|
//
|
||
|
// Called by RPC:
|
||
|
//
|
||
|
// COMMENTS: The ServerStart and ServerStop functions implemented here are
|
||
|
// prototyped in service.h. The other functions are RPC manager
|
||
|
// functions prototypes in relstat.h
|
||
|
//
|
||
|
//
|
||
|
// AUTHOR: Anitha Panapakkam
|
||
|
//
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <assert.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
#include <io.h>
|
||
|
#include <srvfsctl.h>
|
||
|
#include <tchar.h>
|
||
|
#include <rpc.h>
|
||
|
#include "service.h"
|
||
|
#include "relstat.h"
|
||
|
|
||
|
//
|
||
|
// RPC configuration.
|
||
|
//
|
||
|
|
||
|
// This service listens to all the protseqs listed in this array.
|
||
|
// This should be read from the service's configuration in the
|
||
|
// registery.
|
||
|
TCHAR *ProtocolArray[] = { TEXT("ncalrpc"),
|
||
|
TEXT("ncacn_ip_tcp"),
|
||
|
TEXT("ncacn_np"),
|
||
|
TEXT("ncadg_ip_udp")
|
||
|
};
|
||
|
#define BUFFER_SIZE2 256*1024
|
||
|
// Used in RpcServerUseProtseq, for some protseqs
|
||
|
// this is used as a hint for buffer size.
|
||
|
ULONG ProtocolBuffer = 3;
|
||
|
|
||
|
// Use in RpcServerListen(). More threads will increase performance,
|
||
|
// but use more memory.
|
||
|
ULONG MinimumThreads = 3;
|
||
|
|
||
|
BOOLEAN
|
||
|
CheckFilters (
|
||
|
PSYSTEM_POOLTAG TagInfo,
|
||
|
LPCSTR szTag
|
||
|
);
|
||
|
//
|
||
|
// FUNCTION: ServiceStart
|
||
|
//
|
||
|
// PURPOSE: Actual code of the service
|
||
|
// that does the work.
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
// dwArgc - number of command line arguments
|
||
|
// lpszArgv - array of command line arguments
|
||
|
//
|
||
|
// RETURN VALUE:
|
||
|
// none
|
||
|
//
|
||
|
// COMMENTS:
|
||
|
// Starts the service listening for RPC requests.
|
||
|
//
|
||
|
VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
|
||
|
{
|
||
|
UINT i;
|
||
|
RPC_BINDING_VECTOR *pbindingVector = 0;
|
||
|
RPC_STATUS status;
|
||
|
BOOL fListening = FALSE;
|
||
|
|
||
|
///////////////////////////////////////////////////
|
||
|
//
|
||
|
// Service initialization
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Use protocol sequences (protseqs) specified in ProtocolArray.
|
||
|
//
|
||
|
|
||
|
for(i = 0; i < sizeof(ProtocolArray)/sizeof(TCHAR *); i++)
|
||
|
{
|
||
|
|
||
|
// Report the status to the service control manager.
|
||
|
if (!ReportStatusToSCMgr(
|
||
|
SERVICE_START_PENDING, // service state
|
||
|
NO_ERROR, // exit code
|
||
|
3000)) // wait hint
|
||
|
return;
|
||
|
|
||
|
|
||
|
status = RpcServerUseProtseq(ProtocolArray[i],
|
||
|
ProtocolBuffer,
|
||
|
0);
|
||
|
|
||
|
if (status == RPC_S_OK)
|
||
|
{
|
||
|
fListening = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!fListening)
|
||
|
{
|
||
|
// Unable to listen to any protocol!
|
||
|
//
|
||
|
AddToMessageLog(TEXT("RpcServerUseProtseq() failed\n"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Report the status to the service control manager.
|
||
|
//
|
||
|
if (!ReportStatusToSCMgr(
|
||
|
SERVICE_START_PENDING, // service state
|
||
|
NO_ERROR, // exit code
|
||
|
3000)) // wait hint
|
||
|
return;
|
||
|
|
||
|
// Register the services interface(s).
|
||
|
//
|
||
|
|
||
|
status = RpcServerRegisterIf(RelstatRPCService_ServerIfHandle, // from relstat.h
|
||
|
0,
|
||
|
0);
|
||
|
|
||
|
|
||
|
if (status != RPC_S_OK)
|
||
|
return;
|
||
|
|
||
|
// Report the status to the service control manager.
|
||
|
//
|
||
|
if (!ReportStatusToSCMgr(
|
||
|
SERVICE_START_PENDING, // service state
|
||
|
NO_ERROR, // exit code
|
||
|
3000)) // wait hint
|
||
|
return;
|
||
|
|
||
|
|
||
|
// Register interface(s) and binding(s) (endpoints) with
|
||
|
// the endpoint mapper.
|
||
|
//
|
||
|
|
||
|
status = RpcServerInqBindings(&pbindingVector);
|
||
|
|
||
|
if (status != RPC_S_OK)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
status = RpcEpRegister(RelstatRPCService_ServerIfHandle, // from rpcsvc.h
|
||
|
pbindingVector,
|
||
|
0,
|
||
|
0);
|
||
|
|
||
|
if (status != RPC_S_OK)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Report the status to the service control manager.
|
||
|
//
|
||
|
if (!ReportStatusToSCMgr(
|
||
|
SERVICE_START_PENDING, // service state
|
||
|
NO_ERROR, // exit code
|
||
|
3000)) // wait hint
|
||
|
return;
|
||
|
|
||
|
// Enable NT LM Security Support Provider (NtLmSsp service)
|
||
|
//
|
||
|
status = RpcServerRegisterAuthInfo(0,
|
||
|
RPC_C_AUTHN_WINNT,
|
||
|
0,
|
||
|
0
|
||
|
);
|
||
|
if (status != RPC_S_OK)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Report the status to the service control manager.
|
||
|
//
|
||
|
if (!ReportStatusToSCMgr(
|
||
|
SERVICE_START_PENDING, // service state
|
||
|
NO_ERROR, // exit code
|
||
|
3000)) // wait hint
|
||
|
return;
|
||
|
|
||
|
|
||
|
// Start accepting client calls.
|
||
|
//
|
||
|
status = RpcServerListen(MinimumThreads,
|
||
|
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // rpcdce.h
|
||
|
TRUE); // don't block.
|
||
|
|
||
|
if (status != RPC_S_OK)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Report the status to the service control manager.
|
||
|
//
|
||
|
if (!ReportStatusToSCMgr(
|
||
|
SERVICE_RUNNING, // service state
|
||
|
NO_ERROR, // exit code
|
||
|
0)) // wait hint
|
||
|
return;
|
||
|
|
||
|
//
|
||
|
// End of initialization
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////
|
||
|
|
||
|
////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Cleanup
|
||
|
//
|
||
|
|
||
|
// RpcMgmtWaitServerListen() will block until the server has
|
||
|
// stopped listening. If this service had something better to
|
||
|
// do with this thread, it would delay this call until
|
||
|
// ServiceStop() had been called. (Set an event in ServiceStop()).
|
||
|
//
|
||
|
status = RpcMgmtWaitServerListen();
|
||
|
|
||
|
// ASSERT(status == RPC_S_OK)
|
||
|
|
||
|
// Remove entries from the endpoint mapper database.
|
||
|
//
|
||
|
RpcEpUnregister(RelstatRPCService_ServerIfHandle, // from rpcsvc.h
|
||
|
pbindingVector,
|
||
|
0);
|
||
|
|
||
|
// Delete the binding vector
|
||
|
//
|
||
|
RpcBindingVectorFree(&pbindingVector);
|
||
|
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// FUNCTION: ServiceStop
|
||
|
//
|
||
|
// PURPOSE: Stops the service
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
// none
|
||
|
//
|
||
|
// RETURN VALUE:
|
||
|
// none
|
||
|
//
|
||
|
// COMMENTS:
|
||
|
// If a ServiceStop procedure is going to
|
||
|
// take longer than 3 seconds to execute,
|
||
|
// it should spawn a thread to execute the
|
||
|
// stop code, and return. Otherwise, the
|
||
|
// ServiceControlManager will believe that
|
||
|
// the service has stopped responding.
|
||
|
//
|
||
|
VOID ServiceStop()
|
||
|
{
|
||
|
// Stop's the server, wakes the main thread.
|
||
|
|
||
|
RpcMgmtStopServerListening(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
error_status_t
|
||
|
RelStatProcessInfo(
|
||
|
handle_t h,
|
||
|
LONG Pid,
|
||
|
ULONG *pNumberOfProcesses,
|
||
|
PRELSTAT_PROCESS_INFO *ppRelStatProcessInfo)
|
||
|
{
|
||
|
PSYSTEM_PROCESS_INFORMATION pProcessInfo = NULL;
|
||
|
PRELSTAT_PROCESS_INFO pProcessArray = NULL;
|
||
|
ULONG TotalOffset=0;
|
||
|
ULONG NumberOfProcesses = 1; //atleast one process
|
||
|
ULONG NumAlloc = 0;
|
||
|
ULONG i,index,dwMatches = 0;
|
||
|
PBYTE pProcessBuffer = NULL;
|
||
|
NTSTATUS Status= STATUS_INFO_LENGTH_MISMATCH;
|
||
|
DWORD ByteCount = 32768; //TODO : tune it on a "typical system"
|
||
|
DWORD RequiredByteCount = 0;
|
||
|
BOOL fCheck = FALSE;
|
||
|
HANDLE hProcess; // process handle
|
||
|
|
||
|
//two iterations of NtQuerySystemInformation will happen
|
||
|
//can see if there is any other way to allocate a big buffer.
|
||
|
while ( Status == STATUS_INFO_LENGTH_MISMATCH)
|
||
|
{
|
||
|
//
|
||
|
// Allocate a buffer
|
||
|
//
|
||
|
pProcessBuffer = MIDL_user_allocate(ByteCount);
|
||
|
|
||
|
if (pProcessBuffer == NULL)
|
||
|
{
|
||
|
Status = STATUS_NO_MEMORY;
|
||
|
*pNumberOfProcesses = 0;
|
||
|
*ppRelStatProcessInfo = NULL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Perform process enumeration.
|
||
|
//
|
||
|
Status = NtQuerySystemInformation( SystemProcessInformation,
|
||
|
(PVOID)pProcessBuffer,
|
||
|
ByteCount,
|
||
|
&RequiredByteCount );
|
||
|
if (Status == STATUS_INFO_LENGTH_MISMATCH)
|
||
|
{
|
||
|
ByteCount = RequiredByteCount+4096;
|
||
|
if (pProcessBuffer)
|
||
|
LocalFree(pProcessBuffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Status == STATUS_SUCCESS)
|
||
|
{
|
||
|
//walk the returned buffer to get the # of processes
|
||
|
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pProcessBuffer;
|
||
|
TotalOffset = 0;
|
||
|
|
||
|
//client has specified a Pid
|
||
|
if (Pid >= 0)
|
||
|
fCheck = TRUE;
|
||
|
|
||
|
while(pProcessInfo->NextEntryOffset != 0)
|
||
|
{
|
||
|
if ((fCheck == TRUE) &&
|
||
|
(PtrToLong(pProcessInfo->UniqueProcessId) == Pid))
|
||
|
{
|
||
|
//Pid matched. exit from the while loop
|
||
|
// no need to count the processes anymore
|
||
|
//fExit = TRUE;
|
||
|
dwMatches++;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NumberOfProcesses++;
|
||
|
TotalOffset += pProcessInfo->NextEntryOffset;
|
||
|
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
|
||
|
&pProcessBuffer[TotalOffset];
|
||
|
}
|
||
|
|
||
|
printf("Num Processes = %ul, Matches %d \n",NumberOfProcesses,
|
||
|
dwMatches);
|
||
|
|
||
|
if (dwMatches > 0)
|
||
|
NumAlloc = dwMatches;
|
||
|
else
|
||
|
NumAlloc = NumberOfProcesses;
|
||
|
|
||
|
pProcessArray = MIDL_user_allocate(NumAlloc *
|
||
|
sizeof (RELSTAT_PROCESS_INFO));
|
||
|
|
||
|
if (pProcessArray == NULL)
|
||
|
{
|
||
|
printf("No memory for pProcessArray\n");
|
||
|
Status = STATUS_NO_MEMORY;
|
||
|
LocalFree(pProcessBuffer);
|
||
|
pProcessBuffer = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RtlZeroMemory(pProcessArray, NumAlloc *
|
||
|
sizeof(RELSTAT_PROCESS_INFO));
|
||
|
Status = STATUS_SUCCESS;
|
||
|
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pProcessBuffer;
|
||
|
TotalOffset = 0;
|
||
|
|
||
|
//walk the returned buffer and copy to pProcessArray
|
||
|
|
||
|
for(i=0;i<NumberOfProcesses;i++)
|
||
|
{
|
||
|
if (dwMatches > 0)
|
||
|
{
|
||
|
if(PtrToLong(pProcessInfo->UniqueProcessId) != Pid)
|
||
|
goto End;
|
||
|
else
|
||
|
index = dwMatches-1;
|
||
|
}
|
||
|
else
|
||
|
index = i;
|
||
|
|
||
|
pProcessArray[index].NumberOfThreads = pProcessInfo->NumberOfThreads;
|
||
|
pProcessArray[index].CreateTime = pProcessInfo->CreateTime;
|
||
|
pProcessArray[index].UserTime = pProcessInfo->UserTime;
|
||
|
pProcessArray[index].KernelTime = pProcessInfo->KernelTime;
|
||
|
//create a null terminated imagename string
|
||
|
pProcessArray[index].szImageName = MIDL_user_allocate((pProcessInfo->ImageName.Length+1)*2);
|
||
|
if (pProcessInfo->ImageName.Length > 0)
|
||
|
{
|
||
|
wcsncpy(pProcessArray[index].szImageName,
|
||
|
pProcessInfo->ImageName.Buffer,
|
||
|
pProcessInfo->ImageName.Length);
|
||
|
}
|
||
|
pProcessArray[index].szImageName[pProcessInfo->ImageName.Length] = L'\0';
|
||
|
|
||
|
pProcessArray[index].BasePriority = pProcessInfo->BasePriority;
|
||
|
pProcessArray[index].UniqueProcessId = PtrToLong(pProcessInfo->UniqueProcessId);
|
||
|
pProcessArray[index].InheritedFromUniqueProcessId = PtrToLong(pProcessInfo->InheritedFromUniqueProcessId);
|
||
|
|
||
|
pProcessArray[index].HandleCount = pProcessInfo->HandleCount;
|
||
|
pProcessArray[index].SessionId = pProcessInfo->SessionId;
|
||
|
pProcessArray[index].PeakVirtualSize = pProcessInfo->PeakVirtualSize;
|
||
|
pProcessArray[index].VirtualSize = pProcessInfo->VirtualSize;
|
||
|
pProcessArray[index].PageFaultCount = pProcessInfo->PageFaultCount;
|
||
|
pProcessArray[index].PeakWorkingSetSize = pProcessInfo->PeakWorkingSetSize;
|
||
|
pProcessArray[index].WorkingSetSize = pProcessInfo->WorkingSetSize;
|
||
|
pProcessArray[index].QuotaPeakPagedPoolUsage = pProcessInfo->QuotaPeakPagedPoolUsage;
|
||
|
|
||
|
pProcessArray[index].QuotaPagedPoolUsage = pProcessInfo->QuotaPagedPoolUsage;
|
||
|
|
||
|
pProcessArray[index].QuotaPeakNonPagedPoolUsage = pProcessInfo->QuotaPeakNonPagedPoolUsage;
|
||
|
|
||
|
pProcessArray[index].QuotaNonPagedPoolUsage = pProcessInfo->QuotaNonPagedPoolUsage;
|
||
|
|
||
|
pProcessArray[index].PagefileUsage = pProcessInfo->PagefileUsage;
|
||
|
pProcessArray[index].PeakPagefileUsage = pProcessInfo->PeakPagefileUsage;
|
||
|
pProcessArray[index].PrivatePageCount = pProcessInfo->PrivatePageCount;
|
||
|
pProcessArray[index].ReadOperationCount = pProcessInfo->ReadOperationCount;
|
||
|
pProcessArray[index].WriteOperationCount = pProcessInfo->WriteOperationCount;
|
||
|
pProcessArray[index].OtherOperationCount = pProcessInfo->OtherOperationCount;
|
||
|
pProcessArray[index].ReadTransferCount = pProcessInfo->ReadTransferCount;
|
||
|
pProcessArray[index].WriteTransferCount = pProcessInfo->WriteTransferCount;
|
||
|
pProcessArray[index].OtherTransferCount = pProcessInfo->OtherTransferCount;
|
||
|
|
||
|
pProcessArray[index].GdiHandleCount = 0;
|
||
|
|
||
|
|
||
|
hProcess= OpenProcess( PROCESS_QUERY_INFORMATION,
|
||
|
FALSE,
|
||
|
PtrToUlong(pProcessInfo->UniqueProcessId) );
|
||
|
if( hProcess ) {
|
||
|
pProcessArray[index].GdiHandleCount = GetGuiResources( hProcess, GR_GDIOBJECTS );
|
||
|
pProcessArray[index].UsrHandleCount= GetGuiResources( hProcess, GR_USEROBJECTS );
|
||
|
CloseHandle( hProcess );
|
||
|
}
|
||
|
|
||
|
End:
|
||
|
TotalOffset += pProcessInfo->NextEntryOffset;
|
||
|
|
||
|
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pProcessBuffer[TotalOffset];
|
||
|
} //end of for loop
|
||
|
|
||
|
} //end of else
|
||
|
|
||
|
} //end of if
|
||
|
|
||
|
|
||
|
if (NT_SUCCESS(Status))
|
||
|
{
|
||
|
*pNumberOfProcesses = NumAlloc;
|
||
|
*ppRelStatProcessInfo = pProcessArray;
|
||
|
|
||
|
//print some debug messages
|
||
|
printf("Query system info passed\n");
|
||
|
printf("%d number of processes \n",*pNumberOfProcesses);
|
||
|
/*
|
||
|
for(i=0; i< *pNumberOfProcesses; i++)
|
||
|
{
|
||
|
printf("%d%10u%10u%10u%10u%10u%10u%10u\n",
|
||
|
pProcessArray[i].UniqueProcessId,
|
||
|
pProcessArray[i].WorkingSetSize,
|
||
|
pProcessArray[i].QuotaPagedPoolUsage,
|
||
|
pProcessArray[i].QuotaNonPagedPoolUsage,
|
||
|
pProcessArray[i].PagefileUsage,
|
||
|
pProcessArray[i].PrivatePageCount,
|
||
|
pProcessArray[i].HandleCount,
|
||
|
pProcessArray[i].NumberOfThreads);
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pNumberOfProcesses = 0;
|
||
|
*ppRelStatProcessInfo = NULL;
|
||
|
|
||
|
if (pProcessArray)
|
||
|
LocalFree(pProcessArray);
|
||
|
pProcessArray = NULL;
|
||
|
printf("Query system info failed\n");
|
||
|
}
|
||
|
|
||
|
if (pProcessBuffer)
|
||
|
LocalFree(pProcessBuffer);
|
||
|
pProcessBuffer = NULL;
|
||
|
|
||
|
//print a debug message to catch errors in case of marshalling or anything
|
||
|
//else
|
||
|
|
||
|
printf("Fine before return\n");
|
||
|
return (RtlNtStatusToDosError(Status));
|
||
|
}
|
||
|
|
||
|
error_status_t
|
||
|
RelStatPoolTagInfo(
|
||
|
handle_t h,
|
||
|
LPSTR szPoolTag,
|
||
|
ULONG *pNumberOfPoolTags,
|
||
|
PRELSTAT_POOLTAG_INFO *ppRelStatPoolTagInfo)
|
||
|
{
|
||
|
PSYSTEM_POOLTAG_INFORMATION PoolInfo;
|
||
|
#define BUFFER_SIZE 128*1024
|
||
|
UCHAR CurrentBuffer[BUFFER_SIZE];
|
||
|
NTSTATUS Status; // status from NT api
|
||
|
ULONG i;
|
||
|
PRELSTAT_POOLTAG_INFO pPoolTagArray=NULL;
|
||
|
PRELSTAT_POOLTAG_INFO pPoolTagMatchArray=NULL;
|
||
|
BOOLEAN filter = FALSE;
|
||
|
DWORD dwMatchCount = 0;
|
||
|
|
||
|
printf("Filter specified is %S \n", szPoolTag);
|
||
|
|
||
|
Status = NtQuerySystemInformation(
|
||
|
SystemPoolTagInformation,
|
||
|
CurrentBuffer,
|
||
|
BUFFER_SIZE,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
PoolInfo = (PSYSTEM_POOLTAG_INFORMATION)CurrentBuffer;
|
||
|
printf("Query Info returned %x\n",Status);
|
||
|
|
||
|
|
||
|
if (szPoolTag) //check to see if pooltag filter specified
|
||
|
filter = TRUE;
|
||
|
|
||
|
if(NT_SUCCESS(Status) && (PoolInfo->Count > 0))
|
||
|
{
|
||
|
printf("%u Number of Tags \n",PoolInfo->Count);
|
||
|
pPoolTagArray = MIDL_user_allocate(PoolInfo->Count *
|
||
|
sizeof(SYSTEM_POOLTAG));
|
||
|
|
||
|
if (!pPoolTagArray)
|
||
|
{
|
||
|
Status = STATUS_NO_MEMORY;
|
||
|
printf("System out of memory for pooltaginfo\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
for(i=0 ; i < PoolInfo->Count ; i++)
|
||
|
{
|
||
|
|
||
|
if (filter && !CheckFilters(&PoolInfo->TagInfo[i],szPoolTag))
|
||
|
continue;
|
||
|
|
||
|
memcpy(pPoolTagArray[dwMatchCount].Tag, PoolInfo->TagInfo[i].Tag, 4);
|
||
|
pPoolTagArray[dwMatchCount].PagedAllocs = PoolInfo->TagInfo[i].PagedAllocs;
|
||
|
pPoolTagArray[dwMatchCount].PagedFrees = PoolInfo->TagInfo[i].PagedFrees;
|
||
|
pPoolTagArray[dwMatchCount].PagedUsed = PoolInfo->TagInfo[i].PagedUsed;
|
||
|
pPoolTagArray[dwMatchCount].NonPagedAllocs =PoolInfo->TagInfo[i].NonPagedAllocs;
|
||
|
pPoolTagArray[dwMatchCount].NonPagedFrees = PoolInfo->TagInfo[i].NonPagedFrees;
|
||
|
pPoolTagArray[dwMatchCount].NonPagedUsed = PoolInfo->TagInfo[i].NonPagedUsed;
|
||
|
dwMatchCount++;
|
||
|
//need to include union info
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (NT_SUCCESS(Status))
|
||
|
{
|
||
|
if ((filter) && (dwMatchCount < PoolInfo->Count))
|
||
|
{
|
||
|
//allocate and copy only the matched pooltags
|
||
|
|
||
|
pPoolTagMatchArray = MIDL_user_allocate(dwMatchCount *
|
||
|
sizeof(SYSTEM_POOLTAG));
|
||
|
|
||
|
if (!pPoolTagMatchArray)
|
||
|
{
|
||
|
Status = STATUS_NO_MEMORY;
|
||
|
printf("System out of memory for pooltaginfo matches\n");
|
||
|
}
|
||
|
|
||
|
for(i=0;i<dwMatchCount;i++)
|
||
|
{
|
||
|
|
||
|
memcpy(pPoolTagMatchArray[i].Tag, pPoolTagArray[i].Tag,4);
|
||
|
pPoolTagMatchArray[i].PagedAllocs = pPoolTagArray[i].PagedAllocs;
|
||
|
pPoolTagMatchArray[i].PagedFrees = pPoolTagArray[i].PagedFrees;
|
||
|
pPoolTagMatchArray[i].PagedUsed = pPoolTagArray[i].PagedUsed;
|
||
|
pPoolTagMatchArray[i].NonPagedAllocs = pPoolTagArray[i].NonPagedAllocs;
|
||
|
pPoolTagMatchArray[i].NonPagedFrees = pPoolTagArray[i].NonPagedFrees;
|
||
|
pPoolTagMatchArray[i].NonPagedUsed = pPoolTagArray[i].NonPagedUsed;
|
||
|
|
||
|
}
|
||
|
*ppRelStatPoolTagInfo = pPoolTagMatchArray;
|
||
|
*pNumberOfPoolTags = dwMatchCount;
|
||
|
printf("RelStatPoolTagInfo returned TRUE \n");
|
||
|
printf("%u Number of Tags \n",*pNumberOfPoolTags);
|
||
|
MIDL_user_free(pPoolTagArray);
|
||
|
}
|
||
|
else
|
||
|
{ // no filter specified or all the tags need to be sent
|
||
|
*ppRelStatPoolTagInfo = pPoolTagArray;
|
||
|
*pNumberOfPoolTags = PoolInfo->Count;
|
||
|
printf("RelStatPoolTagInfo returned TRUE \n");
|
||
|
printf("%u Number of Tags \n",*pNumberOfPoolTags);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppRelStatPoolTagInfo = NULL;
|
||
|
*pNumberOfPoolTags = 0;
|
||
|
printf("RelStatPoolTagInfo returned FALSE %x \n",Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
return (RtlNtStatusToDosError(Status));
|
||
|
// return ( (NT_SUCCESS(*pResult))?TRUE : FALSE);
|
||
|
}
|
||
|
|
||
|
error_status_t
|
||
|
RelStatBuildNumber(handle_t h,
|
||
|
ULONG* ulBuildNumber)
|
||
|
{
|
||
|
OSVERSIONINFO osVer;
|
||
|
|
||
|
osVer.dwOSVersionInfoSize = sizeof(osVer);
|
||
|
if (GetVersionEx(&osVer))
|
||
|
{
|
||
|
*ulBuildNumber = osVer.dwBuildNumber;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
return RtlNtStatusToDosError(GetLastError());
|
||
|
}
|
||
|
|
||
|
error_status_t
|
||
|
RelStatTickCount(handle_t h,
|
||
|
ULONG* ulTickCount)
|
||
|
{
|
||
|
*ulTickCount = GetTickCount();
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
CheckSingleFilter (
|
||
|
PCHAR Tag,
|
||
|
LPCSTR Filter
|
||
|
)
|
||
|
{
|
||
|
ULONG i;
|
||
|
CHAR tc;
|
||
|
CHAR fc;
|
||
|
|
||
|
|
||
|
for ( i = 0; i < 4; i++ ) {
|
||
|
tc = *Tag++;
|
||
|
fc = *Filter++;
|
||
|
if ( fc == '*' ) return TRUE;
|
||
|
if ( fc == '?' ) continue;
|
||
|
if ( tc != fc ) return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
CheckFilters (
|
||
|
PSYSTEM_POOLTAG TagInfo,
|
||
|
LPCSTR szTag
|
||
|
)
|
||
|
{
|
||
|
BOOLEAN pass = FALSE;
|
||
|
ULONG i;
|
||
|
PCHAR tag;
|
||
|
|
||
|
tag = TagInfo->Tag;
|
||
|
if ( CheckSingleFilter( tag, szTag ))
|
||
|
pass = TRUE;
|
||
|
|
||
|
|
||
|
return pass;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// FUNCTIONS: MIDL_user_allocate and MIDL_user_free
|
||
|
//
|
||
|
// PURPOSE: Used by stubs to allocate and free memory
|
||
|
// in standard RPC calls. Not used when
|
||
|
// [enable_allocate] is specified in the .acf.
|
||
|
//
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
// See documentations.
|
||
|
//
|
||
|
// RETURN VALUE:
|
||
|
// Exceptions on error. This is not required,
|
||
|
// you can use -error allocation on the midl.exe
|
||
|
// command line instead.
|
||
|
//
|
||
|
//
|
||
|
|
||
|
void * __RPC_USER MIDL_user_allocate(size_t size)
|
||
|
{
|
||
|
return(HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, size));
|
||
|
}
|
||
|
|
||
|
void __RPC_USER MIDL_user_free( void *pointer)
|
||
|
{
|
||
|
HeapFree(GetProcessHeap(), 0, pointer);
|
||
|
}
|
||
|
|