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.
5206 lines
146 KiB
5206 lines
146 KiB
/*++
|
|
|
|
Copyright (c) 2001-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
snapshot.cpp
|
|
|
|
Abstract:
|
|
|
|
This module implements snapshot.dll which will be called
|
|
by user32 at unplanned shutdown to take a snapshot of the
|
|
system hardware, OS, and process information.
|
|
|
|
Author:
|
|
|
|
Qingbo Zhao (qingboz) 01-Feb-2001
|
|
|
|
Revision History:
|
|
|
|
JeffMeng Dec-03-2001
|
|
Swethan Jul-31-2002 Added pool information
|
|
|
|
--*/
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <wtypes.h>
|
|
#include <mountmgr.h>
|
|
#include <winioctl.h>
|
|
#include <ntddvol.h>
|
|
#include <ntddscsi.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <tchar.h>
|
|
#include <rpcdce.h>
|
|
|
|
#define _stnprintf _snwprintf
|
|
#define _tsizeof(X) (sizeof(X) / sizeof(*X))
|
|
#define BUFFER_SIZE 64*1024*sizeof(TCHAR)
|
|
#define MIN_BUFFER_SIZE 1024*sizeof(TCHAR)
|
|
#define MAX_BUFFER_SIZE 10*1024*1024*sizeof(TCHAR)
|
|
#define MAXSTR 4*1024
|
|
#define DEFAULT_HISTORYFILES 10
|
|
#define MAX_HISTORYFILES 365
|
|
#define DEFAULT_TIMEOUT 30
|
|
#define MIN_TIMEOUT 2
|
|
#define MAX_TIMEOUT 10 * 60
|
|
#define NUM_OF_CHAR_IN_ULONG64 30
|
|
#define ReliabilityKey L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\Reliability"
|
|
|
|
#define SCHEMA_VERSION_STRING L"1.0"
|
|
//
|
|
// the amount of memory to increase the size
|
|
// of the buffer for NtQuerySystemInformation at each step
|
|
//
|
|
#define BUFFER_SIZE_STEP 65536
|
|
|
|
|
|
void
|
|
WriteToLogFileW(
|
|
HANDLE hFile,
|
|
LPCWSTR lpwszInput
|
|
);
|
|
|
|
void
|
|
WriteToLogFileA(
|
|
HANDLE hFile,
|
|
LPCSTR lpszInput
|
|
);
|
|
|
|
void
|
|
WriteToLogFile(
|
|
HANDLE hFile,
|
|
LPCTSTR lpszInput
|
|
);
|
|
|
|
//
|
|
// Tag enum for XML output.
|
|
//
|
|
enum XMLTAG
|
|
{
|
|
XMLTAG_SETSystemStateData = 0,
|
|
XMLTAG_SETDataType_Header,
|
|
XMLTAG_SETDataType_PageFiles,
|
|
XMLTAG_SETDataType_Memory,
|
|
XMLTAG_SETDataType_PoolInfo,
|
|
|
|
XMLTAG_Memory_PhysicalMemory,
|
|
XMLTAG_Memory_CommittedMemory,
|
|
XMLTAG_Memory_KernelMemory,
|
|
XMLTAG_Memory_Pool,
|
|
XMLTAG_Memory_PageFiles,
|
|
XMLTAG_Memory_memory,
|
|
|
|
XMLTAG_SETDataType_ExtensionDLL,
|
|
XMLTAG_SETDataType_ProcessSummaries,
|
|
XMLTAG_SETDataType_ProcessStartInfo,
|
|
XMLTAG_SETDataType_ProcessesThreadInfo,
|
|
XMLTAG_SETDataType_ProcessesModuleInfo,
|
|
XMLTAG_SETDataType_KernelModuleInfo,
|
|
XMLTAG_SETDataType_OSInfo,
|
|
XMLTAG_SETDataType_HardwareInfo,
|
|
|
|
XMLTAG_HeaderType_ReliabilityGuid,
|
|
XMLTAG_HeaderType_SystemName,
|
|
XMLTAG_HeaderType_UserName,
|
|
XMLTAG_HeaderType_ReasonTitle,
|
|
XMLTAG_HeaderType_ReasonDescription,
|
|
XMLTAG_HeaderType_InitiatingProcess,
|
|
XMLTAG_HeaderType_RestartDate,
|
|
XMLTAG_HeaderType_RestartTime,
|
|
XMLTAG_HeaderType_ReasonCode,
|
|
XMLTAG_HeaderType_RestartType,
|
|
XMLTAG_HeaderType_Comment,
|
|
XMLTAG_HeaderType_SystemUptime,
|
|
XMLTAG_HeaderType_UserLanguageID,
|
|
XMLTAG_HeaderType_SystemLanguageID,
|
|
XMLTAG_HeaderType_SchemaVersion,
|
|
|
|
XMLTAG_PageFileType_PageFile,
|
|
XMLTAG_PageFileType_Path,
|
|
XMLTAG_PageFileType_CurrentSize,
|
|
XMLTAG_PageFileType_Total,
|
|
XMLTAG_PageFileType_Peak,
|
|
XMLTAG_PhysicalMemoryType_Total,
|
|
XMLTAG_PhysicalMemoryType_Available,
|
|
XMLTAG_WorkingSetType_WorkingSet,
|
|
XMLTAG_CommittedMemoryType_Total,
|
|
XMLTAG_CommittedMemoryType_UserMode,
|
|
XMLTAG_CommittedMemoryType_Limit,
|
|
XMLTAG_CommittedMemoryType_Peak,
|
|
XMLTAG_KernelMemoryType_Nonpaged,
|
|
XMLTAG_KernelMemoryType_Paged,
|
|
XMLTAG_PoolType_Nonpaged,
|
|
XMLTAG_PoolType_Paged,
|
|
XMLTAG_PageFilesType_PageFile,
|
|
XMLTAG_memoryType_PhysicalMemory,
|
|
XMLTAG_memoryType_WorkingSet,
|
|
XMLTAG_memoryType_KernelMemory,
|
|
XMLTAG_memoryType_CommittedMemory,
|
|
XMLTAG_memoryType_Pool,
|
|
|
|
XMLTAG_PoolInfo_AllocInformation,
|
|
XMLTAG_PoolInfo_TagEntry,
|
|
XMLTAG_PoolInfo_TagEntry_PoolTag,
|
|
XMLTAG_PoolInfo_TagEntry_PoolType,
|
|
XMLTAG_PoolInfo_TagEntry_NumAllocs,
|
|
XMLTAG_PoolInfo_TagEntry_NumFrees,
|
|
XMLTAG_PoolInfo_TagEntry_NumBytes,
|
|
XMLTAG_PoolInfo_TagEntry_SessionID,
|
|
|
|
XMLTAG_ProcessSummaryType_Process,
|
|
XMLTAG_ProcessSummaryType_PID,
|
|
XMLTAG_ProcessSummaryType_Name,
|
|
XMLTAG_ProcessSummaryType_UserTime,
|
|
XMLTAG_ProcessSummaryType_KernelTime,
|
|
XMLTAG_ProcessSummaryType_WorkingSet,
|
|
XMLTAG_ProcessSummaryType_PageFaults,
|
|
XMLTAG_ProcessSummaryType_CommittedBytes,
|
|
XMLTAG_ProcessSummaryType_Priority,
|
|
XMLTAG_ProcessSummaryType_HandleCount,
|
|
XMLTAG_ProcessSummaryType_ThreadCount,
|
|
|
|
XMLTAG_ProcessStartInfoType_Process,
|
|
XMLTAG_ProcessStartInfoType_PID,
|
|
XMLTAG_ProcessStartInfoType_ImageName,
|
|
XMLTAG_ProcessStartInfoType_CmdLine,
|
|
XMLTAG_ProcessStartInfoType_CurrentDir,
|
|
|
|
XMLTAG_ProcessThreadInfoType_Process,
|
|
XMLTAG_ProcessThreadInfoType_PID,
|
|
XMLTAG_ProcessThreadInfoType_Thread,
|
|
XMLTAG_ProcessThreadInfoType_TID,
|
|
XMLTAG_ProcessThreadInfoType_Priority,
|
|
XMLTAG_ProcessThreadInfoType_ContextSwitches,
|
|
XMLTAG_ProcessThreadInfoType_StartAddress,
|
|
XMLTAG_ProcessThreadInfoType_UserTime,
|
|
XMLTAG_ProcessThreadInfoType_KernelTime,
|
|
XMLTAG_ProcessThreadInfoType_State,
|
|
|
|
XMLTAG_ProcessModuleInfoType_Process,
|
|
XMLTAG_ProcessModuleInfoType_PID,
|
|
XMLTAG_ProcessModuleInfoType_Module,
|
|
XMLTAG_ProcessModuleInfoType_LoadAddr,
|
|
XMLTAG_ProcessModuleInfoType_ImageSize,
|
|
XMLTAG_ProcessModuleInfoType_EntryPoint,
|
|
XMLTAG_ProcessModuleInfoType_FileName,
|
|
|
|
XMLTAG_KernelModuleInfoType_Module,
|
|
XMLTAG_KernelModuleInfoType_ModuleName,
|
|
XMLTAG_KernelModuleInfoType_LoadAddress,
|
|
XMLTAG_KernelModuleInfoType_Code,
|
|
XMLTAG_KernelModuleInfoType_Data,
|
|
XMLTAG_KernelModuleInfoType_Paged,
|
|
XMLTAG_KernelModuleInfoType_Date,
|
|
XMLTAG_KernelModuleInfoType_Time,
|
|
|
|
XMLTAG_KernelModuleInfoType_TotalCode,
|
|
XMLTAG_KernelModuleInfoType_TotalData,
|
|
XMLTAG_KernelModuleInfoType_TotalPaged,
|
|
|
|
XMLTAG_OSInfoType_CurrentBuild,
|
|
XMLTAG_OSInfoType_CurrentType,
|
|
XMLTAG_OSInfoType_CurrentVersion,
|
|
XMLTAG_OSInfoType_Path,
|
|
XMLTAG_OSInfoType_ProductName,
|
|
XMLTAG_OSInfoType_SoftwareType,
|
|
XMLTAG_OSInfoType_SourcePath,
|
|
XMLTAG_OSInfoType_SystemRoot,
|
|
XMLTAG_OSInfoType_CSDVersion,
|
|
XMLTAG_OSInfoType_DebuggerEnabled,
|
|
XMLTAG_OSInfoType_Hotfix,
|
|
XMLTAG_HardwareInfoType_BiosInfo,
|
|
XMLTAG_HardwareInfoType_ProcesorInfo,
|
|
XMLTAG_HardwareInfoType_NICInfo,
|
|
XMLTAG_HardwareInfoType_DiskInfo,
|
|
XMLTAG_BiosInfoType_Identifier,
|
|
XMLTAG_BiosInfoType_SystemBiosDate,
|
|
XMLTAG_BiosInfoType_SystemBiosVersion,
|
|
XMLTAG_BiosInfoType_VideoBiosDate,
|
|
XMLTAG_BiosInfoType_VideoBiosVersion,
|
|
XMLTAG_ProcessorInfoType_Processor,
|
|
XMLTAG_ProcessorInfoType_Number,
|
|
XMLTAG_ProcessorInfoType_Speed,
|
|
XMLTAG_ProcessorInfoType_Identifier,
|
|
XMLTAG_ProcessorInfoType_VendorIdent,
|
|
XMLTAG_NICInfoType_NIC,
|
|
XMLTAG_NICInfoType_Description,
|
|
XMLTAG_NICInfoType_ServiceName,
|
|
|
|
XMLTAG_DiskInfoType_PhysicalInfo,
|
|
XMLTAG_DiskInfoType_PartitionByDiskInfo,
|
|
XMLTAG_DiskInfoType_LogicalDrives,
|
|
|
|
XMLTAG_PhysicalInfoType_Disk, //physical
|
|
XMLTAG_PhysicalInfoType_ID,
|
|
XMLTAG_PhysicalInfoType_BytesPerSector,
|
|
XMLTAG_PhysicalInfoType_SectorsPerTrack,
|
|
XMLTAG_PhysicalInfoType_TracksPerCylinder,
|
|
XMLTAG_PhysicalInfoType_NumberOfCylinders,
|
|
XMLTAG_PhysicalInfoType_PortNumber,
|
|
XMLTAG_PhysicalInfoType_PathID,
|
|
XMLTAG_PhysicalInfoType_TargetID,
|
|
XMLTAG_PhysicalInfoType_LUN,
|
|
XMLTAG_PhysicalInfoType_Manufacturer,
|
|
|
|
XMLTAG_PartitionByDiskInfoType_Disk, //logical
|
|
XMLTAG_PartitionByDiskInfoType_DiskID,
|
|
XMLTAG_PartitionByDiskInfoType_Partitions,
|
|
XMLTAG_PartitionByDiskInfoType_PartitionInfo,
|
|
XMLTAG_PartitionInfoType_PartitionID,
|
|
XMLTAG_PartitionInfoType_Extents,
|
|
XMLTAG_PartitionInfoType_ExtentInfo,
|
|
XMLTAG_ExtentInfoType_ID,
|
|
XMLTAG_ExtentInfoType_StartingOffset,
|
|
XMLTAG_ExtentInfoType_PartitionSize,
|
|
|
|
XMLTAG_LogicalDriveInfoType_LogicalDriveInfo,
|
|
XMLTAG_LogicalDriveInfoType_DrivePath,
|
|
XMLTAG_LogicalDriveInfoType_FreeSpaceBytes,
|
|
XMLTAG_LogicalDriveInfoType_TotalSpaceBytes,
|
|
XMLTAG_Timing,
|
|
|
|
XMLTAG_END //this is to do a check that the number of entries here is the same as the number of entries in XMLTagNames
|
|
//Any additions to this set of enums must be made before XMLTAG_END
|
|
};
|
|
|
|
//
|
|
// Tag names and level for XML output.
|
|
// Note: The number of XMLTagNames should be the same as the number of enum entries above
|
|
//
|
|
|
|
struct XMLTags
|
|
{
|
|
LPCTSTR szName;
|
|
DWORD dwLevel;
|
|
} XMLTagNames[] =
|
|
{
|
|
{TEXT("SETSystemStateData"), 0},
|
|
{TEXT("Header"), 1},
|
|
{TEXT("PageFiles"), 1},
|
|
{TEXT("Memory"), 1},
|
|
{TEXT("PoolInfo"),1},
|
|
|
|
{TEXT("PhysicalMemory"), 2},
|
|
{TEXT("CommittedMemory"), 2},
|
|
{TEXT("KernelMemory"), 2},
|
|
{TEXT("Pool"), 2},
|
|
{TEXT("PageFiles"), 2},
|
|
{TEXT("Memory"), 2},
|
|
|
|
{TEXT("Extension"), 1},
|
|
{TEXT("ProcessSummaries"), 1},
|
|
{TEXT("ProcessStartInfo"), 1},
|
|
{TEXT("ProcessesThreadInfo"), 1},
|
|
{TEXT("ProcessesModuleInfo"), 1},
|
|
{TEXT("KernelModuleInfo"), 1},
|
|
{TEXT("OSInfo"), 1},
|
|
{TEXT("HardwareInfo"), 1},
|
|
|
|
{TEXT("ReliabilityGuid"), 2},
|
|
{TEXT("SystemName"), 2},
|
|
{TEXT("UserName"),2},
|
|
{TEXT("ReasonTitle"),2},
|
|
{TEXT("ReasonDescription"),2},
|
|
{TEXT("InitiatingProcess"), 2},
|
|
{TEXT("RestartDate"), 2},
|
|
{TEXT("RestartTime"), 2},
|
|
{TEXT("ReasonCode"), 2},
|
|
{TEXT("RestartType"), 2},
|
|
{TEXT("Comment"), 2},
|
|
{TEXT("SystemUptime"), 2},
|
|
{TEXT("UserLanguageID"), 2},
|
|
{TEXT("SystemLanguageID"), 2},
|
|
{TEXT("SchemaVersion"),2},
|
|
|
|
{TEXT("PageFile"), 2},
|
|
{TEXT("Path"), 3},
|
|
{TEXT("CurrentSize"), 3},
|
|
{TEXT("Total"), 3},
|
|
{TEXT("Peak"), 3},
|
|
|
|
{TEXT("Total"), 3},
|
|
{TEXT("Available"), 3},
|
|
{TEXT("WorkingSet"),2},
|
|
{TEXT("Total"), 3},
|
|
{TEXT("UserMode"), 3},
|
|
{TEXT("Limit"), 3},
|
|
{TEXT("Peak"), 3},
|
|
{TEXT("Nonpaged"), 3},
|
|
{TEXT("Paged"), 3},
|
|
{TEXT("Nonpaged"), 3},
|
|
{TEXT("Paged"), 3},
|
|
{TEXT("PageFile"), 3},
|
|
{TEXT("PhysicalMemory"), 3},
|
|
{TEXT("WorkingSet"), 3},
|
|
{TEXT("KernelMemory"), 3},
|
|
{TEXT("CommittedMemory"), 3},
|
|
{TEXT("Pool"), 3},
|
|
|
|
{TEXT("AllocationInformation"),2}, //Pool Info: This tag is here for future extensibility in case we need to add anything more to Pool Info
|
|
{TEXT("TagEntry"),3}, // Pool Info
|
|
{TEXT("PoolTag"),4},
|
|
{TEXT("PoolType"),4},
|
|
{TEXT("NumAllocs"),4},
|
|
{TEXT("NumFrees"),4},
|
|
{TEXT("NumBytes"),4},
|
|
{TEXT("SessionID"),4},
|
|
|
|
{TEXT("Process"), 2}, //Process Info
|
|
{TEXT("PID"), 3},
|
|
{TEXT("Name"),3},
|
|
{TEXT("UserTime"),3},
|
|
{TEXT("KernelTime"), 3},
|
|
{TEXT("WorkingSet"),3},
|
|
{TEXT("PageFaults"),3},
|
|
{TEXT("CommittedBytes"), 3},
|
|
{TEXT("Priority"),3},
|
|
{TEXT("HandleCount"),3},
|
|
{TEXT("ThreadCount"),3},
|
|
|
|
{TEXT("Process"), 2}, // ProcessSummary
|
|
{TEXT("PID"),3},
|
|
{TEXT("ImageName"), 3},
|
|
{TEXT("CmdLine"), 3},
|
|
{TEXT("CurrentDir"), 3},
|
|
|
|
{TEXT("Process"), 2}, //ProcessThreadInfo
|
|
{TEXT("PID"), 3},
|
|
{TEXT("Thread"), 3},
|
|
{TEXT("TID"), 4},
|
|
{TEXT("Priority"), 4},
|
|
{TEXT("ContextSwitches"), 4},
|
|
{TEXT("StartAddress"), 4},
|
|
{TEXT("UserTime"), 4},
|
|
{TEXT("KernelTime"), 4},
|
|
{TEXT("State"), 4},
|
|
|
|
{TEXT("Process"), 2}, //Process Module Info
|
|
{TEXT("PID"), 3},
|
|
{TEXT("Module"), 3},
|
|
{TEXT("LoadAddr"), 4},
|
|
{TEXT("ImageSize"), 4},
|
|
{TEXT("EntryPoint"), 4},
|
|
{TEXT("FileName"), 4},
|
|
|
|
{TEXT("Module"), 2}, //kernel module
|
|
{TEXT("ModuleName"), 3},
|
|
{TEXT("LoadAddress"), 3},
|
|
{TEXT("Code"),3},
|
|
{TEXT("Data"),3},
|
|
{TEXT("Paged"),3},
|
|
{TEXT("Date"),3},
|
|
{TEXT("Time"),3},
|
|
|
|
{TEXT("TotalCode"), 2},
|
|
{TEXT("TotalData"), 2},
|
|
{TEXT("TotalPaged"), 2},
|
|
|
|
|
|
{TEXT("CurrentBuild"), 2}, //os information
|
|
{TEXT("CurrentType"), 2},
|
|
{TEXT("CurrentVersion"), 2},
|
|
{TEXT("Path"), 2},
|
|
{TEXT("ProductName"), 2},
|
|
{TEXT("SoftwareType"), 2},
|
|
{TEXT("SourcePath"), 2},
|
|
{TEXT("SystemRoot"), 2},
|
|
{TEXT("CSDVersion"), 2},
|
|
{TEXT("DebuggerEnabled"),2},
|
|
{TEXT("Hotfix"), 2},
|
|
{TEXT("BiosInfo"), 2},
|
|
{TEXT("ProcessorInfo"), 2},
|
|
{TEXT("NICInfo"), 2},
|
|
{TEXT("DiskInfo"), 2},
|
|
{TEXT("Identifier"), 3},
|
|
{TEXT("SystemBiosDate"), 3},
|
|
{TEXT("SystemBiosVersion"), 3},
|
|
{TEXT("VideoBiosDate"), 3},
|
|
{TEXT("VideoBiosVersion"), 3},
|
|
|
|
{TEXT("Processor"), 3},
|
|
{TEXT("Number"), 4},
|
|
{TEXT("Speed"), 4},
|
|
{TEXT("Identifier"), 4},
|
|
{TEXT("VendorIdent"), 4},
|
|
{TEXT("NIC"), 3},
|
|
{TEXT("Description"), 4},
|
|
{TEXT("ServiceName"), 4},
|
|
{TEXT("PhysicalDisks"), 3},
|
|
{TEXT("PartitionByDiskInfo"), 3},
|
|
{TEXT("LogicalDrives"), 3},
|
|
|
|
{TEXT("Disk"), 4}, //physical disk
|
|
{TEXT("DiskID"), 5},
|
|
{TEXT("BytesPerSector"), 5},
|
|
{TEXT("SectorsPerTrack"), 5},
|
|
{TEXT("TracksPerCylinder"), 5},
|
|
{TEXT("NumberOfCylinders"), 5},
|
|
{TEXT("PortNumber"), 5},
|
|
{TEXT("PathID"), 5},
|
|
{TEXT("TargetID"), 5},
|
|
{TEXT("LUN"), 5},
|
|
{TEXT("Manufacturer"), 5},
|
|
|
|
{TEXT("Disk"), 4}, //partition
|
|
{TEXT("DiskID"), 5},
|
|
{TEXT("Partitions"), 5},
|
|
{TEXT("PartitionInfo"),6},
|
|
{TEXT("PartitionID"), 7},
|
|
{TEXT("Extents"), 7},
|
|
{TEXT("ExtentInfo"), 8},
|
|
{TEXT("ID"), 9},
|
|
{TEXT("StartingOffset"), 9},
|
|
{TEXT("PartitionSize"), 9},
|
|
|
|
{TEXT("LogicalDriveInfo"), 4},
|
|
{TEXT("DrivePath"), 5},
|
|
{TEXT("FreeSpaceBytes"), 5},
|
|
{TEXT("TotalSpaceBytes"), 5},
|
|
{TEXT("Timing"), 1}
|
|
};
|
|
|
|
#define REQUIRED_NUM_OF_STRINGS 7
|
|
|
|
// Number of elements in XMLTagNames array.
|
|
DWORD dwXMLTags = sizeof(XMLTagNames) / sizeof(XMLTags);
|
|
|
|
//
|
|
// Implements the output in XML format.
|
|
//
|
|
class XMLOutput
|
|
{
|
|
//
|
|
// Currently the max level we have is 9, but if anything changes to
|
|
// the XMLTagNames, change MAX_XML_LEVEL accordingly.
|
|
//
|
|
enum {MAX_XML_LEVEL = 20};
|
|
LPCTSTR szTags[MAX_XML_LEVEL];
|
|
DWORD dwCurLevel;
|
|
HANDLE hOutput;
|
|
BOOL bBareTag;
|
|
public:
|
|
XMLOutput(LPCTSTR szHeader, HANDLE hFile)
|
|
: dwCurLevel(0), hOutput(hFile), bBareTag(FALSE)
|
|
{
|
|
WriteToLogFile(hOutput, szHeader);
|
|
WriteToLogFile(hOutput, TEXT("\n"));
|
|
for(DWORD i = 0; i < MAX_XML_LEVEL; i++)
|
|
szTags[i] = NULL;
|
|
}
|
|
|
|
~XMLOutput()
|
|
{
|
|
int nLevel = dwCurLevel;
|
|
while (nLevel >= 0 && szTags[nLevel])
|
|
{
|
|
//
|
|
// Close the ones that are still open.
|
|
//
|
|
for(DWORD i = 0; i < (DWORD)nLevel; i++)
|
|
WriteToLogFile(hOutput, TEXT("\t"));
|
|
WriteToLogFile(hOutput, TEXT("</"));
|
|
WriteToLogFile(hOutput, szTags[nLevel]);
|
|
WriteToLogFile(hOutput, TEXT(">\n"));
|
|
szTags[nLevel] = NULL;
|
|
nLevel--;
|
|
}
|
|
}
|
|
|
|
VOID Write(XMLTAG nTag, LPCSTR szStr)
|
|
{
|
|
DWORD dwLevel = XMLTagNames[nTag].dwLevel;
|
|
|
|
while (dwLevel <= dwCurLevel && szTags[dwCurLevel])
|
|
{
|
|
//
|
|
// Close the previous one
|
|
//
|
|
for(DWORD i = 0; i < dwCurLevel; i++)
|
|
WriteToLogFile(hOutput, TEXT("\t"));
|
|
WriteToLogFile(hOutput, TEXT("</"));
|
|
WriteToLogFile(hOutput, szTags[dwCurLevel]);
|
|
WriteToLogFile(hOutput, TEXT(">\n"));
|
|
szTags[dwCurLevel] = NULL;
|
|
dwCurLevel--;
|
|
}
|
|
|
|
dwCurLevel = dwLevel;
|
|
szTags[dwCurLevel] = XMLTagNames[nTag].szName;
|
|
|
|
if(bBareTag)
|
|
WriteToLogFile(hOutput, TEXT("\n"));
|
|
for(DWORD i = 0; i < dwLevel; i++)
|
|
WriteToLogFile(hOutput, TEXT("\t"));
|
|
WriteToLogFile(hOutput, TEXT("<"));
|
|
WriteToLogFile(hOutput, szTags[dwCurLevel]);
|
|
WriteToLogFile(hOutput, TEXT(">"));
|
|
if(szStr && *szStr)
|
|
{
|
|
WriteToLogFileA(hOutput, szStr);
|
|
WriteToLogFile(hOutput, TEXT("\n"));
|
|
bBareTag = FALSE;
|
|
}
|
|
else
|
|
bBareTag = TRUE;
|
|
}
|
|
|
|
VOID Write(XMLTAG nTag, LPCWSTR szStr)
|
|
{
|
|
DWORD dwLevel = XMLTagNames[nTag].dwLevel;
|
|
|
|
while (dwLevel <= dwCurLevel && szTags[dwCurLevel])
|
|
{
|
|
//
|
|
// Close the previous one
|
|
//
|
|
for(DWORD i = 0; i < dwCurLevel; i++)
|
|
WriteToLogFile(hOutput, TEXT("\t"));
|
|
WriteToLogFile(hOutput, TEXT("</"));
|
|
WriteToLogFile(hOutput, szTags[dwCurLevel]);
|
|
WriteToLogFile(hOutput, TEXT(">\n"));
|
|
szTags[dwCurLevel] = NULL;
|
|
dwCurLevel--;
|
|
}
|
|
|
|
dwCurLevel = dwLevel;
|
|
szTags[dwCurLevel] = XMLTagNames[nTag].szName;
|
|
|
|
if(bBareTag)
|
|
WriteToLogFile(hOutput, TEXT("\n"));
|
|
for(DWORD i = 0; i < dwLevel; i++)
|
|
WriteToLogFile(hOutput, TEXT("\t"));
|
|
WriteToLogFile(hOutput, TEXT("<"));
|
|
WriteToLogFile(hOutput, szTags[dwCurLevel]);
|
|
WriteToLogFile(hOutput, TEXT(">"));
|
|
if(szStr && *szStr)
|
|
{
|
|
WriteToLogFileW(hOutput, szStr);
|
|
WriteToLogFile(hOutput, TEXT("\n"));
|
|
bBareTag = FALSE;
|
|
}
|
|
else
|
|
bBareTag = TRUE;
|
|
}
|
|
|
|
} *gXMLOutput = NULL;
|
|
|
|
VOID
|
|
PrintLoadedDrivers(
|
|
HANDLE hFile
|
|
);
|
|
|
|
ULONG
|
|
LogSystemSnapshot(
|
|
LPCTSTR *lpStrings,
|
|
PLONG BuffSize,
|
|
LPTSTR lpszBuff
|
|
);
|
|
|
|
UINT LogSystemSnapshotToFile(
|
|
HANDLE hFile
|
|
);
|
|
|
|
|
|
void
|
|
LogPoolInfo(
|
|
HANDLE hFile
|
|
);
|
|
|
|
void
|
|
LogLogicalDriveInfo(
|
|
HANDLE hFile
|
|
);
|
|
|
|
void
|
|
LogHardwareInfo(
|
|
HANDLE hFile
|
|
);
|
|
|
|
void
|
|
LogPhysicalDiskInfo(
|
|
HANDLE hFile
|
|
);
|
|
|
|
void
|
|
LogHotfixes(
|
|
HANDLE hFile
|
|
);
|
|
|
|
void
|
|
LogOsInfo(
|
|
HANDLE hFile
|
|
);
|
|
|
|
void
|
|
LogBIOSInfo(
|
|
HANDLE hFile
|
|
);
|
|
|
|
NTSTATUS
|
|
SnapshotRegOpenKey(
|
|
IN LPCWSTR lpKeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT PHANDLE KeyHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
SnapshotRegQueryValueKey(
|
|
IN HANDLE KeyHandle,
|
|
IN LPCWSTR lpValueName,
|
|
IN ULONG Length,
|
|
OUT PVOID KeyValue,
|
|
OUT PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
SnapshotRegEnumKey(
|
|
IN HANDLE KeyHandle,
|
|
IN ULONG Index,
|
|
OUT LPWSTR lpKeyName,
|
|
OUT PULONG lpNameLength
|
|
);
|
|
|
|
NTSTATUS
|
|
SnapshotRegSetValueKey(
|
|
IN HANDLE KeyHandle,
|
|
IN LPCWSTR lpValueName,
|
|
IN DWORD dwType,
|
|
IN LPVOID lpData,
|
|
IN DWORD cbData
|
|
);
|
|
|
|
void
|
|
DeleteOldFiles(
|
|
LPCTSTR lpPath
|
|
);
|
|
|
|
void
|
|
LoadExtensionDlls(
|
|
HANDLE hFile
|
|
);
|
|
|
|
DWORD WINAPI
|
|
_LogSystemSnapshot(
|
|
void* pv
|
|
);
|
|
|
|
DWORD WINAPI
|
|
GetTimeOut(
|
|
void* pv
|
|
);
|
|
|
|
typedef struct _MODULEINFO
|
|
{
|
|
LPVOID lpBaseOfDll;
|
|
DWORD SizeOfImage;
|
|
LPVOID EntryPoint;
|
|
} MODULEINFO, *LPMODULEINFO;
|
|
|
|
BOOL
|
|
WINAPI
|
|
SnapshotGetModuleInformation(
|
|
HANDLE hProcess,
|
|
HMODULE hModule,
|
|
LPMODULEINFO lpmodinfo,
|
|
DWORD cb
|
|
);
|
|
|
|
DWORD
|
|
WINAPI
|
|
SnapshotGetModuleBaseNameW(
|
|
HANDLE hProcess,
|
|
HMODULE hModule,
|
|
LPWSTR lpFilename,
|
|
DWORD nSize
|
|
);
|
|
|
|
DWORD
|
|
WINAPI
|
|
SnapshotGetModuleFileNameExW(
|
|
HANDLE hProcess,
|
|
HMODULE hModule,
|
|
LPWSTR lpFilename,
|
|
DWORD nSize
|
|
);
|
|
|
|
BOOL
|
|
WINAPI
|
|
SnapshotEnumProcessModules(
|
|
HANDLE hProcess,
|
|
HMODULE *lphModule,
|
|
DWORD cb,
|
|
LPDWORD lpcbNeeded
|
|
);
|
|
|
|
BOOL
|
|
SnapshotFindModule(
|
|
IN HANDLE hProcess,
|
|
IN HMODULE hModule,
|
|
OUT PLDR_DATA_TABLE_ENTRY LdrEntryData
|
|
);
|
|
|
|
BOOL
|
|
AdjustAccess(
|
|
LPCWSTR lpszDir
|
|
);
|
|
|
|
ULONG CurrentBufferSize;
|
|
|
|
LPCTSTR StateTable[] =
|
|
{
|
|
TEXT("Initialized"),
|
|
TEXT("Ready"),
|
|
TEXT("Running"),
|
|
TEXT("Standby"),
|
|
TEXT("Terminated"),
|
|
TEXT("Wait:"),
|
|
TEXT("Transition"),
|
|
TEXT("Unknown"),
|
|
TEXT("Unknown"),
|
|
TEXT("Unknown"),
|
|
TEXT("Unknown"),
|
|
TEXT("Unknown")
|
|
};
|
|
|
|
LPCTSTR WaitTable[] =
|
|
{
|
|
TEXT("Executive"),
|
|
TEXT("FreePage"),
|
|
TEXT("PageIn"),
|
|
TEXT("PoolAllocation"),
|
|
TEXT("DelayExecution"),
|
|
TEXT("Suspended"),
|
|
TEXT("UserRequest"),
|
|
TEXT("Executive"),
|
|
TEXT("FreePage"),
|
|
TEXT("PageIn"),
|
|
TEXT("PoolAllocation"),
|
|
TEXT("DelayExecution"),
|
|
TEXT("Suspended"),
|
|
TEXT("UserRequest"),
|
|
TEXT("EventPairHigh"),
|
|
TEXT("EventPairLow"),
|
|
TEXT("LpcReceive"),
|
|
TEXT("LpcReply"),
|
|
TEXT("VirtualMemory"),
|
|
TEXT("PageOut"),
|
|
TEXT("Spare1"),
|
|
TEXT("Spare2"),
|
|
TEXT("Spare3"),
|
|
TEXT("Spare4"),
|
|
TEXT("Spare5"),
|
|
TEXT("Spare6"),
|
|
TEXT("Spare7"),
|
|
TEXT("Unknown"),
|
|
TEXT("Unknown"),
|
|
TEXT("Unknown")
|
|
};
|
|
|
|
LPCTSTR Empty = TEXT(" ");
|
|
|
|
BOOLEAN fUserOnly = TRUE;
|
|
BOOLEAN fSystemOnly = TRUE;
|
|
BOOLEAN fVerbose = FALSE;
|
|
|
|
#define STR_BUFFER_SIZE 512
|
|
TCHAR g_lpszBuffer[STR_BUFFER_SIZE];
|
|
TCHAR g_lpszFileName[2*MAX_PATH + 1] ;
|
|
|
|
//
|
|
// struct for thread proc.
|
|
//
|
|
typedef struct _THREADPARAM
|
|
{
|
|
DWORD Flags;
|
|
LPCTSTR *lpStrings;
|
|
DWORD NumOfStrings;
|
|
PLONG BuffSize;
|
|
LPTSTR lpszBuff;
|
|
LONG lCanOrphanThread;
|
|
}THREADPARAM, *PTHREADPARAM;
|
|
|
|
class Timing
|
|
{
|
|
enum {MAX_TIMING_ENTRIES = 30};
|
|
INT preTicks;
|
|
INT cnt;
|
|
HANDLE hFile;
|
|
struct _XX{
|
|
WCHAR sz[100];
|
|
INT ticks;
|
|
};
|
|
_XX sec[MAX_TIMING_ENTRIES];
|
|
public:
|
|
Timing()
|
|
{
|
|
preTicks = GetTickCount();
|
|
cnt = 0;
|
|
hFile = NULL;
|
|
}
|
|
|
|
void Timeit(HANDLE h, LPCWSTR szSec)
|
|
{
|
|
if(wcslen(szSec) >= 100 || cnt >= MAX_TIMING_ENTRIES)
|
|
return;
|
|
wcscpy(sec[cnt].sz, szSec);
|
|
sec[cnt].ticks = GetTickCount() - preTicks;
|
|
preTicks = GetTickCount();
|
|
hFile = h;
|
|
cnt++;
|
|
}
|
|
|
|
~Timing()
|
|
{
|
|
WCHAR buf[255];
|
|
WriteToLogFile(hFile, TEXT("\n"));
|
|
gXMLOutput->Write(XMLTAG_Timing, (LPCWSTR)NULL);
|
|
WriteToLogFile(hFile, TEXT("\n"));
|
|
for (INT i = 0; i < cnt; i++)
|
|
{
|
|
wsprintf(buf, L"\t\t<%s>%d</%s>\n", sec[i].sz, sec[i].ticks, sec[i].sz);
|
|
WriteToLogFileW(hFile, buf);
|
|
}
|
|
}
|
|
|
|
} *g_pTime = NULL;
|
|
|
|
DWORD
|
|
GetReliabilityGUID(
|
|
LPTSTR* ppszGuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the reliablity GUID. It will check the registry value
|
|
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Reliability\ReliabilityGUID
|
|
first, if it is not there. It will call UuidCreate create the GUID and set the value
|
|
there.
|
|
|
|
Arguments:
|
|
|
|
ppszGUID - caller needs to free
|
|
|
|
Return Value:
|
|
|
|
if failed, return the error code
|
|
|
|
Note:
|
|
Caller needs to call LocalFree to free the GUID String.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwResult = ERROR_SUCCESS;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
HANDLE hKey;
|
|
|
|
LPCTSTR GuidStrVal = TEXT("ReliabilityGUID");
|
|
LPTSTR pszGuid = NULL;
|
|
DWORD cbSize = 0;
|
|
|
|
//
|
|
// 0FC4926A-992D-40d2-B609-32BFD10C5FBC
|
|
// 32 GUID chars + 4 '-' + 1 '\0'
|
|
//
|
|
enum { MAX_GUID_STR_LEN = 37 };
|
|
|
|
status = SnapshotRegOpenKey(ReliabilityKey, KEY_ALL_ACCESS, &hKey);
|
|
if (!NT_SUCCESS(status) )
|
|
{
|
|
dwResult = RtlNtStatusToDosError(status);
|
|
return dwResult;
|
|
}
|
|
|
|
cbSize = MAX_GUID_STR_LEN * sizeof(TCHAR);
|
|
if (!(pszGuid = (LPWSTR)LocalAlloc(LPTR, cbSize)))
|
|
{
|
|
dwResult = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
status = SnapshotRegQueryValueKey(hKey, GuidStrVal, cbSize, pszGuid, &cbSize);
|
|
if (!NT_SUCCESS(status) || !(*pszGuid))
|
|
{
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
UUID Guid;
|
|
LPTSTR pszStringUuid = NULL;
|
|
|
|
//
|
|
// We will regenerate the guid key if:
|
|
// 1. value doesn't exist
|
|
// 2. value has been modified to longer string (>MAX_GUID_STR_LEN).
|
|
// 3. failed with other reasons. ???
|
|
//
|
|
rpcStatus = UuidCreate(&Guid);
|
|
if ( rpcStatus != RPC_S_OK && rpcStatus != RPC_S_UUID_LOCAL_ONLY )
|
|
{
|
|
dwResult = rpcStatus;
|
|
goto error;
|
|
}
|
|
|
|
rpcStatus = UuidToStringW(&Guid, &pszStringUuid);
|
|
if ( rpcStatus != RPC_S_OK || !pszStringUuid )
|
|
{
|
|
dwResult = (rpcStatus == RPC_S_OK)? RPC_S_OUT_OF_MEMORY : rpcStatus;
|
|
goto error;
|
|
}
|
|
|
|
_tcsncpy( pszGuid, pszStringUuid, MAX_GUID_STR_LEN - 1);
|
|
pszGuid[ MAX_GUID_STR_LEN - 1 ] = 0;
|
|
|
|
RpcStringFree( &pszStringUuid );
|
|
|
|
cbSize = MAX_GUID_STR_LEN * sizeof(TCHAR);
|
|
status = SnapshotRegSetValueKey( hKey, GuidStrVal, REG_SZ, (LPVOID)pszGuid, cbSize);
|
|
if (!NT_SUCCESS( status ))
|
|
{
|
|
dwResult = RtlNtStatusToDosError(status);
|
|
goto error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Success, make sure it is NULL terminated. and we will NOT
|
|
// do any format validation here.
|
|
//
|
|
pszGuid[ MAX_GUID_STR_LEN - 1 ] = 0;
|
|
}
|
|
|
|
//
|
|
// Now pszGuid contain the valid GUID, let's update the ppszGuid string.
|
|
//
|
|
*ppszGuid = pszGuid;
|
|
pszGuid = NULL;
|
|
|
|
error:
|
|
|
|
NtClose(hKey);
|
|
|
|
//
|
|
// pszGuid only needs to be freed if we failed. In the
|
|
// success case, it will be set to NULL.
|
|
//
|
|
LocalFree( pszGuid );
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
DWORD WINAPI
|
|
_LogSystemSnapshot(
|
|
void* pv)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the thread entry point.
|
|
|
|
Arguments:
|
|
|
|
pv - thread parameter, a point to THREADPARAM struct.
|
|
|
|
Return Value:
|
|
|
|
thread exit code.
|
|
|
|
--*/
|
|
|
|
{
|
|
SYSTEMTIME systime;
|
|
TIME_ZONE_INFORMATION TimeZone ;
|
|
HANDLE hFile = NULL;
|
|
UINT res = 0;
|
|
LONG lBuffSize ;
|
|
LPTSTR lpszTemp;
|
|
PTHREADPARAM pparam = (PTHREADPARAM)pv;
|
|
DWORD Flags = pparam->Flags;
|
|
LPCTSTR* lpStrings = pparam->lpStrings;
|
|
DWORD NumOfStrings = pparam->NumOfStrings;
|
|
PLONG BuffSize = pparam->BuffSize;
|
|
LPTSTR lpszBuff = pparam->lpszBuff;
|
|
LONG lLength = 0;
|
|
LPTSTR pszReliabilityGuid = NULL;
|
|
ULARGE_INTEGER ullTotal, ullFree, ullAvailable;
|
|
|
|
GetLocalTime(&systime);
|
|
|
|
lBuffSize = *BuffSize ;
|
|
*lpszBuff = 0;
|
|
*BuffSize = 0 ;
|
|
|
|
//
|
|
// Set up the log path %SYSTEMDIR%\Logfiles\Shutdown
|
|
//
|
|
GetSystemDirectory(g_lpszFileName, MAX_PATH);
|
|
_tcsncat(g_lpszFileName, TEXT("\\LogFiles"), 2*MAX_PATH - lstrlen(g_lpszFileName)); // making sure the directory.
|
|
g_lpszFileName[2*MAX_PATH] = 0;
|
|
CreateDirectory(g_lpszFileName, NULL);
|
|
_tcsncat(g_lpszFileName, TEXT("\\ShutDown"), 2*MAX_PATH - lstrlen(g_lpszFileName)); // .. exists
|
|
g_lpszFileName[2*MAX_PATH] = 0;
|
|
|
|
if ( CreateDirectory(g_lpszFileName, NULL) )
|
|
{
|
|
//
|
|
// setup will create this directory, but if admin delete this directory by accident,
|
|
// we will recreate it with the correct ACL.
|
|
//
|
|
if(!AdjustAccess(g_lpszFileName))
|
|
{
|
|
//
|
|
// So only administrators and system can have read and write access.
|
|
//
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure available disk space is at least 100M.
|
|
//
|
|
if (GetDiskFreeSpaceEx(g_lpszFileName, &ullAvailable, &ullTotal, &ullFree))
|
|
{
|
|
if (ullAvailable.HighPart == 0 && ullAvailable.LowPart < 100 * 1024 * 1024)
|
|
{
|
|
return ERROR_DISK_FULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
//
|
|
// Delete old files first. so if the number of days is set to
|
|
// 0, we will still has the current log file around.
|
|
//
|
|
DeleteOldFiles(g_lpszFileName);
|
|
|
|
_tcsncat(g_lpszFileName, TEXT("\\ShutDown_"), 2*MAX_PATH - lstrlen(g_lpszFileName));
|
|
g_lpszFileName[2*MAX_PATH] = 0;
|
|
lpszTemp = (LPTSTR)(g_lpszFileName + (lstrlen(g_lpszFileName)));
|
|
_stnprintf(lpszTemp, 2*MAX_PATH - (lstrlen(g_lpszFileName)),
|
|
TEXT("%4d%02d%02d%02d%02d%02d.xml"),
|
|
systime.wYear, systime.wMonth, systime.wDay,
|
|
systime.wHour, systime.wMinute, systime.wSecond);
|
|
g_lpszFileName[2*MAX_PATH] = 0;
|
|
|
|
hFile = CreateFile(g_lpszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
return HandleToUlong(INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
lLength = _tcslen(g_lpszFileName);
|
|
if (lBuffSize <= lLength)
|
|
{
|
|
res = ERROR_INSUFFICIENT_BUFFER;
|
|
goto cleanup;
|
|
}
|
|
|
|
_tcsncpy(lpszBuff, g_lpszFileName, lBuffSize);
|
|
lpszBuff[ lLength ] = 0;
|
|
*BuffSize = lLength ;
|
|
|
|
gXMLOutput = new XMLOutput(TEXT("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"), hFile);
|
|
if(! gXMLOutput)
|
|
{
|
|
res = GetLastError();
|
|
goto cleanup;
|
|
}
|
|
|
|
GetTimeZoneInformation(&TimeZone);
|
|
|
|
//
|
|
// lpString Format:
|
|
// 0: InitiateProcess
|
|
// 1: SystemName
|
|
// 2: ReasonTitle
|
|
// 3: ReasonCode
|
|
// 4: Restart Type
|
|
// 5: Comment
|
|
// 6: UserName
|
|
//
|
|
gXMLOutput->Write(XMLTAG_SETSystemStateData, (LPCWSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_SETDataType_Header, (LPCWSTR)NULL);
|
|
|
|
if ( !GetReliabilityGUID( &pszReliabilityGuid ) && pszReliabilityGuid )
|
|
{
|
|
gXMLOutput->Write(XMLTAG_HeaderType_ReliabilityGuid, pszReliabilityGuid);
|
|
LocalFree(pszReliabilityGuid);
|
|
}
|
|
else
|
|
{
|
|
gXMLOutput->Write(XMLTAG_HeaderType_ReliabilityGuid, (LPCSTR)NULL);
|
|
}
|
|
|
|
if ( NumOfStrings == REQUIRED_NUM_OF_STRINGS )
|
|
{
|
|
//gXMLOutput->Write(XMLTAG_HeaderType_SystemName, lpStrings[1]);
|
|
//gXMLOutput->Write(XMLTAG_HeaderType_UserName, lpStrings[6]);
|
|
gXMLOutput->Write(XMLTAG_HeaderType_ReasonTitle, lpStrings[2]);
|
|
|
|
|
|
gXMLOutput->Write(XMLTAG_HeaderType_InitiatingProcess, lpStrings[0]);
|
|
}
|
|
else
|
|
{
|
|
//gXMLOutput->Write(XMLTAG_HeaderType_SystemName, (LPCSTR)NULL);
|
|
//gXMLOutput->Write(XMLTAG_HeaderType_UserName, (LPCSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_HeaderType_ReasonTitle, (LPCSTR)NULL);
|
|
|
|
|
|
gXMLOutput->Write(XMLTAG_HeaderType_InitiatingProcess, (LPCSTR)NULL);
|
|
}
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%d-%d-%d"),
|
|
systime.wYear, systime.wMonth, systime.wDay);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
gXMLOutput->Write(XMLTAG_HeaderType_RestartDate, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%d-%d-%d (%s(%d))"),
|
|
systime.wHour, systime.wMinute, systime.wSecond,
|
|
TimeZone.StandardName, TimeZone.Bias);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
gXMLOutput->Write(XMLTAG_HeaderType_RestartTime, (LPCTSTR)g_lpszBuffer);
|
|
|
|
if ( NumOfStrings == REQUIRED_NUM_OF_STRINGS )
|
|
{
|
|
gXMLOutput->Write(XMLTAG_HeaderType_ReasonCode, lpStrings[3]);
|
|
gXMLOutput->Write(XMLTAG_HeaderType_RestartType, lpStrings[4]);
|
|
gXMLOutput->Write(XMLTAG_HeaderType_Comment, lpStrings[5]);
|
|
}
|
|
else
|
|
{
|
|
gXMLOutput->Write(XMLTAG_HeaderType_ReasonCode, (LPCSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_HeaderType_RestartType, (LPCSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_HeaderType_Comment, (LPCSTR)NULL);
|
|
}
|
|
|
|
InterlockedExchange(&pparam->lCanOrphanThread, 1 );
|
|
|
|
__try{
|
|
//
|
|
// Ok write the snapshot to the file
|
|
//
|
|
res = LogSystemSnapshotToFile(hFile);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
//
|
|
// exception in extension dll.
|
|
//
|
|
res = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if ( gXMLOutput )
|
|
{
|
|
delete gXMLOutput;
|
|
gXMLOutput = NULL;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
|
|
return res;
|
|
}
|
|
|
|
ULONG LogSystemSnapshot(
|
|
DWORD Flags,
|
|
LPCTSTR *lpStrings,
|
|
PLONG BuffSize,
|
|
LPTSTR lpszBuff)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function exported to outsiders. This function will
|
|
spawn a thread to do the logging and wait for certain
|
|
amount of time. If the thread does not return by then, it will
|
|
leave it orphan.
|
|
|
|
Arguments:
|
|
|
|
Flags - logging flags. (Num of Strings passed)
|
|
|
|
lpStrings -
|
|
|
|
BuffSize - the size of lpszBuff in TCHARs.
|
|
|
|
lpszBuff - Hold the snapshot file name on return.
|
|
|
|
Return Value:
|
|
|
|
exit code.
|
|
|
|
--*/
|
|
|
|
{
|
|
THREADPARAM param;
|
|
HANDLE hThread = NULL;
|
|
DWORD tid;
|
|
DWORD dwTimeout = DEFAULT_TIMEOUT;
|
|
DWORD dwResult = 0;
|
|
|
|
LPCWSTR TimeOutVal = L"SnapshotTimeout";
|
|
HANDLE hKey;
|
|
DWORD dwSize;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
//A coding errror
|
|
ASSERT (XMLTAG_END == sizeof(XMLTagNames)/sizeof(struct XMLTags));
|
|
|
|
if ( !lpStrings || !BuffSize || *BuffSize == 0 || !lpszBuff )
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
param.Flags = Flags;
|
|
param.NumOfStrings = Flags;
|
|
param.lpStrings = lpStrings;
|
|
param.BuffSize = BuffSize;
|
|
param.lpszBuff = lpszBuff;
|
|
param.lCanOrphanThread = 0;
|
|
|
|
Status = SnapshotRegOpenKey(ReliabilityKey, KEY_READ, &hKey);
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
Status = SnapshotRegQueryValueKey(hKey, TimeOutVal, dwSize, &dwTimeout, &dwSize);
|
|
|
|
if ( NT_SUCCESS(Status) )
|
|
{
|
|
if (dwTimeout < MIN_TIMEOUT )
|
|
dwTimeout = MIN_TIMEOUT;
|
|
|
|
if (dwTimeout > MAX_TIMEOUT )
|
|
dwTimeout = MAX_TIMEOUT;
|
|
}
|
|
else
|
|
{
|
|
dwTimeout = DEFAULT_TIMEOUT;
|
|
}
|
|
|
|
NtClose(hKey);
|
|
}
|
|
|
|
hThread = CreateThread(NULL, 128 * 1024, _LogSystemSnapshot, ¶m, 0, &tid);
|
|
|
|
if(hThread)
|
|
{
|
|
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); // increase priority.
|
|
|
|
do
|
|
{
|
|
//
|
|
// Normally the child thread will complete the first part within
|
|
// MIN_TIMEOUT seconds, but if the system was too slow, we will
|
|
// wait for another wait period before we actually time out.
|
|
//
|
|
dwResult = WaitForSingleObject(hThread, dwTimeout * 1000);
|
|
}
|
|
while ( InterlockedCompareExchange( ¶m.lCanOrphanThread, 0, 0 ) == 0
|
|
&& dwResult != WAIT_OBJECT_0 );
|
|
|
|
if ( dwResult == WAIT_OBJECT_0 )
|
|
{
|
|
if ( !GetExitCodeThread( hThread, &dwResult ) )
|
|
dwResult = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
dwResult = ERROR_TIMEOUT;
|
|
}
|
|
|
|
CloseHandle(hThread);
|
|
}
|
|
else
|
|
{
|
|
dwResult = GetLastError();
|
|
}
|
|
|
|
if ( ERROR_SUCCESS != dwResult )
|
|
{
|
|
*lpszBuff = 0;
|
|
*BuffSize = 0;
|
|
}
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
|
|
|
|
UINT LogSystemSnapshotToFile(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function actually does the logging.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
exit code.
|
|
|
|
--*/
|
|
|
|
{
|
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
|
|
PSYSTEM_THREAD_INFORMATION ThreadInfo;
|
|
BYTE* LargeBuffer1;
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
ULONG TotalOffset = 0;
|
|
TIME_FIELDS UserTime;
|
|
TIME_FIELDS KernelTime;
|
|
TIME_FIELDS UpTime;
|
|
SYSTEM_BASIC_INFORMATION BasicInfo;
|
|
SYSTEM_TIMEOFDAY_INFORMATION TimeOfDayInfo;
|
|
PSYSTEM_PAGEFILE_INFORMATION PageFileInfo;
|
|
LARGE_INTEGER Time;
|
|
ANSI_STRING pname;
|
|
SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
|
|
SYSTEM_FILECACHE_INFORMATION FileCache;
|
|
SIZE_T SumCommit;
|
|
SIZE_T SumWorkingSet;
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
return 1;
|
|
|
|
//SetFileApisToOEM();
|
|
|
|
g_pTime = new Timing();
|
|
|
|
if ( !g_pTime )
|
|
return GetLastError();
|
|
|
|
LargeBuffer1 = (BYTE*) VirtualAlloc (NULL,
|
|
MAX_BUFFER_SIZE,
|
|
MEM_RESERVE,
|
|
PAGE_READWRITE);
|
|
if (LargeBuffer1 == NULL)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if (VirtualAlloc (LargeBuffer1,
|
|
BUFFER_SIZE,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE) == NULL)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
CurrentBufferSize = BUFFER_SIZE;
|
|
|
|
status = NtQuerySystemInformation(
|
|
SystemBasicInformation,
|
|
&BasicInfo,
|
|
sizeof(SYSTEM_BASIC_INFORMATION),
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto cleanup;;
|
|
}
|
|
|
|
status = NtQuerySystemInformation(
|
|
SystemTimeOfDayInformation,
|
|
&TimeOfDayInfo,
|
|
sizeof(SYSTEM_TIMEOFDAY_INFORMATION),
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
Time.QuadPart = TimeOfDayInfo.CurrentTime.QuadPart -
|
|
TimeOfDayInfo.BootTime.QuadPart;
|
|
|
|
RtlTimeToElapsedTimeFields ( &Time, &UpTime);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%3ld %2ld:%02ld:%02ld.%03ld"),
|
|
UpTime.Day,
|
|
UpTime.Hour,
|
|
UpTime.Minute,
|
|
UpTime.Second,
|
|
UpTime.Milliseconds);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
gXMLOutput->Write(XMLTAG_HeaderType_SystemUptime, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf( g_lpszBuffer, TEXT("0x%04x"), GetUserDefaultLangID());
|
|
gXMLOutput->Write(XMLTAG_HeaderType_UserLanguageID, g_lpszBuffer);
|
|
|
|
_stprintf( g_lpszBuffer, TEXT("0x%04x"), GetSystemDefaultLangID());
|
|
gXMLOutput->Write(XMLTAG_HeaderType_SystemLanguageID, g_lpszBuffer);
|
|
|
|
|
|
gXMLOutput->Write(XMLTAG_HeaderType_SchemaVersion, SCHEMA_VERSION_STRING);
|
|
|
|
|
|
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)LargeBuffer1;
|
|
status = NtQuerySystemInformation(
|
|
SystemPageFileInformation,
|
|
PageFileInfo,
|
|
CurrentBufferSize,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
|
|
//
|
|
// Print out the page file information.
|
|
//
|
|
|
|
if (PageFileInfo->TotalSize == 0)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_SETDataType_PageFiles, TEXT("no page files in use"));
|
|
}
|
|
else
|
|
{
|
|
gXMLOutput->Write(XMLTAG_SETDataType_PageFiles, (LPCWSTR)NULL);
|
|
|
|
for (; ; )
|
|
{
|
|
gXMLOutput->Write(XMLTAG_PageFileType_PageFile, (LPCWSTR)NULL);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%ls"), PageFileInfo->PageFileName.Buffer);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_PageFileType_Path, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%ld"),
|
|
PageFileInfo->TotalSize*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PageFileType_CurrentSize, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%ld"),
|
|
PageFileInfo->TotalInUse*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PageFileType_Total, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%ld"),
|
|
PageFileInfo->PeakUsage*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PageFileType_Peak, (LPCTSTR)g_lpszBuffer);
|
|
|
|
if (PageFileInfo->NextEntryOffset == 0)
|
|
{
|
|
break;
|
|
}
|
|
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)(
|
|
(PCHAR)PageFileInfo + PageFileInfo->NextEntryOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
retry:
|
|
status = NtQuerySystemInformation(
|
|
SystemProcessInformation,
|
|
LargeBuffer1,
|
|
CurrentBufferSize,
|
|
NULL
|
|
);
|
|
|
|
if (status == STATUS_INFO_LENGTH_MISMATCH)
|
|
{
|
|
|
|
//
|
|
// Increase buffer size.
|
|
//
|
|
|
|
CurrentBufferSize += 8192;
|
|
|
|
if (VirtualAlloc (LargeBuffer1,
|
|
CurrentBufferSize,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE) == NULL)
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Memory commit failed\n"));
|
|
goto cleanup;
|
|
}
|
|
goto retry;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("Query info failed %lx\n"),status);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
WriteToLogFile(hFile,g_lpszBuffer);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// display pmon style process output, then detailed output that includes
|
|
// per thread stuff
|
|
//
|
|
|
|
TotalOffset = 0;
|
|
SumCommit = 0;
|
|
SumWorkingSet = 0;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
|
while (TRUE)
|
|
{
|
|
SumCommit += ProcessInfo->PrivatePageCount / 1024;
|
|
SumWorkingSet += ProcessInfo->WorkingSetSize / 1024;
|
|
if (ProcessInfo->NextEntryOffset == 0)
|
|
{
|
|
break;
|
|
}
|
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
|
}
|
|
|
|
status = NtQuerySystemInformation(
|
|
SystemPerformanceInformation,
|
|
&PerfInfo,
|
|
sizeof(PerfInfo),
|
|
NULL
|
|
);
|
|
|
|
if ( !NT_SUCCESS(status) )
|
|
{
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("Query perf Failed %lx\n"),status);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
WriteToLogFile(hFile, g_lpszBuffer);
|
|
goto cleanup;
|
|
}
|
|
|
|
status = NtQuerySystemInformation(
|
|
SystemFileCacheInformation,
|
|
&FileCache,
|
|
sizeof(FileCache),
|
|
NULL
|
|
);
|
|
|
|
if ( !NT_SUCCESS(status) )
|
|
{
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("Query file cache Failed %lx\n"),status);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
WriteToLogFile(hFile, g_lpszBuffer);
|
|
goto cleanup;
|
|
}
|
|
|
|
NtQuerySystemInformation(
|
|
SystemBasicInformation,
|
|
&BasicInfo,
|
|
sizeof(BasicInfo),
|
|
NULL
|
|
);
|
|
|
|
SumWorkingSet += FileCache.CurrentSize/1024;
|
|
gXMLOutput->Write(XMLTAG_SETDataType_Memory, (LPCWSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_Memory_PhysicalMemory,(LPCWSTR)NULL);
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),
|
|
BasicInfo.NumberOfPhysicalPages*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PhysicalMemoryType_Total, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),
|
|
PerfInfo.AvailablePages*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PhysicalMemoryType_Available, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"), SumWorkingSet);
|
|
gXMLOutput->Write(XMLTAG_WorkingSetType_WorkingSet, (LPCTSTR)g_lpszBuffer);
|
|
|
|
gXMLOutput->Write(XMLTAG_Memory_CommittedMemory, (LPCWSTR)NULL);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
PerfInfo.CommittedPages*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_CommittedMemoryType_Total, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"), SumCommit);
|
|
gXMLOutput->Write(XMLTAG_CommittedMemoryType_UserMode, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
PerfInfo.CommitLimit*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_CommittedMemoryType_Limit, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
PerfInfo.PeakCommitment*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_CommittedMemoryType_Peak, (LPCTSTR)g_lpszBuffer);
|
|
|
|
gXMLOutput->Write(XMLTAG_Memory_KernelMemory, (LPCWSTR)NULL);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
(PerfInfo.ResidentSystemCodePage + PerfInfo.ResidentSystemDriverPage)*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_KernelMemoryType_Nonpaged, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
(PerfInfo.ResidentPagedPoolPage)*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_KernelMemoryType_Paged, (LPCTSTR)g_lpszBuffer);
|
|
|
|
|
|
gXMLOutput->Write(XMLTAG_Memory_Pool, (LPCWSTR)NULL);
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
PerfInfo.NonPagedPoolPages*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PoolType_Nonpaged, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),
|
|
PerfInfo.PagedPoolPages*(BasicInfo.PageSize/1024));
|
|
gXMLOutput->Write(XMLTAG_PoolType_Paged, (LPCTSTR)g_lpszBuffer);
|
|
|
|
g_pTime->Timeit(hFile, L"SummaryInfo");
|
|
|
|
LogPoolInfo(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"PoolInfo");
|
|
|
|
TotalOffset = 0;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
|
|
|
|
|
//
|
|
// Process summary information
|
|
//
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ProcessSummaries, (LPCWSTR)NULL);
|
|
|
|
while (TRUE)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_Process, (LPCWSTR) NULL );
|
|
|
|
pname.Buffer = NULL;
|
|
if ( ProcessInfo->ImageName.Buffer )
|
|
{
|
|
RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
|
|
}
|
|
|
|
RtlTimeToElapsedTimeFields ( &ProcessInfo->UserTime, &UserTime);
|
|
RtlTimeToElapsedTimeFields ( &ProcessInfo->KernelTime, &KernelTime);
|
|
|
|
//
|
|
// PID
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%3ld", HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_PID, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Name
|
|
//
|
|
_snprintf((char*)g_lpszBuffer, STR_BUFFER_SIZE, "%s",
|
|
ProcessInfo->UniqueProcessId == 0 ?
|
|
"Idle Process" : (ProcessInfo->ImageName.Buffer ? pname.Buffer : "System"));
|
|
((char*)g_lpszBuffer)[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_Name, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// UserTime
|
|
//
|
|
_snprintf((char*)g_lpszBuffer, STR_BUFFER_SIZE, "%3ld:%02ld:%02ld.%03ld",
|
|
UserTime.Hour,
|
|
UserTime.Minute,
|
|
UserTime.Second,
|
|
UserTime.Milliseconds );
|
|
((char*)g_lpszBuffer)[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_UserTime, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// KernelTime
|
|
//
|
|
_snprintf((char*)g_lpszBuffer, STR_BUFFER_SIZE, "%3ld:%02ld:%02ld.%03ld",
|
|
KernelTime.Hour,
|
|
KernelTime.Minute,
|
|
KernelTime.Second,
|
|
KernelTime.Milliseconds );
|
|
((char*)g_lpszBuffer)[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_KernelTime, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Working Set
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%ld", ProcessInfo->WorkingSetSize / 1024);
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_WorkingSet, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// PageFaults
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%ld", ProcessInfo->PageFaultCount);
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_PageFaults, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
//CommittedBytes
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%ld", ProcessInfo->PrivatePageCount / 1024);
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_CommittedBytes, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Priority
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%ld", ProcessInfo->BasePriority);
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_Priority, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// HandleCount
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%ld", ProcessInfo->HandleCount);
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_HandleCount, (LPCSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// ThreadCount
|
|
//
|
|
sprintf((char*)g_lpszBuffer, "%ld", ProcessInfo->NumberOfThreads);
|
|
gXMLOutput->Write(XMLTAG_ProcessSummaryType_ThreadCount, (LPCSTR)g_lpszBuffer);
|
|
|
|
if ( pname.Buffer )
|
|
{
|
|
RtlFreeAnsiString(&pname);
|
|
}
|
|
|
|
if (ProcessInfo->NextEntryOffset == 0)
|
|
{
|
|
break;
|
|
}
|
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
|
}
|
|
|
|
g_pTime->Timeit(hFile, L"ProcessInfo");
|
|
|
|
//
|
|
// Process Start up information
|
|
//
|
|
{
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
|
|
|
TotalOffset = 0;
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ProcessStartInfo, (LPCWSTR)NULL);
|
|
|
|
while (TRUE)
|
|
{
|
|
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
if(hProcess)
|
|
{
|
|
PROCESS_BASIC_INFORMATION ppbi;
|
|
status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ppbi, sizeof(ppbi), NULL);
|
|
if(NT_SUCCESS(status))
|
|
{
|
|
PPEB ppeb = ppbi.PebBaseAddress;
|
|
struct _RTL_USER_PROCESS_PARAMETERS* pupp;
|
|
struct _RTL_USER_PROCESS_PARAMETERS rupp;
|
|
SIZE_T dwRead, dwRead1, dwRead2;
|
|
|
|
if(ReadProcessMemory(hProcess, &ppeb->ProcessParameters, &pupp, sizeof(pupp), &dwRead)
|
|
&& ReadProcessMemory(hProcess, pupp, &rupp, sizeof(rupp), &dwRead))
|
|
{
|
|
WCHAR CurrentDirectory[MAX_PATH];
|
|
WCHAR CommandLine[MAX_PATH];
|
|
WCHAR ImagePathName[MAX_PATH];
|
|
|
|
if(ReadProcessMemory(hProcess,
|
|
rupp.CurrentDirectory.DosPath.Buffer,
|
|
CurrentDirectory,
|
|
(MAX_PATH - 1) * sizeof(WCHAR) > rupp.CurrentDirectory.DosPath.Length ?
|
|
rupp.CurrentDirectory.DosPath.Length : (MAX_PATH - 1) * sizeof(WCHAR),
|
|
&dwRead)
|
|
&& ReadProcessMemory(hProcess,
|
|
rupp.CommandLine.Buffer,
|
|
CommandLine,
|
|
(MAX_PATH - 1) * sizeof(WCHAR) > rupp.CommandLine.Length ?
|
|
rupp.CommandLine.Length : (MAX_PATH - 1) * sizeof(WCHAR),
|
|
&dwRead1)
|
|
&& ReadProcessMemory(hProcess,
|
|
rupp.ImagePathName.Buffer,
|
|
ImagePathName,
|
|
(MAX_PATH - 1) * sizeof(WCHAR) > rupp.ImagePathName.Length ?
|
|
rupp.ImagePathName.Length : (MAX_PATH - 1) * sizeof(WCHAR),
|
|
&dwRead2)
|
|
)
|
|
{
|
|
CurrentDirectory[dwRead/sizeof(WCHAR)] = '\0';
|
|
CommandLine[dwRead1/sizeof(WCHAR)] = '\0';
|
|
ImagePathName[dwRead2/sizeof(WCHAR)] = '\0';
|
|
|
|
gXMLOutput->Write(XMLTAG_ProcessStartInfoType_Process, (LPCWSTR)NULL);
|
|
|
|
swprintf(g_lpszBuffer, L"%d", HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
|
|
gXMLOutput->Write(XMLTAG_ProcessStartInfoType_PID, (LPCWSTR)g_lpszBuffer);
|
|
|
|
gXMLOutput->Write(XMLTAG_ProcessStartInfoType_ImageName, (LPCWSTR)ImagePathName);
|
|
gXMLOutput->Write(XMLTAG_ProcessStartInfoType_CmdLine, (LPCWSTR)CommandLine);
|
|
gXMLOutput->Write(XMLTAG_ProcessStartInfoType_CurrentDir, (LPCWSTR)CurrentDirectory);
|
|
}
|
|
}
|
|
|
|
}
|
|
CloseHandle(hProcess);
|
|
}
|
|
if (ProcessInfo->NextEntryOffset == 0)
|
|
{
|
|
break;
|
|
}
|
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
|
}
|
|
|
|
}
|
|
|
|
g_pTime->Timeit(hFile, L"ProcessStartupInfo");
|
|
|
|
//
|
|
// Process thread information
|
|
//
|
|
{
|
|
|
|
//WriteToLogFileA(hFile, "\nProcess thread information:\n");
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ProcessesThreadInfo, (LPCWSTR)NULL);
|
|
TotalOffset = 0;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
|
while (TRUE)
|
|
{
|
|
DWORD dwThreadIndex = 0;
|
|
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
|
|
if (ProcessInfo->NumberOfThreads)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_Process, (LPCWSTR)NULL);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_PID, (LPCTSTR)g_lpszBuffer);
|
|
|
|
}
|
|
while (dwThreadIndex < ProcessInfo->NumberOfThreads)
|
|
{
|
|
RtlTimeToElapsedTimeFields ( &ThreadInfo->UserTime, &UserTime);
|
|
RtlTimeToElapsedTimeFields ( &ThreadInfo->KernelTime, &KernelTime);
|
|
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_Thread, (LPCWSTR)NULL);
|
|
|
|
//
|
|
// TID
|
|
//
|
|
wsprintf(g_lpszBuffer, TEXT("%lx"),
|
|
ProcessInfo->UniqueProcessId == 0 ? 0 : HandleToUlong(ThreadInfo->ClientId.UniqueThread));
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_TID, (LPCWSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Priority
|
|
//
|
|
wsprintf(g_lpszBuffer, TEXT("%ld"), ProcessInfo->UniqueProcessId == 0 ? 0 : ThreadInfo->Priority);
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_Priority, (LPCWSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Context Switches
|
|
//
|
|
wsprintf(g_lpszBuffer, TEXT("%ld"), ThreadInfo->ContextSwitches);
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_ContextSwitches, (LPCWSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Start Address
|
|
//
|
|
wsprintf(g_lpszBuffer, TEXT("%p"), ProcessInfo->UniqueProcessId == 0 ? 0 : ThreadInfo->StartAddress);
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_StartAddress, (LPCWSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// User Time
|
|
//
|
|
wsprintf(g_lpszBuffer, TEXT("%2ld:%02ld:%02ld.%03ld"),
|
|
UserTime.Hour,
|
|
UserTime.Minute,
|
|
UserTime.Second,
|
|
UserTime.Milliseconds);
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_UserTime, (LPCWSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Kernel Time
|
|
//
|
|
wsprintf(g_lpszBuffer, TEXT("%2ld:%02ld:%02ld.%03ld"),
|
|
KernelTime.Hour,
|
|
KernelTime.Minute,
|
|
KernelTime.Second,
|
|
KernelTime.Milliseconds);
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_KernelTime, (LPCWSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// State
|
|
//
|
|
_snwprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("%s%s"),
|
|
StateTable[ThreadInfo->ThreadState],
|
|
(ThreadInfo->ThreadState == 5) ? WaitTable[ThreadInfo->WaitReason] : Empty );
|
|
gXMLOutput->Write(XMLTAG_ProcessThreadInfoType_State, (LPCWSTR)g_lpszBuffer);
|
|
|
|
ThreadInfo += 1;
|
|
dwThreadIndex += 1;
|
|
}
|
|
if (ProcessInfo->NextEntryOffset == 0)
|
|
{
|
|
break;
|
|
}
|
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
|
}
|
|
}
|
|
|
|
g_pTime->Timeit(hFile, L"ProcessThreadInfo");
|
|
|
|
//
|
|
// Process module information
|
|
//
|
|
{
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ProcessesModuleInfo, (LPCWSTR)NULL);
|
|
TotalOffset = 0;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
|
while (TRUE)
|
|
{
|
|
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
if(hProcess)
|
|
{
|
|
#define dwMaxModules 1024
|
|
HMODULE modules[dwMaxModules];
|
|
DWORD dwModules = 0;
|
|
|
|
if(SnapshotEnumProcessModules(hProcess, modules, dwMaxModules * sizeof(HMODULE), &dwModules) && dwModules > 0)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_Process, (LPCWSTR)NULL);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_PID, (LPCTSTR)g_lpszBuffer);
|
|
|
|
dwModules /= sizeof(HMODULE);
|
|
dwModules = dwModules > dwMaxModules? dwMaxModules : dwModules;
|
|
for(DWORD dwModuleIndex = 0; dwModuleIndex < dwModules; dwModuleIndex++)
|
|
{
|
|
MODULEINFO info;
|
|
WCHAR szName[MAX_PATH + 1];
|
|
|
|
if(SnapshotGetModuleInformation(hProcess, modules[dwModuleIndex], &info, sizeof(MODULEINFO))
|
|
&& SnapshotGetModuleFileNameExW(hProcess, modules[dwModuleIndex], szName, MAX_PATH - 1))
|
|
{
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_Module, (LPCWSTR)NULL);
|
|
|
|
//
|
|
// LoadAddr
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%14p"), info.lpBaseOfDll);
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_LoadAddr, g_lpszBuffer);
|
|
|
|
//
|
|
// ImageSize
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), info.SizeOfImage);
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_ImageSize, g_lpszBuffer);
|
|
|
|
//
|
|
// Entry Point
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%11p"), info.EntryPoint);
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_EntryPoint, g_lpszBuffer);
|
|
|
|
//
|
|
// FileName
|
|
//
|
|
gXMLOutput->Write(XMLTAG_ProcessModuleInfoType_FileName, szName);
|
|
|
|
}
|
|
}
|
|
}
|
|
CloseHandle(hProcess);
|
|
}
|
|
if (ProcessInfo->NextEntryOffset == 0)
|
|
{
|
|
break;
|
|
}
|
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
|
}
|
|
}
|
|
|
|
g_pTime->Timeit(hFile, L"ProcessModuleInfo");
|
|
|
|
PrintLoadedDrivers(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"LoadedDrivers");
|
|
|
|
gXMLOutput->Write(XMLTAG_SETDataType_OSInfo, (LPCWSTR)NULL);
|
|
LogOsInfo(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"OsInfo");
|
|
|
|
LogHotfixes(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"HotFixes");
|
|
|
|
gXMLOutput->Write(XMLTAG_SETDataType_HardwareInfo, (LPCWSTR)NULL);
|
|
LogBIOSInfo(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"BiosInfo");
|
|
|
|
LogHardwareInfo(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"HardwareInfo");
|
|
|
|
gXMLOutput->Write(XMLTAG_HardwareInfoType_DiskInfo, (LPCWSTR)NULL);
|
|
LogPhysicalDiskInfo(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"PhysicalDiskInfo");
|
|
|
|
LogLogicalDriveInfo(hFile);
|
|
|
|
g_pTime->Timeit(hFile, L"LogicalDriveInfo");
|
|
|
|
//
|
|
// Removing ExtensionDll code
|
|
// Right now CSRSS will call this snapshot dll, having ExtensionDll can impose
|
|
// more security risk, so we are removing it out in production code.
|
|
//
|
|
// LoadExtensionDlls(hFile);
|
|
//
|
|
g_pTime->Timeit(hFile, L"ExtensionDll");
|
|
|
|
VirtualFree(LargeBuffer1, 0, MEM_RELEASE);
|
|
delete g_pTime;
|
|
g_pTime = NULL;
|
|
return 0;
|
|
|
|
cleanup:
|
|
VirtualFree(LargeBuffer1, 0, MEM_RELEASE);
|
|
if(g_pTime)
|
|
{
|
|
delete g_pTime;
|
|
g_pTime = NULL;
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
|
|
typedef struct _MODULE_DATA
|
|
{
|
|
ULONG CodeSize;
|
|
ULONG DataSize;
|
|
ULONG BssSize;
|
|
ULONG RoDataSize;
|
|
ULONG ImportDataSize;
|
|
ULONG ExportDataSize;
|
|
ULONG ResourceDataSize;
|
|
ULONG PagedSize;
|
|
ULONG InitSize;
|
|
ULONG CheckSum;
|
|
ULONG TimeDateStamp;
|
|
} MODULE_DATA, *PMODULE_DATA;
|
|
|
|
typedef struct _LOADED_IMAGE
|
|
{
|
|
BYTE* MappedAddress;
|
|
PIMAGE_NT_HEADERS FileHeader;
|
|
PIMAGE_SECTION_HEADER LastRvaSection;
|
|
int NumberOfSections;
|
|
PIMAGE_SECTION_HEADER Sections;
|
|
} LOADED_IMAGE, *PLOADED_IMAGE;
|
|
|
|
|
|
VOID
|
|
SumModuleData(
|
|
PMODULE_DATA Sum,
|
|
PMODULE_DATA Current
|
|
)
|
|
{
|
|
Sum->CodeSize += Current->CodeSize;
|
|
Sum->DataSize += Current->DataSize;
|
|
Sum->BssSize += Current->BssSize;
|
|
Sum->RoDataSize += Current->RoDataSize;
|
|
Sum->ImportDataSize += Current->ImportDataSize;
|
|
Sum->ExportDataSize += Current->ExportDataSize;
|
|
Sum->ResourceDataSize += Current->ResourceDataSize;
|
|
Sum->PagedSize += Current->PagedSize;
|
|
Sum->InitSize += Current->InitSize;
|
|
}
|
|
|
|
VOID
|
|
GetModuleData(
|
|
HANDLE hFile,
|
|
PMODULE_DATA Mod
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will Get the module data.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
HANDLE hMappedFile;
|
|
PIMAGE_DOS_HEADER DosHeader;
|
|
LOADED_IMAGE LoadedImage;
|
|
ULONG SectionAlignment;
|
|
PIMAGE_SECTION_HEADER Section;
|
|
int i;
|
|
ULONG Size;
|
|
|
|
hMappedFile = CreateFileMapping(
|
|
hFile,
|
|
NULL,
|
|
PAGE_READONLY,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
if ( !hMappedFile )
|
|
{
|
|
return;
|
|
}
|
|
|
|
LoadedImage.MappedAddress = (BYTE*) MapViewOfFile(
|
|
hMappedFile,
|
|
FILE_MAP_READ,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
CloseHandle(hMappedFile);
|
|
|
|
if ( !LoadedImage.MappedAddress )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Everything is mapped. Now check the image and find nt image headers
|
|
//
|
|
|
|
DosHeader = (PIMAGE_DOS_HEADER)LoadedImage.MappedAddress;
|
|
|
|
if ( DosHeader->e_magic != IMAGE_DOS_SIGNATURE )
|
|
{
|
|
UnmapViewOfFile(LoadedImage.MappedAddress);
|
|
return;
|
|
}
|
|
|
|
LoadedImage.FileHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);
|
|
|
|
if ( LoadedImage.FileHeader->Signature != IMAGE_NT_SIGNATURE )
|
|
{
|
|
UnmapViewOfFile(LoadedImage.MappedAddress);
|
|
return;
|
|
}
|
|
|
|
LoadedImage.NumberOfSections = LoadedImage.FileHeader->FileHeader.NumberOfSections;
|
|
LoadedImage.Sections = (PIMAGE_SECTION_HEADER)((ULONG_PTR)LoadedImage.FileHeader + sizeof(IMAGE_NT_HEADERS));
|
|
LoadedImage.LastRvaSection = LoadedImage.Sections;
|
|
|
|
//
|
|
// Walk through the sections and tally the dater
|
|
//
|
|
|
|
SectionAlignment = LoadedImage.FileHeader->OptionalHeader.SectionAlignment;
|
|
|
|
for (Section = LoadedImage.Sections,i=0; i<LoadedImage.NumberOfSections; i++,Section++)
|
|
{
|
|
Size = Section->Misc.VirtualSize;
|
|
|
|
if (Size == 0)
|
|
{
|
|
Size = Section->SizeOfRawData;
|
|
}
|
|
|
|
Size = (Size + SectionAlignment - 1) & ~(SectionAlignment - 1);
|
|
|
|
if (!memcmp((const char*) Section->Name,"PAGE", 4 ))
|
|
{
|
|
Mod->PagedSize += Size;
|
|
}
|
|
else if (!_stricmp((const char*) Section->Name,"INIT" ))
|
|
{
|
|
Mod->InitSize += Size;
|
|
}
|
|
else if (!_stricmp((const char*) Section->Name,".bss" ))
|
|
{
|
|
Mod->BssSize = Size;
|
|
}
|
|
else if (!_stricmp((const char*) Section->Name,".edata" ))
|
|
{
|
|
Mod->ExportDataSize = Size;
|
|
}
|
|
else if (!_stricmp((const char*) Section->Name,".idata" ))
|
|
{
|
|
Mod->ImportDataSize = Size;
|
|
}
|
|
else if (!_stricmp((const char*) Section->Name,".rsrc" ))
|
|
{
|
|
Mod->ResourceDataSize = Size;
|
|
}
|
|
else if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
|
|
{
|
|
Mod->CodeSize += Size;
|
|
}
|
|
else if (Section->Characteristics & IMAGE_SCN_MEM_WRITE)
|
|
{
|
|
Mod->DataSize += Size;
|
|
}
|
|
else if (Section->Characteristics & IMAGE_SCN_MEM_READ)
|
|
{
|
|
Mod->RoDataSize += Size;
|
|
}
|
|
else
|
|
{
|
|
Mod->DataSize += Size;
|
|
}
|
|
}
|
|
|
|
Mod->CheckSum = LoadedImage.FileHeader->OptionalHeader.CheckSum;
|
|
Mod->TimeDateStamp = LoadedImage.FileHeader->FileHeader.TimeDateStamp;
|
|
|
|
UnmapViewOfFile(LoadedImage.MappedAddress);
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintLoadedDrivers(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log the loaded drivers.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG i, j, ulLen;
|
|
LPSTR s;
|
|
TCHAR ModuleName[MAX_PATH + 1];
|
|
HANDLE FileHandle;
|
|
TCHAR KernelPath[MAX_PATH + 1];
|
|
TCHAR DriversPath[MAX_PATH + 1];
|
|
LPTSTR ModuleInfo;
|
|
ULONG ModuleInfoLength;
|
|
ULONG ReturnedLength;
|
|
PRTL_PROCESS_MODULES Modules;
|
|
PRTL_PROCESS_MODULE_INFORMATION Module;
|
|
NTSTATUS Status;
|
|
MODULE_DATA Sum;
|
|
MODULE_DATA Current;
|
|
__int64 timeStamp;
|
|
FILETIME ft;
|
|
SYSTEMTIME st;
|
|
|
|
gXMLOutput->Write(XMLTAG_SETDataType_KernelModuleInfo, (LPCWSTR)NULL);
|
|
|
|
//
|
|
// Locate system drivers.
|
|
//
|
|
|
|
ModuleInfoLength = 64000;
|
|
while (1)
|
|
{
|
|
ModuleInfo = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ModuleInfoLength * sizeof(TCHAR));
|
|
if (ModuleInfo == NULL)
|
|
{
|
|
wsprintf (g_lpszBuffer, TEXT("Failed to allocate memory for module information buffer of size %d"),
|
|
ModuleInfoLength);
|
|
WriteToLogFile(hFile, g_lpszBuffer);
|
|
return;
|
|
}
|
|
Status = NtQuerySystemInformation (
|
|
SystemModuleInformation,
|
|
ModuleInfo,
|
|
ModuleInfoLength * sizeof(TCHAR),
|
|
&ReturnedLength);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)ModuleInfo);
|
|
if (Status == STATUS_INFO_LENGTH_MISMATCH &&
|
|
ReturnedLength > ModuleInfoLength * sizeof(TCHAR))
|
|
{
|
|
ModuleInfoLength = ReturnedLength / sizeof(TCHAR);
|
|
continue;
|
|
}
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("query system info failed status - %lx"),Status);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
WriteToLogFile(hFile, g_lpszBuffer);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
|
|
GetSystemDirectory(KernelPath,sizeof(KernelPath)/sizeof(TCHAR));
|
|
lstrcpy(DriversPath, KernelPath);
|
|
lstrcat(DriversPath,TEXT("\\Drivers"));
|
|
ZeroMemory(&Sum,sizeof(Sum));
|
|
// PrintModuleHeader(hFile);
|
|
|
|
Modules = (PRTL_PROCESS_MODULES)ModuleInfo;
|
|
Module = &Modules->Modules[ 0 ];
|
|
for (i=0; i<Modules->NumberOfModules; i++)
|
|
{
|
|
|
|
ZeroMemory(&Current,sizeof(Current));
|
|
s = (LPSTR)&Module->FullPathName[ Module->OffsetToFileName ];
|
|
//
|
|
// try to open the file
|
|
//
|
|
|
|
SetCurrentDirectory(KernelPath);
|
|
#ifdef _UNICODE
|
|
MultiByteToWideChar(CP_ACP, 0, s, -1, ModuleName, MAX_PATH);
|
|
#else
|
|
strcpy(ModuleName, s);
|
|
#endif //_UNICODE
|
|
FileHandle = CreateFile(
|
|
ModuleName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if ( FileHandle == INVALID_HANDLE_VALUE )
|
|
{
|
|
SetCurrentDirectory(DriversPath);
|
|
|
|
FileHandle = CreateFile(
|
|
ModuleName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if ( FileHandle != INVALID_HANDLE_VALUE )
|
|
{
|
|
GetModuleData(FileHandle,&Current);
|
|
CloseHandle(FileHandle);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Module, (LPCWSTR)NULL);
|
|
|
|
//
|
|
// Module Name
|
|
//
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("%s"), ModuleName);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_ModuleName, (LPCTSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// LoadAddress
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%p"), Module->ImageBase);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_LoadAddress, (LPCTSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Code
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), Current.CodeSize);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Code, (LPCTSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Data
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), Current.DataSize);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Data, (LPCTSTR)g_lpszBuffer);
|
|
|
|
//
|
|
// Paged
|
|
//
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), Current.PagedSize);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Paged, (LPCTSTR)g_lpszBuffer);
|
|
|
|
SumModuleData(&Sum,&Current);
|
|
if (Current.TimeDateStamp)
|
|
{
|
|
timeStamp = Current.TimeDateStamp;
|
|
timeStamp += (__int64)11644444799; //difference between filetime and time_t in seconds.
|
|
timeStamp *= 10000000; // turn into 100 nano seconds.
|
|
ft.dwLowDateTime = (DWORD)timeStamp;
|
|
for (j = 0; j < 32; j++)
|
|
timeStamp /= 2;
|
|
ft.dwHighDateTime = (DWORD)timeStamp;
|
|
FileTimeToSystemTime(&ft, &st);
|
|
|
|
//
|
|
// Date & Time
|
|
//
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("%d-%d-%d"), st.wMonth, st.wDay, st.wYear );
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Date, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("%d:%d:%d"), st.wHour, st.wMinute, st.wSecond);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Time, (LPCTSTR)g_lpszBuffer);
|
|
}
|
|
else
|
|
{
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Date, (LPCTSTR)L"UNKNOWN");
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_Date, (LPCTSTR)L"UNKNOWN");
|
|
}
|
|
Module++;
|
|
}
|
|
|
|
XMLTAG_KernelModuleInfoType_TotalCode,
|
|
XMLTAG_KernelModuleInfoType_TotalData,
|
|
XMLTAG_KernelModuleInfoType_TotalPaged,
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), Sum.CodeSize);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_TotalCode, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), Sum.DataSize);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_TotalData, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), Sum.PagedSize);
|
|
gXMLOutput->Write(XMLTAG_KernelModuleInfoType_TotalPaged, (LPCTSTR)g_lpszBuffer);
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)ModuleInfo);
|
|
}
|
|
|
|
|
|
void
|
|
LogLogicalDriveInfo(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log the logical drive info.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwDriveMask;
|
|
static TCHAR* tszDrives = TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
|
ULARGE_INTEGER i64FreeBytesToCaller;
|
|
ULARGE_INTEGER i64TotalBytesToCaller;
|
|
ULARGE_INTEGER i64TotalFreeBytesOnDrive;
|
|
int iMask;
|
|
TCHAR tszDrive[5]; //Buffer for drive such as "A:\".
|
|
TCHAR tszBuffer[NUM_OF_CHAR_IN_ULONG64]; //buffer to contain info for one logical drive.
|
|
int i;
|
|
|
|
dwDriveMask = GetLogicalDrives();
|
|
|
|
gXMLOutput->Write(XMLTAG_DiskInfoType_LogicalDrives, (LPCWSTR)NULL);
|
|
|
|
for(i = 0; i < (int)_tcslen(tszDrives); i++)
|
|
{
|
|
iMask = dwDriveMask & 0x1;
|
|
_stprintf(tszDrive, TEXT("%c:\\"), tszDrives[i]);
|
|
dwDriveMask >>= 1;
|
|
if(iMask && GetDriveType(tszDrive) == DRIVE_FIXED
|
|
&& GetDiskFreeSpaceEx(tszDrive, &i64FreeBytesToCaller, &i64TotalBytesToCaller, &i64TotalFreeBytesOnDrive))
|
|
{
|
|
gXMLOutput->Write(XMLTAG_LogicalDriveInfoType_LogicalDriveInfo, (LPCWSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_LogicalDriveInfoType_DrivePath, tszDrive);
|
|
_stprintf(tszBuffer, TEXT("%I64d"), i64TotalFreeBytesOnDrive.QuadPart);
|
|
gXMLOutput->Write(XMLTAG_LogicalDriveInfoType_FreeSpaceBytes, tszBuffer);
|
|
_stprintf(tszBuffer, TEXT("%I64d"), i64TotalBytesToCaller.QuadPart);
|
|
gXMLOutput->Write(XMLTAG_LogicalDriveInfoType_TotalSpaceBytes, tszBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
SnapshotRegOpenKey(
|
|
IN LPCWSTR lpKeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT PHANDLE KeyHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will open a reg key.
|
|
|
|
Arguments:
|
|
|
|
lpKeyName - name of the key.
|
|
|
|
DesiredAccess - accecss flag.
|
|
|
|
KeyHandle - holds the handle on success.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
RtlInitUnicodeString( &KeyName, lpKeyName );
|
|
RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
|
|
NTSTATUS Status;
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
Status = (NTSTATUS)NtOpenKey( KeyHandle, DesiredAccess, &ObjectAttributes );
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SnapshotRegSetValueKey(
|
|
IN HANDLE KeyHandle,
|
|
IN LPCWSTR lpValueName,
|
|
IN DWORD dwType,
|
|
IN LPVOID lpData,
|
|
IN DWORD cbData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will query val key.
|
|
|
|
Arguments:
|
|
|
|
KeyHandle - handle to the reg key.
|
|
|
|
lpValueName - name of the reg val.
|
|
|
|
dwType - type of the value
|
|
|
|
lpData - PVOID data
|
|
|
|
cbData - cb of the data size
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING ValueName;
|
|
|
|
RtlInitUnicodeString( &ValueName, lpValueName );
|
|
|
|
return NtSetValueKey( KeyHandle,
|
|
&ValueName,
|
|
0,
|
|
dwType,
|
|
lpData,
|
|
cbData);
|
|
}
|
|
|
|
NTSTATUS
|
|
SnapshotRegQueryValueKey(
|
|
IN HANDLE KeyHandle,
|
|
IN LPCWSTR lpValueName,
|
|
IN ULONG Length,
|
|
OUT PVOID KeyValue,
|
|
OUT PULONG ResultLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will query val key.
|
|
|
|
Arguments:
|
|
|
|
KeyHandle - handle to the reg key.
|
|
|
|
lpValueName - name of the reg val.
|
|
|
|
Length - length of lpValueName.
|
|
|
|
KeyValue - Holds the value on return.
|
|
|
|
ResultLength - the lenght of the result in bytes.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING ValueName;
|
|
ULONG BufferLength;
|
|
NTSTATUS Status;
|
|
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
|
RtlInitUnicodeString( &ValueName, lpValueName );
|
|
|
|
BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + Length;
|
|
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) malloc(BufferLength);
|
|
if (KeyValueInformation == NULL)
|
|
{
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Status = NtQueryValueKey(
|
|
KeyHandle,
|
|
&ValueName,
|
|
KeyValuePartialInformation,
|
|
KeyValueInformation,
|
|
BufferLength,
|
|
ResultLength
|
|
);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
|
|
RtlCopyMemory(KeyValue,
|
|
KeyValueInformation->Data,
|
|
KeyValueInformation->DataLength
|
|
);
|
|
|
|
*ResultLength = KeyValueInformation->DataLength;
|
|
if (KeyValueInformation->Type == REG_SZ)
|
|
{
|
|
if (KeyValueInformation->DataLength + sizeof(WCHAR) > Length)
|
|
{
|
|
KeyValueInformation->DataLength -= sizeof(WCHAR);
|
|
}
|
|
((PUCHAR)KeyValue)[KeyValueInformation->DataLength++] = 0;
|
|
((PUCHAR)KeyValue)[KeyValueInformation->DataLength] = 0;
|
|
*ResultLength = KeyValueInformation->DataLength + sizeof(WCHAR);
|
|
}
|
|
}
|
|
free(KeyValueInformation);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SnapshotRegEnumKey(
|
|
IN HANDLE KeyHandle,
|
|
IN ULONG Index,
|
|
OUT LPWSTR lpKeyName,
|
|
OUT PULONG lpNameLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function enum reg keys.
|
|
|
|
Arguments:
|
|
|
|
KeyHandle - handle to the reg key.
|
|
|
|
Index - the index of the subkey.
|
|
|
|
lpKeyName - holds the subkey name on return.
|
|
|
|
lpNameLength - the length of the subkey name.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING ValueName;
|
|
ULONG BufferLength;
|
|
NTSTATUS Status;
|
|
PKEY_BASIC_INFORMATION pKeyBasicInformation;
|
|
RtlInitUnicodeString( &ValueName, lpKeyName );
|
|
|
|
BufferLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) + *lpNameLength;
|
|
pKeyBasicInformation = (PKEY_BASIC_INFORMATION) malloc(BufferLength);
|
|
if (pKeyBasicInformation == NULL)
|
|
{
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Status = NtEnumerateKey(
|
|
KeyHandle,
|
|
Index,
|
|
KeyBasicInformation,
|
|
(PVOID)pKeyBasicInformation,
|
|
BufferLength,
|
|
lpNameLength
|
|
);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
RtlCopyMemory(lpKeyName,
|
|
pKeyBasicInformation->Name,
|
|
pKeyBasicInformation->NameLength
|
|
);
|
|
|
|
*lpNameLength = pKeyBasicInformation->NameLength;
|
|
if(*lpNameLength > 0)
|
|
lpKeyName[(*lpNameLength) - 1] = L'\0';
|
|
else
|
|
lpKeyName[0] = L'\0';
|
|
}
|
|
free((BYTE*)pKeyBasicInformation);
|
|
|
|
return Status;
|
|
}
|
|
|
|
void
|
|
LogHardwareInfo(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log hardware info
|
|
(computer name, processor info and netcard info).
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPCWSTR ComputerNameKey = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName";
|
|
LPCWSTR ComputerNameValsz = L"ComputerName";
|
|
LPCWSTR ProcessorKey = L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor";
|
|
LPCWSTR ProcessorSpeedValdw = L"~MHz";
|
|
LPCWSTR ProcessorIdentifierValsz = L"Identifier";
|
|
LPCWSTR ProcessorVendorValsz = L"VendorIdentifier";
|
|
LPCWSTR NetcardKey = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
|
|
LPCWSTR NetcardDescsz = L"Description";
|
|
LPCWSTR NetcardServiceNamesz = L"ServiceName";
|
|
HANDLE hKey;
|
|
HANDLE hSubkey;
|
|
WCHAR szVal[MAX_PATH + 1];
|
|
WCHAR szSubkey[MAX_PATH + 1];
|
|
DWORD dwVal;
|
|
DWORD dwSize;
|
|
DWORD dwSubkeyIndex;
|
|
DWORD dwRes;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
//Get Computer Name
|
|
Status = SnapshotRegOpenKey(ComputerNameKey, KEY_READ, &hKey);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
//WriteToLogFile(hFile, TEXT("Failed to open registry key for hardware information\n\n"));
|
|
return;
|
|
}
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(hKey, ComputerNameValsz, dwSize, szVal, &dwSize);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
//WriteToLogFile(hFile, TEXT("Failed to query registry key value for hardware information\n\n"));
|
|
return;
|
|
}
|
|
NtClose(hKey);
|
|
//WriteToLogFile(hFile, TEXT("Active Computer Name: "));
|
|
szVal[dwSize] = '\0';
|
|
//WriteToLogFileW(hFile, szVal);
|
|
//WriteToLogFile(hFile, TEXT("\n"));
|
|
|
|
//Get Processor Info
|
|
Status = SnapshotRegOpenKey(ProcessorKey, KEY_READ, &hKey);
|
|
gXMLOutput->Write(XMLTAG_HardwareInfoType_ProcesorInfo, (LPCWSTR)NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for hardware information"));
|
|
return;
|
|
}
|
|
dwSubkeyIndex = 0;
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
|
|
Status = SnapshotRegEnumKey(hKey, dwSubkeyIndex, szSubkey, &dwSize);
|
|
while(NT_SUCCESS(Status))
|
|
{
|
|
wcscpy(szVal, ProcessorKey);
|
|
wcscat(szVal, L"\\");
|
|
wcscat(szVal, szSubkey);
|
|
|
|
Status = SnapshotRegOpenKey(szVal, KEY_READ, &hSubkey);
|
|
gXMLOutput->Write(XMLTAG_ProcessorInfoType_Processor, (LPCWSTR)NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for hardware information"));
|
|
return;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
Status = SnapshotRegQueryValueKey(hSubkey, ProcessorSpeedValdw, dwSize, &dwVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
NtClose(hSubkey);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry key value for hardware information"));
|
|
return;
|
|
}
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE, TEXT("%s"), szSubkey);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ProcessorInfoType_Number, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), dwVal);
|
|
gXMLOutput->Write(XMLTAG_ProcessorInfoType_Speed, (LPCTSTR)g_lpszBuffer);
|
|
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(hSubkey, ProcessorIdentifierValsz, dwSize, szVal, &dwSize);
|
|
gXMLOutput->Write(XMLTAG_ProcessorInfoType_Identifier, (LPCTSTR)NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
NtClose(hSubkey);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry key value for hardware information"));
|
|
return;
|
|
}
|
|
WriteToLogFileW(hFile, szVal);
|
|
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(hSubkey, ProcessorVendorValsz, dwSize, szVal, &dwSize);
|
|
gXMLOutput->Write(XMLTAG_ProcessorInfoType_VendorIdent, (LPCTSTR)NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
NtClose(hSubkey);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry key value for hardware information"));
|
|
return;
|
|
}
|
|
WriteToLogFileW(hFile, szVal);
|
|
|
|
NtClose(hSubkey);
|
|
dwSubkeyIndex++;
|
|
Status = SnapshotRegEnumKey(hKey, dwSubkeyIndex, szSubkey, &dwSize);
|
|
}
|
|
NtClose(hKey);
|
|
|
|
//Get NetCard Info
|
|
|
|
gXMLOutput->Write(XMLTAG_HardwareInfoType_NICInfo, (LPCWSTR)NULL);
|
|
Status = SnapshotRegOpenKey(NetcardKey, KEY_READ, &hKey);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for hardware information"));
|
|
return;
|
|
}
|
|
|
|
dwSubkeyIndex = 0;
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegEnumKey(hKey, dwSubkeyIndex, szSubkey, &dwSize);
|
|
while(NT_SUCCESS(Status))
|
|
{
|
|
wcscpy(szVal, NetcardKey);
|
|
wcscat(szVal, L"\\");
|
|
wcscat(szVal, szSubkey);
|
|
Status = SnapshotRegOpenKey(szVal, KEY_READ, &hSubkey);
|
|
gXMLOutput->Write(XMLTAG_NICInfoType_NIC, (LPCWSTR)NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for hardware information"));
|
|
return;
|
|
}
|
|
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(hSubkey, NetcardDescsz, dwSize, szVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
NtClose(hSubkey);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry key value for hardware information"));
|
|
return;
|
|
}
|
|
|
|
gXMLOutput->Write(XMLTAG_NICInfoType_Description, (LPCWSTR)NULL);
|
|
WriteToLogFileW(hFile, szVal);
|
|
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(hSubkey, NetcardServiceNamesz, dwSize, szVal, &dwSize);
|
|
gXMLOutput->Write(XMLTAG_NICInfoType_ServiceName, (LPCWSTR)NULL);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
NtClose(hSubkey);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry key value for hardware information"));
|
|
return;
|
|
}
|
|
WriteToLogFileW(hFile, szVal);
|
|
NtClose(hSubkey);
|
|
dwSubkeyIndex++;
|
|
Status = SnapshotRegEnumKey(hKey, dwSubkeyIndex, szSubkey, &dwSize);
|
|
}
|
|
|
|
NtClose(hKey);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
SnapshotIsVolumeName(
|
|
LPWSTR Name
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is a helper for LogPhysicalDiskInfo.
|
|
|
|
Arguments:
|
|
|
|
Name - name to verify.
|
|
|
|
Return Value:
|
|
|
|
TRUE if is volume name, else FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (Name[0] == '\\' &&
|
|
(Name[1] == '?' || Name[1] == '\\') &&
|
|
Name[2] == '?' &&
|
|
Name[3] == '\\' &&
|
|
Name[4] == 'V' &&
|
|
Name[5] == 'o' &&
|
|
Name[6] == 'l' &&
|
|
Name[7] == 'u' &&
|
|
Name[8] == 'm' &&
|
|
Name[9] == 'e' &&
|
|
Name[10] == '{' &&
|
|
Name[19] == '-' &&
|
|
Name[24] == '-' &&
|
|
Name[29] == '-' &&
|
|
Name[34] == '-' &&
|
|
Name[47] == '}' ) {
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void
|
|
WriteTagEntry(
|
|
PSYSTEM_POOLTAG TagInfo,
|
|
ULONG SessionId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will write the XML tags for a single tag entry. It is used to log both session and system pool information
|
|
|
|
Arguments:
|
|
|
|
TagInfo - Contains the alloc info. for the particular tag
|
|
Session id -
|
|
-1 for System pool
|
|
Session id for Session pool
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
if (TagInfo == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (!(TagInfo->PagedAllocs) && !(TagInfo->NonPagedAllocs)) {
|
|
//We don't need a TagEntry for BIG pool
|
|
return;
|
|
}
|
|
|
|
gXMLOutput->Write( XMLTAG_PoolInfo_TagEntry, (LPCWSTR)NULL);
|
|
|
|
//Add the entries
|
|
_stprintf (g_lpszBuffer, TEXT("%c%c%c%c"),TagInfo->Tag[0],TagInfo->Tag[1],TagInfo->Tag[2],TagInfo->Tag[3]);
|
|
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_PoolTag, (LPCTSTR)g_lpszBuffer);
|
|
|
|
if (TagInfo->PagedAllocs != 0)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_PoolType, _T("Paged"));
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),TagInfo->PagedAllocs);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_NumAllocs, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),TagInfo->PagedFrees);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_NumFrees, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),TagInfo->PagedUsed);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_NumBytes, (LPCTSTR)g_lpszBuffer);
|
|
|
|
|
|
}
|
|
else if (TagInfo->NonPagedAllocs != 0)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_PoolType, _T("Nonp"));
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),TagInfo->NonPagedAllocs);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_NumAllocs, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),TagInfo->NonPagedFrees);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_NumFrees, (LPCTSTR)g_lpszBuffer);
|
|
|
|
_stprintf (g_lpszBuffer, TEXT("%ld"),TagInfo->NonPagedUsed);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_NumBytes, (LPCTSTR)g_lpszBuffer);
|
|
|
|
}
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%ld"),SessionId);
|
|
gXMLOutput->Write(XMLTAG_PoolInfo_TagEntry_SessionID, (LPCTSTR)g_lpszBuffer);
|
|
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
GetSystemPoolInformation(
|
|
PUCHAR *SystemBuffer,
|
|
SIZE_T *SystemBufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve system pool tag information
|
|
|
|
Arguments:
|
|
|
|
SystemBuffer - Will hold the tag information
|
|
SystemBufferSize - Size of this buffer
|
|
|
|
Return Value:
|
|
|
|
Status of the query
|
|
|
|
--*/
|
|
|
|
{
|
|
size_t NewBufferSize;
|
|
NTSTATUS ReturnedStatus = STATUS_SUCCESS;
|
|
|
|
if( SystemBuffer == NULL || SystemBufferSize == NULL ) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// There is no buffer allocated yet.
|
|
//
|
|
|
|
if( *SystemBufferSize == 0 || *SystemBuffer == NULL ) {
|
|
|
|
NewBufferSize = sizeof( UCHAR ) * BUFFER_SIZE_STEP;
|
|
|
|
*SystemBuffer = (PUCHAR) malloc( NewBufferSize );
|
|
|
|
if( *SystemBuffer != NULL ) {
|
|
|
|
*SystemBufferSize = NewBufferSize;
|
|
|
|
} else {
|
|
|
|
//
|
|
// insufficient memory
|
|
//
|
|
|
|
ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Iterate by buffer's size.
|
|
//
|
|
|
|
while( *SystemBuffer != NULL ) {
|
|
|
|
ReturnedStatus = NtQuerySystemInformation (
|
|
SystemPoolTagInformation,
|
|
*SystemBuffer,
|
|
(ULONG)*SystemBufferSize,
|
|
NULL );
|
|
|
|
if( ! NT_SUCCESS(ReturnedStatus) ) {
|
|
|
|
//
|
|
// Free the current buffer.
|
|
//
|
|
|
|
free( *SystemBuffer );
|
|
|
|
*SystemBuffer = NULL;
|
|
|
|
if (ReturnedStatus == STATUS_INFO_LENGTH_MISMATCH) {
|
|
|
|
//
|
|
// Try with a larger buffer size.
|
|
//
|
|
|
|
NewBufferSize = *SystemBufferSize + BUFFER_SIZE_STEP;
|
|
|
|
*SystemBuffer = (PUCHAR) malloc( NewBufferSize );
|
|
|
|
if( *SystemBuffer != NULL ) {
|
|
|
|
//
|
|
// Allocated new buffer.
|
|
//
|
|
|
|
*SystemBufferSize = NewBufferSize;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Insufficient memory.
|
|
//
|
|
|
|
ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
*SystemBufferSize = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*SystemBufferSize = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// NtQuerySystemInformation returned success.
|
|
//
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
return ReturnedStatus;
|
|
}
|
|
|
|
NTSTATUS
|
|
GetSessionPoolInformation ( )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve pool tag information for terminal server sessions
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Status of the query
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG NewBufferSize;
|
|
SYSTEM_SESSION_PROCESS_INFORMATION SessionProcessInformation;
|
|
ULONG SessionBufferSize = 0;
|
|
PSYSTEM_SESSION_POOLTAG_INFORMATION SessionBuffer = NULL;
|
|
PSYSTEM_SESSION_POOLTAG_INFORMATION CrtSessionPooltagInfo;
|
|
ULONG SessionTag=0;
|
|
PSYSTEM_POOLTAG TagInfo;
|
|
|
|
|
|
//Get information for all sessions
|
|
SessionProcessInformation.SessionId = -1;
|
|
|
|
while (TRUE)
|
|
{
|
|
SessionProcessInformation.SizeOfBuf = SessionBufferSize;
|
|
SessionProcessInformation.Buffer = SessionBuffer;
|
|
|
|
Status = NtQuerySystemInformation (SystemSessionPoolTagInformation,
|
|
&SessionProcessInformation,
|
|
sizeof (SessionProcessInformation),
|
|
& NewBufferSize);
|
|
|
|
if (Status == STATUS_INFO_LENGTH_MISMATCH) {
|
|
|
|
if (SessionBufferSize != 0) {
|
|
|
|
//
|
|
// Our buffer is just not large enough. Add BUFFER_SIZE_STEP
|
|
// to its size.
|
|
|
|
free (SessionBuffer);
|
|
|
|
NewBufferSize = SessionBufferSize + BUFFER_SIZE_STEP;
|
|
}
|
|
|
|
SessionBuffer = (PSYSTEM_SESSION_POOLTAG_INFORMATION)malloc (NewBufferSize);
|
|
|
|
if (SessionBuffer == NULL) {
|
|
|
|
//
|
|
// Bad luck, we cannot allocate so much memory
|
|
// so bail out.
|
|
//
|
|
|
|
SessionBufferSize = 0;
|
|
|
|
if (SessionBuffer) {
|
|
free(SessionBuffer);
|
|
}
|
|
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
SessionBufferSize = NewBufferSize;
|
|
}
|
|
else if (Status == STATUS_INVALID_INFO_CLASS) {
|
|
|
|
//
|
|
// This is probably a Win2k or XP box so we just ignore the error.
|
|
//
|
|
|
|
ASSERT (SessionBuffer == NULL);
|
|
|
|
break;
|
|
}
|
|
else if (!NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Query failed for some reason.
|
|
//
|
|
|
|
return Status;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// All set - we have the information.
|
|
//
|
|
|
|
if (NewBufferSize == 0 && SessionBuffer != NULL) {
|
|
|
|
//
|
|
// We didn't get back any information (e.g. the session doesn't exist).
|
|
//
|
|
|
|
SessionBuffer->Count = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//No sessions in existence.. just return
|
|
if (SessionBuffer == NULL) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//We have the session info. now.. ready for output
|
|
CrtSessionPooltagInfo = SessionBuffer;
|
|
|
|
while (TRUE) {
|
|
|
|
for (SessionTag = 0; SessionTag < CrtSessionPooltagInfo->Count; SessionTag += 1) {
|
|
|
|
TagInfo = &(CrtSessionPooltagInfo->TagInfo[ SessionTag ]);
|
|
|
|
WriteTagEntry(TagInfo,CrtSessionPooltagInfo->SessionId);
|
|
|
|
}
|
|
|
|
if (CrtSessionPooltagInfo->NextEntryOffset > 0)
|
|
CrtSessionPooltagInfo = (PSYSTEM_SESSION_POOLTAG_INFORMATION)
|
|
((PCHAR)CrtSessionPooltagInfo + CrtSessionPooltagInfo->NextEntryOffset);
|
|
else
|
|
break;
|
|
|
|
}
|
|
|
|
if (SessionBuffer)
|
|
{
|
|
free(SessionBuffer);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
void LogPoolInfo(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log information about the system and session pools
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status; // status from NT api
|
|
DWORD x= 0; // counter
|
|
PSYSTEM_POOLTAG_INFORMATION PoolInfo;
|
|
PUCHAR SystemBuffer = NULL;
|
|
SIZE_T SystemBufferSize = 0;
|
|
|
|
// grab all pool information
|
|
Status = GetSystemPoolInformation(
|
|
&SystemBuffer,
|
|
&SystemBufferSize
|
|
);
|
|
|
|
if (! NT_SUCCESS(Status)) {
|
|
|
|
goto Error;
|
|
}
|
|
|
|
PoolInfo = (PSYSTEM_POOLTAG_INFORMATION)SystemBuffer;
|
|
|
|
//Add the tags for the PoolInfo
|
|
gXMLOutput->Write( XMLTAG_SETDataType_PoolInfo, (LPCWSTR)NULL);
|
|
|
|
gXMLOutput->Write( XMLTAG_PoolInfo_AllocInformation, (LPCWSTR)NULL);
|
|
|
|
for (x = 0; x < (int)PoolInfo->Count; x++) {
|
|
WriteTagEntry(&(PoolInfo->TagInfo[x]),-1);
|
|
}
|
|
|
|
GetSessionPoolInformation();
|
|
|
|
Error:
|
|
if(SystemBuffer) {
|
|
free(SystemBuffer);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
LogPhysicalDiskInfo(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log the physical disk infor.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
PMOUNTMGR_MOUNT_POINTS mountPoints = NULL;
|
|
MOUNTMGR_MOUNT_POINT mountPoint;
|
|
ULONG returnSize, success;
|
|
SYSTEM_DEVICE_INFORMATION DevInfo;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG NumberOfDisks;
|
|
PWCHAR deviceNameBuffer;
|
|
ULONG i;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
DISK_GEOMETRY disk_geometry;
|
|
PDISK_CACHE_INFORMATION disk_cache;
|
|
PSCSI_ADDRESS scsi_address;
|
|
PWCHAR KeyName;
|
|
WCHAR wszVal[MAX_PATH + 1];
|
|
HANDLE hDisk = INVALID_HANDLE_VALUE;
|
|
UNICODE_STRING UnicodeName;
|
|
|
|
ULONG SizeNeeded;
|
|
DWORD dwSize;
|
|
const ULONG MAX_MOUNT_POINTS_SIZE = 4096;
|
|
//
|
|
// Get the Number of Physical Disks
|
|
//
|
|
gXMLOutput->Write(XMLTAG_DiskInfoType_PhysicalInfo, (LPCWSTR)NULL);
|
|
|
|
RtlZeroMemory(&DevInfo, sizeof(DevInfo));
|
|
Status = NtQuerySystemInformation(
|
|
SystemDeviceInformation,
|
|
&DevInfo, sizeof (DevInfo), NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed to query system information"));
|
|
return;
|
|
}
|
|
|
|
NumberOfDisks = DevInfo.NumberOfDisks;
|
|
|
|
//
|
|
// Open Each Physical Disk and get Disk Layout information
|
|
//
|
|
|
|
for (i=0; i < NumberOfDisks; i++)
|
|
{
|
|
|
|
DISK_CACHE_INFORMATION cacheInfo;
|
|
WCHAR driveBuffer[20];
|
|
|
|
HANDLE PartitionHandle;
|
|
HANDLE KeyHandle;
|
|
ULONG DataLength;
|
|
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_Disk, (LPCWSTR)NULL);
|
|
|
|
//
|
|
// Get Partition0 handle to get the Disk layout
|
|
//
|
|
deviceNameBuffer = (PWCHAR) g_lpszBuffer;
|
|
swprintf(deviceNameBuffer, L"\\Device\\Harddisk%d\\Partition0", i);
|
|
|
|
RtlInitUnicodeString(&UnicodeName, deviceNameBuffer);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Status = NtOpenFile(
|
|
&PartitionHandle,
|
|
FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
|
|
);
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed calling NtOpenFile"));
|
|
return;
|
|
}
|
|
|
|
RtlZeroMemory(&disk_geometry, sizeof(DISK_GEOMETRY));
|
|
|
|
// get geomerty information, the caller wants this
|
|
Status = NtDeviceIoControlFile(PartitionHandle,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
|
NULL,
|
|
0,
|
|
&disk_geometry,
|
|
sizeof (DISK_GEOMETRY)
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(PartitionHandle);
|
|
WriteToLogFile(hFile, TEXT("Failed calling NtDeviceIoControlFile 1"));
|
|
return;
|
|
}
|
|
|
|
scsi_address = (PSCSI_ADDRESS) g_lpszBuffer;
|
|
Status = NtDeviceIoControlFile(PartitionHandle,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_SCSI_GET_ADDRESS,
|
|
NULL,
|
|
0,
|
|
scsi_address,
|
|
sizeof (SCSI_ADDRESS)
|
|
);
|
|
|
|
NtClose(PartitionHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed calling NtDeviceIoControlFile 2"));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get Manufacturer's name from Registry
|
|
// We need to get the SCSI Address and then query the Registry with it.
|
|
//
|
|
|
|
KeyName = (PWCHAR) g_lpszBuffer;
|
|
swprintf(KeyName,
|
|
L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target ID %d\\Logical Unit Id %d",
|
|
scsi_address->PortNumber, scsi_address->PathId, scsi_address->TargetId, scsi_address->Lun
|
|
);
|
|
Status = SnapshotRegOpenKey(KeyName, KEY_READ, &KeyHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for physical disk information"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(KeyHandle, L"Identifier", dwSize, wszVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(KeyHandle);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry value for physical disk information"));
|
|
return;
|
|
}
|
|
NtClose(KeyHandle);
|
|
}
|
|
|
|
//
|
|
// Package all information about this disk and write an event record
|
|
//
|
|
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), i);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_ID, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), disk_geometry.BytesPerSector);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_BytesPerSector, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), disk_geometry.SectorsPerTrack);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_SectorsPerTrack, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), disk_geometry.TracksPerCylinder);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_TracksPerCylinder, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%I64d"), disk_geometry.Cylinders.QuadPart);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_NumberOfCylinders, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), scsi_address->PortNumber);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_PortNumber, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), scsi_address->PathId);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_PathID, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), scsi_address->TargetId);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_TargetID, (LPCTSTR)g_lpszBuffer);
|
|
_stprintf(g_lpszBuffer, TEXT("%d"), scsi_address->Lun);
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_LUN, (LPCTSTR)g_lpszBuffer);
|
|
|
|
gXMLOutput->Write(XMLTAG_PhysicalInfoType_Manufacturer, (LPCWSTR)NULL);
|
|
WriteToLogFileW(hFile, wszVal);
|
|
}
|
|
|
|
//
|
|
// Get Logical Disk Information
|
|
//
|
|
wcscpy(wszVal, MOUNTMGR_DEVICE_NAME);
|
|
RtlInitUnicodeString(&UnicodeName, (LPWSTR)wszVal);
|
|
UnicodeName.MaximumLength = MAXSTR;
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
Status = NtCreateFile(
|
|
&hDisk,
|
|
GENERIC_READ | SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE,
|
|
NULL, 0);
|
|
|
|
gXMLOutput->Write(XMLTAG_DiskInfoType_PartitionByDiskInfo, (LPCWSTR)NULL);
|
|
|
|
if (!NT_SUCCESS(Status) )
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed calling NtCreateFile"));
|
|
return;
|
|
}
|
|
|
|
mountPoints = (PMOUNTMGR_MOUNT_POINTS)VirtualAlloc (NULL,
|
|
MAX_MOUNT_POINTS_SIZE,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE );
|
|
|
|
if ( !mountPoints )
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed calling VirtualAlloc"));
|
|
goto error;
|
|
}
|
|
|
|
RtlZeroMemory(&mountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
|
|
mountPoints->Size = 0;
|
|
returnSize = 0;
|
|
|
|
Status = NtDeviceIoControlFile(hDisk,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_MOUNTMGR_QUERY_POINTS,
|
|
mountPoints,
|
|
sizeof(MOUNTMGR_MOUNT_POINT),
|
|
mountPoints,
|
|
MAX_MOUNT_POINTS_SIZE
|
|
);
|
|
|
|
if ( STATUS_BUFFER_OVERFLOW == Status )
|
|
{
|
|
ULONG size = mountPoints->Size;
|
|
|
|
VirtualFree( mountPoints, 0, MEM_RELEASE);
|
|
mountPoints = NULL;
|
|
|
|
if ( size != 0 )
|
|
{
|
|
//
|
|
// retry with the new size
|
|
//
|
|
mountPoints = (PMOUNTMGR_MOUNT_POINTS)VirtualAlloc (NULL,
|
|
size,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE );
|
|
|
|
if ( !mountPoints )
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed calling VirtualAlloc"));
|
|
goto error;
|
|
}
|
|
|
|
RtlZeroMemory(&mountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
|
|
returnSize = 0;
|
|
|
|
Status = NtDeviceIoControlFile(hDisk,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_MOUNTMGR_QUERY_POINTS,
|
|
mountPoints,
|
|
sizeof(MOUNTMGR_MOUNT_POINT),
|
|
mountPoints,
|
|
size
|
|
);
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
WCHAR name[MAX_PATH + 1];
|
|
CHAR OutBuffer[MAXSTR];
|
|
PMOUNTMGR_MOUNT_POINT point;
|
|
UNICODE_STRING VolumePoint;
|
|
PVOLUME_DISK_EXTENTS VolExt;
|
|
PDISK_EXTENT DiskExt;
|
|
ULONG lMountIndex;
|
|
int iDisk, iPartition;
|
|
iDisk = -1;
|
|
|
|
|
|
for (lMountIndex=0; lMountIndex<mountPoints->NumberOfMountPoints; lMountIndex++)
|
|
{
|
|
point = &mountPoints->MountPoints[lMountIndex];
|
|
|
|
if (point->SymbolicLinkNameLength)
|
|
{
|
|
RtlCopyMemory(name,
|
|
(PCHAR) mountPoints + point->SymbolicLinkNameOffset,
|
|
point->SymbolicLinkNameLength);
|
|
name[point->SymbolicLinkNameLength/sizeof(WCHAR)] = 0;
|
|
if (SnapshotIsVolumeName(name))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
if (point->DeviceNameLength)
|
|
{
|
|
HANDLE hVolume;
|
|
ULONG dwBytesReturned;
|
|
PSTORAGE_DEVICE_NUMBER Number;
|
|
DWORD IErrorMode;
|
|
|
|
RtlCopyMemory(name,
|
|
(PCHAR) mountPoints + point->DeviceNameOffset,
|
|
point->DeviceNameLength);
|
|
name[point->DeviceNameLength/sizeof(WCHAR)] = 0;
|
|
|
|
RtlInitUnicodeString(&UnicodeName, name);
|
|
UnicodeName.MaximumLength = MAXSTR;
|
|
|
|
//
|
|
// If the device name does not have the harddisk prefix
|
|
// then it may be a floppy or cdrom and we want avoid
|
|
// calling NtCreateFile on them.
|
|
//
|
|
if(_wcsnicmp(name,L"\\device\\harddisk",16))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
//
|
|
// We do not want any pop up dialog here in case we are unable to
|
|
// access the volume.
|
|
//
|
|
IErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
|
|
Status = NtCreateFile(
|
|
&hVolume,
|
|
GENERIC_READ | SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL, 0);
|
|
SetErrorMode(IErrorMode);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
RtlZeroMemory(OutBuffer, MAXSTR);
|
|
dwBytesReturned = 0;
|
|
VolExt = (PVOLUME_DISK_EXTENTS) OutBuffer;
|
|
|
|
Status = NtDeviceIoControlFile(hVolume,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
|
|
NULL,
|
|
0,
|
|
OutBuffer,
|
|
MAXSTR
|
|
);
|
|
if (NT_SUCCESS(Status) )
|
|
{
|
|
ULONG j;
|
|
ULONG NumberOfExtents = VolExt->NumberOfDiskExtents;
|
|
TCHAR tszTemp[NUM_OF_CHAR_IN_ULONG64];
|
|
|
|
if(iDisk == -1 || iDisk != (&VolExt->Extents[0])->DiskNumber)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_PartitionByDiskInfoType_Disk, (LPCWSTR)NULL);
|
|
_stnprintf(tszTemp, NUM_OF_CHAR_IN_ULONG64, TEXT("%d"), (&VolExt->Extents[0])->DiskNumber);
|
|
tszTemp[ _tsizeof(tszTemp) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_PartitionByDiskInfoType_DiskID, (LPCTSTR)tszTemp);
|
|
iDisk = (&VolExt->Extents[0])->DiskNumber;
|
|
iPartition = 0;
|
|
gXMLOutput->Write(XMLTAG_PartitionByDiskInfoType_Partitions, (LPCWSTR)NULL);
|
|
}
|
|
gXMLOutput->Write(XMLTAG_PartitionByDiskInfoType_PartitionInfo, (LPCWSTR)NULL);
|
|
|
|
_stnprintf(tszTemp, NUM_OF_CHAR_IN_ULONG64,
|
|
TEXT("%d"),
|
|
iPartition);
|
|
tszTemp[ _tsizeof(tszTemp) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_PartitionInfoType_PartitionID, (LPCTSTR)tszTemp);
|
|
|
|
gXMLOutput->Write(XMLTAG_PartitionInfoType_Extents, (LPCWSTR)NULL);
|
|
gXMLOutput->Write(XMLTAG_PartitionInfoType_ExtentInfo, (LPCWSTR)NULL);
|
|
for (j=0; j < NumberOfExtents; j++)
|
|
{
|
|
DiskExt = &VolExt->Extents[j];
|
|
_stnprintf(tszTemp, NUM_OF_CHAR_IN_ULONG64,TEXT("%d"),j);
|
|
tszTemp[ _tsizeof(tszTemp) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ExtentInfoType_ID, tszTemp);
|
|
|
|
_stnprintf(tszTemp, NUM_OF_CHAR_IN_ULONG64, TEXT("%I64d"),
|
|
DiskExt->StartingOffset.QuadPart);
|
|
tszTemp[ _tsizeof(tszTemp) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ExtentInfoType_StartingOffset, tszTemp);
|
|
|
|
_stnprintf(tszTemp, NUM_OF_CHAR_IN_ULONG64, TEXT("%I64d"), DiskExt->ExtentLength.QuadPart);
|
|
tszTemp[ _tsizeof(tszTemp) - 1 ] = 0;
|
|
gXMLOutput->Write(XMLTAG_ExtentInfoType_PartitionSize, tszTemp);
|
|
}
|
|
iPartition++;
|
|
}
|
|
NtClose(hVolume);
|
|
}
|
|
}
|
|
}
|
|
|
|
error:
|
|
NtClose(hDisk);
|
|
|
|
if ( mountPoints )
|
|
VirtualFree( mountPoints, 0, MEM_RELEASE );
|
|
}
|
|
|
|
void
|
|
LogHotfixes(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log hotfixes.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPCWSTR HotFixKey = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix";
|
|
LPCWSTR wszValName = L"Installed";
|
|
HANDLE hKey, hSubkey;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
UINT i;
|
|
DWORD dwSize, dwVal, dwSubkeyIndex;
|
|
WCHAR szKey[MAX_PATH + 1];
|
|
WCHAR szSubkey[MAX_PATH + 1];
|
|
|
|
|
|
Status = SnapshotRegOpenKey(HotFixKey, KEY_READ, &hKey);
|
|
if (!NT_SUCCESS(Status) )
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Hotfix registry key does not exist or open failed"));
|
|
return;
|
|
}
|
|
|
|
dwSubkeyIndex = 0;
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegEnumKey(hKey, dwSubkeyIndex, szSubkey, &dwSize);
|
|
while(NT_SUCCESS(Status))
|
|
{
|
|
wcscpy(szKey, HotFixKey);
|
|
wcscat(szKey, L"\\");
|
|
wcscat(szKey, szSubkey);
|
|
|
|
Status = SnapshotRegOpenKey(szKey, KEY_READ, &hSubkey);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
return;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
Status = SnapshotRegQueryValueKey(hSubkey, wszValName, dwSize, &dwVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(hKey);
|
|
NtClose(hSubkey);
|
|
WriteToLogFile(hFile, TEXT("Failed to query registry key value for hotfix info"));
|
|
return;
|
|
}
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%s"),
|
|
szSubkey);
|
|
if(dwVal == 1)
|
|
{
|
|
gXMLOutput->Write(XMLTAG_OSInfoType_Hotfix, (LPCWSTR)NULL);
|
|
WriteToLogFile(hFile, g_lpszBuffer);
|
|
}
|
|
|
|
NtClose(hSubkey);
|
|
dwSubkeyIndex++;
|
|
Status = SnapshotRegEnumKey(hKey, dwSubkeyIndex, szSubkey, &dwSize);
|
|
}
|
|
NtClose(hKey);
|
|
}
|
|
|
|
void
|
|
LogOsInfo(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log OS infor.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPCWSTR OsInfoKey = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion";
|
|
LPCWSTR awszValName[] =
|
|
{
|
|
//L"BuildLab",
|
|
L"CurrentBuildNumber",
|
|
L"CurrentType",
|
|
L"CurrentVersion",
|
|
//L"InstallDate",
|
|
L"PathName",
|
|
//L"ProductId",
|
|
L"ProductName",
|
|
//L"RegDone",
|
|
//L"RegisteredOrgnization",
|
|
//L"RegisteredOwner",
|
|
L"SoftwareType",
|
|
L"SourcePath",
|
|
L"SystemRoot"
|
|
};
|
|
|
|
XMLTAG tags[] =
|
|
{
|
|
XMLTAG_OSInfoType_CurrentBuild,
|
|
XMLTAG_OSInfoType_CurrentType,
|
|
XMLTAG_OSInfoType_CurrentVersion,
|
|
XMLTAG_OSInfoType_Path,
|
|
XMLTAG_OSInfoType_ProductName,
|
|
XMLTAG_OSInfoType_SoftwareType,
|
|
XMLTAG_OSInfoType_SourcePath,
|
|
XMLTAG_OSInfoType_SystemRoot
|
|
};
|
|
|
|
UINT uVals = sizeof(awszValName) / sizeof(LPCWSTR);
|
|
HANDLE hKey;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
UINT i;
|
|
WCHAR wszVal[MAX_PATH + 1];
|
|
DWORD dwSize;
|
|
SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo = { 0 };
|
|
|
|
Status = SnapshotRegOpenKey(OsInfoKey, KEY_READ, &hKey);
|
|
if (!NT_SUCCESS(Status) )
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for os version info"));
|
|
return;
|
|
}
|
|
|
|
for(i = 0; i < uVals; i++)
|
|
{
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
Status = SnapshotRegQueryValueKey(hKey, awszValName[i], dwSize, wszVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
gXMLOutput->Write(tags[i], (LPCWSTR)NULL);
|
|
|
|
WriteToLogFileW(hFile, wszVal);
|
|
}
|
|
NtClose(hKey);
|
|
|
|
Status = NtQuerySystemInformation(
|
|
SystemKernelDebuggerInformation,
|
|
&KdInfo,
|
|
sizeof(KdInfo),
|
|
NULL);
|
|
|
|
if ((NT_SUCCESS(Status)) && KdInfo.KernelDebuggerEnabled)
|
|
{
|
|
_stprintf(g_lpszBuffer, TEXT("YES"));
|
|
}
|
|
else
|
|
{
|
|
_stprintf(g_lpszBuffer, TEXT("NO"));
|
|
}
|
|
gXMLOutput->Write(XMLTAG_OSInfoType_DebuggerEnabled, (LPCTSTR)g_lpszBuffer);
|
|
|
|
}
|
|
|
|
void
|
|
LogBIOSInfo(
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve and log the system BIOS info.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPCWSTR BiosInfoKey = L"\\Registry\\Machine\\Hardware\\Description\\System";
|
|
LPCWSTR awszValName[] =
|
|
{
|
|
L"Identifier",
|
|
L"SystemBiosDate",
|
|
L"SystemBiosVersion",
|
|
L"VideoBiosDate",
|
|
L"VideoBiosVersion"
|
|
};
|
|
XMLTAG tags[] =
|
|
{
|
|
XMLTAG_BiosInfoType_Identifier,
|
|
XMLTAG_BiosInfoType_SystemBiosDate,
|
|
XMLTAG_BiosInfoType_SystemBiosVersion,
|
|
XMLTAG_BiosInfoType_VideoBiosDate,
|
|
XMLTAG_BiosInfoType_VideoBiosVersion
|
|
};
|
|
|
|
UINT uVals = sizeof(awszValName) / sizeof(LPCWSTR);
|
|
HANDLE hKey;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
UINT i;
|
|
WCHAR wszVal[MAX_PATH + 1];
|
|
LPWSTR pwsz;
|
|
DWORD dwSize, dwLen;
|
|
|
|
gXMLOutput->Write(XMLTAG_HardwareInfoType_BiosInfo, (LPCWSTR)NULL);
|
|
|
|
Status = SnapshotRegOpenKey(BiosInfoKey, KEY_READ, &hKey);
|
|
if (!NT_SUCCESS(Status) )
|
|
{
|
|
WriteToLogFile(hFile, TEXT("Failed to open registry key for BIOS info"));
|
|
return;
|
|
}
|
|
//WriteToLogFile(hFile, TEXT("BIOS Info:\n"));
|
|
|
|
for(i = 0; i < uVals; i++)
|
|
{
|
|
dwSize = MAX_PATH * sizeof(WCHAR);
|
|
|
|
Status = SnapshotRegQueryValueKey(hKey, awszValName[i], dwSize, wszVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
continue;
|
|
}
|
|
gXMLOutput->Write(tags[i], (LPCWSTR)NULL);
|
|
|
|
dwLen = 0;
|
|
pwsz = wszVal;
|
|
while(dwLen + 1< dwSize / sizeof(WCHAR))
|
|
{
|
|
WriteToLogFileW(hFile, pwsz);
|
|
dwLen += wcslen(pwsz) + 1;
|
|
pwsz += wcslen(pwsz) + 1;
|
|
}
|
|
}
|
|
NtClose(hKey);
|
|
}
|
|
|
|
void
|
|
DeleteOldFiles(
|
|
LPCTSTR lpPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function delete the old log files. The time is in number of days.
|
|
We will first check the registry, if user has a specifid number of days,
|
|
it will be used, else the default will be used.
|
|
|
|
Arguments:
|
|
|
|
lpPath - the directory where snapshot are logged.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPCWSTR lpValName = L"SnapshotHistoryFiles";
|
|
HANDLE hKey, hFile;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD dwSize, dwVal;
|
|
TCHAR szFileName[MAX_PATH + 1];
|
|
WIN32_FIND_DATA winData;
|
|
BOOL bFound = TRUE;
|
|
SYSTEMTIME systime;
|
|
FILETIME filetime;
|
|
__int64 i64Filetime, i64Filetime1;
|
|
|
|
GetSystemTime(&systime);
|
|
SystemTimeToFileTime(&systime, &filetime);
|
|
i64Filetime = (__int64)filetime.dwHighDateTime;
|
|
i64Filetime <<= 32;
|
|
i64Filetime |= (__int64)filetime.dwLowDateTime;
|
|
|
|
Status = SnapshotRegOpenKey(ReliabilityKey, KEY_ALL_ACCESS, &hKey);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
Status = SnapshotRegQueryValueKey(hKey, lpValName, dwSize, &dwVal, &dwSize);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
dwVal = DEFAULT_HISTORYFILES;
|
|
}
|
|
else if (dwVal > MAX_HISTORYFILES)
|
|
{
|
|
dwVal = MAX_HISTORYFILES;
|
|
}
|
|
|
|
NtClose(hKey);
|
|
}
|
|
else
|
|
{
|
|
dwVal = DEFAULT_HISTORYFILES;
|
|
}
|
|
|
|
//
|
|
// make sure buffer won't overflow.
|
|
// 32: shutdown_YYYYMMDDHHMMSS.xml
|
|
//
|
|
if ( wcslen( lpPath ) > _tsizeof(szFileName) - 32 )
|
|
return;
|
|
|
|
lstrcpy(szFileName, lpPath);
|
|
lstrcat(szFileName, TEXT("\\ShutDown_*"));
|
|
|
|
hFile = FindFirstFile(szFileName, &winData);
|
|
while(hFile != INVALID_HANDLE_VALUE && bFound)
|
|
{
|
|
i64Filetime1 = (__int64)winData.ftCreationTime.dwHighDateTime;
|
|
i64Filetime1 <<= 32;
|
|
i64Filetime1 |= (__int64)winData.ftCreationTime.dwLowDateTime;
|
|
|
|
if(i64Filetime - i64Filetime1 >= (const __int64)24*60*60*10000000 * dwVal)
|
|
{
|
|
lstrcpy(szFileName, lpPath);
|
|
lstrcat(szFileName, TEXT("\\"));
|
|
lstrcat(szFileName,winData.cFileName);
|
|
DeleteFile(szFileName);
|
|
}
|
|
bFound = FindNextFile(hFile, &winData);
|
|
}
|
|
|
|
if(hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
FindClose(hFile);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// Removing Extension DLL function
|
|
//
|
|
|
|
//
|
|
// Each extension DLL must implment and export the following function.
|
|
//
|
|
typedef BOOL (* EXTENSIONDLLPROC)(LPWSTR , LPDWORD);
|
|
|
|
void
|
|
LoadExtensionDlls(
|
|
HANDLE hFile)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will load all extension dlls. All extension dlls
|
|
are reg val keys under the ExtensionDlls key (which is under the
|
|
reliability key). The values are all DWORD, 0 means dont load,
|
|
any other value means load.
|
|
|
|
Arguments:
|
|
|
|
hFile - Handle to the file to write to.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPCWSTR lpKeyName = L"ExtensionDlls";
|
|
LPCSTR szProcName = "GetSnapShotInfo";
|
|
HANDLE hKey;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
DWORD dwSize, dwVal;
|
|
WCHAR szSysdir[MAX_PATH + 1];
|
|
WCHAR szDll[MAX_PATH + 1];
|
|
WCHAR szPath[MAX_PATH + 1];
|
|
LPTSTR szTempFileName;
|
|
|
|
|
|
_stnprintf(g_lpszBuffer, STR_BUFFER_SIZE,
|
|
TEXT("%s\\%s"),
|
|
ReliabilityKey,
|
|
lpKeyName
|
|
);
|
|
g_lpszBuffer[ _tsizeof(g_lpszBuffer) - 1 ] = 0;
|
|
|
|
GetSystemDirectory(szSysdir, MAX_PATH);
|
|
|
|
Status = SnapshotRegOpenKey(g_lpszBuffer, KEY_ALL_ACCESS, &hKey);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
ULONG index = 0;
|
|
ULONG resultlen;
|
|
DWORD dwVal;
|
|
PKEY_VALUE_FULL_INFORMATION pv = (PKEY_VALUE_FULL_INFORMATION)g_lpszBuffer;
|
|
HMODULE hExtDll = NULL;
|
|
EXTENSIONDLLPROC pnExtproc = NULL;
|
|
LPWSTR psz = NULL;
|
|
|
|
psz = (LPWSTR)LocalAlloc(LMEM_FIXED, BUFFER_SIZE);
|
|
if(!psz)
|
|
{
|
|
NtClose(hKey);
|
|
return;
|
|
}
|
|
|
|
while(1)
|
|
{
|
|
Status = NtEnumerateValueKey(
|
|
hKey,
|
|
index,
|
|
KeyValueFullInformation,
|
|
pv,
|
|
(ULONG)STR_BUFFER_SIZE - 1,
|
|
&resultlen
|
|
);
|
|
index++;
|
|
|
|
//
|
|
// If we cannot hold in a 64k buffer, forget about it.
|
|
//
|
|
if(Status == STATUS_BUFFER_OVERFLOW)
|
|
continue;
|
|
|
|
if(Status == STATUS_NO_MORE_ENTRIES)
|
|
break;
|
|
|
|
//
|
|
// Type must be DWORD and name cannot be longer than MAXSTR/2.
|
|
//
|
|
if(pv->Type != REG_DWORD || pv->NameLength >= MAXSTR/2)
|
|
continue;
|
|
|
|
//
|
|
// Now we get one. Check val, if 0 skip.
|
|
//
|
|
dwVal = *((DWORD*)((LPBYTE)pv + pv->DataOffset));
|
|
if(dwVal == 0)
|
|
continue;
|
|
|
|
wcscpy(szDll, szSysdir);
|
|
wcscat(szDll, L"\\");
|
|
wcsncat(szDll, pv->Name, pv->NameLength/sizeof(WCHAR));
|
|
szDll[wcslen(szSysdir) + pv->NameLength/sizeof(WCHAR) + 1] = L'\0';
|
|
|
|
//
|
|
// Now check to make sure the dll we load is still in the
|
|
// system directory.
|
|
//
|
|
if ( GetFullPathName( szDll, MAX_PATH, szPath, &szTempFileName ) )
|
|
{
|
|
szPath[ wcslen( szSysdir ) ] = 0;
|
|
|
|
if ( _tcschr( &szPath[ wcslen(szSysdir ) + 1 ], TEXT('\\') ) ||
|
|
_tcsicmp( szPath, szSysdir ) )
|
|
{
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ExtensionDLL, (LPCWSTR)NULL);
|
|
_snwprintf(g_lpszBuffer,
|
|
STR_BUFFER_SIZE,
|
|
TEXT("Invalid extension dll: '%s'\n"),
|
|
szDll);
|
|
WriteToLogFileW(hFile, g_lpszBuffer);
|
|
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
|
|
hExtDll = LoadLibraryW(szDll);
|
|
if(hExtDll)
|
|
{
|
|
pnExtproc = (EXTENSIONDLLPROC)GetProcAddress(hExtDll, szProcName);
|
|
if(pnExtproc)
|
|
{
|
|
DWORD len = BUFFER_SIZE / sizeof(WCHAR);
|
|
if((*pnExtproc)(psz, &len))
|
|
{
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ExtensionDLL, (LPCWSTR)NULL);
|
|
psz[BUFFER_SIZE /sizeof(WCHAR)] = L'\0';
|
|
WriteToLogFileW(hFile, (LPCWSTR)psz);
|
|
}
|
|
pnExtproc = NULL;
|
|
}
|
|
FreeLibrary(hExtDll);
|
|
hExtDll = NULL;
|
|
}
|
|
else
|
|
{
|
|
gXMLOutput->Write(XMLTAG_SETDataType_ExtensionDLL, (LPCWSTR)NULL);
|
|
_snwprintf(g_lpszBuffer,
|
|
STR_BUFFER_SIZE,
|
|
TEXT("Load extension dll: '%s' failed\n"),
|
|
szDll);
|
|
WriteToLogFileW(hFile, g_lpszBuffer);
|
|
}
|
|
}
|
|
LocalFree(psz);
|
|
NtClose(hKey);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
BOOL
|
|
SnapshotFindModule(
|
|
IN HANDLE hProcess,
|
|
IN HMODULE hModule,
|
|
OUT PLDR_DATA_TABLE_ENTRY LdrEntryData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the loader table entry for the specified
|
|
module. The function copies the entry into the buffer pointed to
|
|
by the LdrEntryData parameter.
|
|
|
|
Arguments:
|
|
|
|
hProcess - Supplies the target process.
|
|
|
|
hModule - Identifies the module whose loader entry is being
|
|
requested. A value of NULL references the module handle
|
|
associated with the image file that was used to create the
|
|
process.
|
|
|
|
LdrEntryData - Returns the requested table entry.
|
|
|
|
Return Value:
|
|
|
|
TRUE if a matching entry was found.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROCESS_BASIC_INFORMATION BasicInfo;
|
|
NTSTATUS Status;
|
|
PPEB Peb;
|
|
PPEB_LDR_DATA Ldr;
|
|
PLIST_ENTRY LdrHead;
|
|
PLIST_ENTRY LdrNext;
|
|
|
|
Status = NtQueryInformationProcess(
|
|
hProcess,
|
|
ProcessBasicInformation,
|
|
&BasicInfo,
|
|
sizeof(BasicInfo),
|
|
NULL
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
SetLastError( RtlNtStatusToDosError( Status ) );
|
|
return(FALSE);
|
|
}
|
|
|
|
Peb = BasicInfo.PebBaseAddress;
|
|
|
|
|
|
if ( !ARGUMENT_PRESENT( hModule )) {
|
|
if (!ReadProcessMemory(hProcess, &Peb->ImageBaseAddress, &hModule, sizeof(hModule), NULL)) {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Ldr = Peb->Ldr
|
|
//
|
|
|
|
if (!ReadProcessMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL)) {
|
|
return (FALSE);
|
|
}
|
|
|
|
if (!Ldr) {
|
|
// Ldr might be null (for instance, if the process hasn't started yet).
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
LdrHead = &Ldr->InMemoryOrderModuleList;
|
|
|
|
//
|
|
// LdrNext = Head->Flink;
|
|
//
|
|
|
|
if (!ReadProcessMemory(hProcess, &LdrHead->Flink, &LdrNext, sizeof(LdrNext), NULL)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
while (LdrNext != LdrHead) {
|
|
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
|
|
|
LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
|
|
|
if (!ReadProcessMemory(hProcess, LdrEntry, LdrEntryData, sizeof(*LdrEntryData), NULL)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
if ((HMODULE) LdrEntryData->DllBase == hModule) {
|
|
return(TRUE);
|
|
}
|
|
|
|
LdrNext = LdrEntryData->InMemoryOrderLinks.Flink;
|
|
}
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
SnapshotEnumProcessModules(
|
|
HANDLE hProcess,
|
|
HMODULE *lphModule,
|
|
DWORD cb,
|
|
LPDWORD lpcbNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function Enums all of the modules in the given process.
|
|
|
|
Arguments:
|
|
|
|
hProcess - Identifies process for which to enum modules.
|
|
|
|
lphModule - Points to the buffer that is to receive the Module handles.
|
|
|
|
cb - size of the buffer in bytes.
|
|
|
|
lpcbNeeded - if buffer if not enough, give the needed size in bytes.
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROCESS_BASIC_INFORMATION BasicInfo;
|
|
NTSTATUS Status;
|
|
PPEB Peb;
|
|
PPEB_LDR_DATA Ldr;
|
|
PLIST_ENTRY LdrHead;
|
|
PLIST_ENTRY LdrNext;
|
|
DWORD chMax;
|
|
DWORD ch;
|
|
|
|
Status = NtQueryInformationProcess(
|
|
hProcess,
|
|
ProcessBasicInformation,
|
|
&BasicInfo,
|
|
sizeof(BasicInfo),
|
|
NULL
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) )
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( Status ) );
|
|
return(FALSE);
|
|
}
|
|
|
|
Peb = BasicInfo.PebBaseAddress;
|
|
|
|
//
|
|
// Ldr = Peb->Ldr
|
|
//
|
|
|
|
if (!ReadProcessMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
LdrHead = &Ldr->InMemoryOrderModuleList;
|
|
|
|
//
|
|
// LdrNext = Head->Flink;
|
|
//
|
|
|
|
if (!ReadProcessMemory(hProcess, &LdrHead->Flink, &LdrNext, sizeof(LdrNext), NULL))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
chMax = cb / sizeof(HMODULE);
|
|
ch = 0;
|
|
|
|
while (LdrNext != LdrHead)
|
|
{
|
|
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
|
LDR_DATA_TABLE_ENTRY LdrEntryData;
|
|
|
|
LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
|
|
|
if (!ReadProcessMemory(hProcess, LdrEntry, &LdrEntryData, sizeof(LdrEntryData), NULL))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
if (ch < chMax)
|
|
{
|
|
__try
|
|
{
|
|
lphModule[ch] = (HMODULE) LdrEntryData.DllBase;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
ch++;
|
|
|
|
LdrNext = LdrEntryData.InMemoryOrderLinks.Flink;
|
|
}
|
|
|
|
__try
|
|
{
|
|
*lpcbNeeded = ch * sizeof(HMODULE);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
SnapshotGetModuleFileNameExW(
|
|
HANDLE hProcess,
|
|
HMODULE hModule,
|
|
LPWSTR lpFilename,
|
|
DWORD nSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves the full pathname of the executable file
|
|
from which the specified module was loaded. The function copies the
|
|
null-terminated filename into the buffer pointed to by the
|
|
lpFilename parameter.
|
|
|
|
Arguments:
|
|
|
|
hModule - Identifies the module whose executable file name is being
|
|
requested. A value of NULL references the module handle
|
|
associated with the image file that was used to create the
|
|
process.
|
|
|
|
lpFilename - Points to the buffer that is to receive the filename.
|
|
|
|
nSize - Specifies the maximum number of characters to copy. If the
|
|
filename is longer than the maximum number of characters
|
|
specified by the nSize parameter, it is truncated.
|
|
|
|
Return Value:
|
|
|
|
The return value specifies the actual length of the string copied to
|
|
the buffer. A return value of zero indicates an error and extended
|
|
error status is available using the GetLastError function.
|
|
|
|
--*/
|
|
|
|
{
|
|
LDR_DATA_TABLE_ENTRY LdrEntryData;
|
|
DWORD cb;
|
|
|
|
if (!SnapshotFindModule(hProcess, hModule, &LdrEntryData))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
nSize *= sizeof(WCHAR);
|
|
|
|
cb = LdrEntryData.FullDllName.Length + sizeof (WCHAR);
|
|
if ( nSize < cb )
|
|
{
|
|
cb = nSize;
|
|
}
|
|
|
|
if (!ReadProcessMemory(hProcess, LdrEntryData.FullDllName.Buffer, lpFilename, cb, NULL))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
if (cb == LdrEntryData.FullDllName.Length + sizeof (WCHAR))
|
|
{
|
|
cb -= sizeof(WCHAR);
|
|
}
|
|
|
|
return(cb / sizeof(WCHAR));
|
|
}
|
|
|
|
|
|
DWORD
|
|
WINAPI
|
|
SnapshotGetModuleBaseNameW(
|
|
HANDLE hProcess,
|
|
HMODULE hModule,
|
|
LPWSTR lpFilename,
|
|
DWORD nSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retrieves base name of the executable file
|
|
from which the specified module was loaded. The function copies the
|
|
null-terminated filename into the buffer pointed to by the
|
|
lpFilename parameter.
|
|
|
|
Arguments:
|
|
|
|
hModule - Identifies the module whose executable file name is being
|
|
requested. A value of NULL references the module handle
|
|
associated with the image file that was used to create the
|
|
process.
|
|
|
|
lpFilename - Points to the buffer that is to receive the filename.
|
|
|
|
nSize - Specifies the maximum number of characters to copy. If the
|
|
filename is longer than the maximum number of characters
|
|
specified by the nSize parameter, it is truncated.
|
|
|
|
Return Value:
|
|
|
|
The number of WCHARs in lpFilename.
|
|
|
|
--*/
|
|
{
|
|
LDR_DATA_TABLE_ENTRY LdrEntryData;
|
|
DWORD cb;
|
|
|
|
if (!SnapshotFindModule(hProcess, hModule, &LdrEntryData))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
nSize *= sizeof(WCHAR);
|
|
|
|
cb = LdrEntryData.BaseDllName.Length + sizeof (WCHAR);
|
|
if ( nSize < cb )
|
|
{
|
|
cb = nSize;
|
|
}
|
|
|
|
if (!ReadProcessMemory(hProcess, LdrEntryData.BaseDllName.Buffer, lpFilename, cb, NULL))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
if (cb == LdrEntryData.BaseDllName.Length + sizeof (WCHAR))
|
|
{
|
|
cb -= sizeof(WCHAR);
|
|
}
|
|
|
|
return(cb / sizeof(WCHAR));
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
SnapshotGetModuleInformation(
|
|
HANDLE hProcess,
|
|
HMODULE hModule,
|
|
LPMODULEINFO lpmodinfo,
|
|
DWORD cb
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function gets the module information given a module handle and its
|
|
process handle.
|
|
|
|
Arguments:
|
|
|
|
hProcess - Supplies the target process.
|
|
|
|
hModule - Identifies the module whose information will be retrieved.
|
|
|
|
lpmodinfo - Holds module infor on return.
|
|
|
|
cb - size of the buffer in bytes.
|
|
|
|
Return Value:
|
|
|
|
TRUE on success.
|
|
FALSES on failure.
|
|
|
|
--*/
|
|
{
|
|
LDR_DATA_TABLE_ENTRY LdrEntryData;
|
|
MODULEINFO modinfo;
|
|
|
|
if (cb < sizeof(MODULEINFO))
|
|
{
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
return(FALSE);
|
|
}
|
|
|
|
if (!SnapshotFindModule(hProcess, hModule, &LdrEntryData))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
modinfo.lpBaseOfDll = (PVOID) hModule;
|
|
modinfo.SizeOfImage = LdrEntryData.SizeOfImage;
|
|
modinfo.EntryPoint = LdrEntryData.EntryPoint;
|
|
|
|
__try
|
|
{
|
|
*lpmodinfo = modinfo;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
WCHAR g_pszWriteBuffer[ MAX_PATH + 1 ];
|
|
|
|
void
|
|
WriteToLogFileW(
|
|
HANDLE hFile,
|
|
LPCWSTR lpwszInput
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will write a unicode string to the file.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
lpwszInput - the string to write.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwWriten = 0;
|
|
BYTE *bBuffer = NULL;
|
|
BYTE *bConvertBuffer = NULL;
|
|
int nLen, nRetLen;
|
|
|
|
nLen = wcslen(lpwszInput);
|
|
|
|
if ( nLen > (sizeof(g_pszWriteBuffer)/sizeof(WCHAR) - 1) )
|
|
{
|
|
if ( !(bBuffer = (BYTE*)malloc((nLen + 1) * sizeof(WCHAR)) ) )
|
|
return;
|
|
|
|
bConvertBuffer = bBuffer;
|
|
nLen = (nLen + 1) * sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
bConvertBuffer = (BYTE*) g_pszWriteBuffer;
|
|
nLen = sizeof(g_pszWriteBuffer);
|
|
}
|
|
|
|
nRetLen = WideCharToMultiByte(CP_UTF8, 0, lpwszInput, -1, (LPSTR)bConvertBuffer, nLen, NULL, NULL);
|
|
if(nRetLen != 0)
|
|
{
|
|
WriteFile(hFile, (LPVOID)bConvertBuffer, nRetLen-1, &dwWriten, NULL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if WideCharToMultiByte failed, we will double the allocation size
|
|
//
|
|
BYTE *bNewBuffer = NULL;
|
|
|
|
nLen = wcslen(lpwszInput) * sizeof(WCHAR) * 2 + 1;
|
|
|
|
if ( (bNewBuffer = (BYTE*)malloc( nLen ) ) )
|
|
{
|
|
nRetLen = WideCharToMultiByte(CP_UTF8, 0, lpwszInput, -1, (LPSTR)bNewBuffer, nLen, NULL, NULL);
|
|
|
|
if (nRetLen != 0 )
|
|
WriteFile(hFile, (LPVOID)bNewBuffer, nRetLen-1, &dwWriten, NULL);
|
|
|
|
free(bNewBuffer);
|
|
}
|
|
}
|
|
|
|
if ( bBuffer )
|
|
free(bBuffer);
|
|
}
|
|
|
|
void
|
|
WriteToLogFileA(
|
|
HANDLE hFile,
|
|
LPCSTR lpszInput
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will write a ansi string to the file.
|
|
|
|
Arguments:
|
|
|
|
hFile - handle to the log file.
|
|
|
|
lpwszInput - the string to write.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwWriten;
|
|
WriteFile(hFile, (LPVOID)lpszInput, strlen(lpszInput), &dwWriten, NULL);
|
|
}
|
|
|
|
|
|
void
|
|
WriteToLogFile(
|
|
HANDLE hFile,
|
|
LPCTSTR lpszInput
|
|
)
|
|
{
|
|
#ifdef _UNICODE
|
|
WriteToLogFileW(hFile, lpszInput);
|
|
#else
|
|
WriteToLogFileA(hFile, lpszInput);
|
|
#endif //_UNICODE
|
|
}
|
|
|
|
BOOL
|
|
AdjustAccess(
|
|
LPCWSTR lpszDir
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will ajust access to the log file dir.
|
|
We will give System and Admins full rights.
|
|
|
|
Arguments:
|
|
|
|
lpszDir - path to the log files.
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE on failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
PACL pAcl=NULL;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
|
|
DWORD dwSDLen = 0;
|
|
|
|
DWORD cbAcl = 0;
|
|
PSID pSidSystem = NULL;
|
|
PSID pSidAdmin = NULL;
|
|
DWORD dwSidSystemLen = 0;
|
|
DWORD dwSidAdminLen = 0;
|
|
SID_NAME_USE snu;
|
|
|
|
pSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, sizeof(SECURITY_DESCRIPTOR));
|
|
if( NULL == pSecurityDescriptor )
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Initialize the security descriptor.
|
|
//
|
|
if (!InitializeSecurityDescriptor(
|
|
pSecurityDescriptor,
|
|
SECURITY_DESCRIPTOR_REVISION
|
|
))
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
Status = RtlAllocateAndInitializeSid(
|
|
&SidAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&pSidSystem
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastError(RtlNtStatusToDosError(Status));
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
Status = RtlAllocateAndInitializeSid(
|
|
&SidAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pSidAdmin
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastError(RtlNtStatusToDosError(Status));
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
}
|
|
|
|
cbAcl = GetLengthSid(pSidSystem) + GetLengthSid(pSidAdmin) + sizeof(ACL) + (3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
pAcl = (PACL) LocalAlloc( LPTR, cbAcl );
|
|
if( NULL == pAcl )
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Initialize the ACL.
|
|
//
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION))
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
if (!AddAccessAllowedAceEx(pAcl,
|
|
ACL_REVISION,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_ALL,
|
|
pSidSystem
|
|
))
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
if (!AddAccessAllowedAceEx(pAcl,
|
|
ACL_REVISION,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_ALL,
|
|
pSidAdmin
|
|
))
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
if (!SetSecurityDescriptorDacl(pSecurityDescriptor,
|
|
TRUE, pAcl, FALSE))
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
if(!SetFileSecurityW(lpszDir, DACL_SECURITY_INFORMATION, pSecurityDescriptor))
|
|
{
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
CLEANUPANDEXIT:
|
|
if(pAcl != NULL)
|
|
{
|
|
LocalFree(pAcl);
|
|
}
|
|
|
|
if( pSecurityDescriptor != NULL )
|
|
{
|
|
LocalFree( pSecurityDescriptor );
|
|
}
|
|
|
|
if( pSidSystem != NULL )
|
|
{
|
|
FreeSid( pSidSystem );
|
|
}
|
|
|
|
if( pSidAdmin != NULL )
|
|
{
|
|
FreeSid( pSidAdmin );
|
|
}
|
|
|
|
return dwStatus == ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
GetTimeOut(
|
|
void* pv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Thread proc to get timeout from registry.
|
|
|
|
Arguments:
|
|
|
|
pv - thread param.
|
|
|
|
Return Value:
|
|
|
|
0 if success, non-zero if fail.
|
|
|
|
--*/
|
|
{
|
|
LPCWSTR TimeOutVal = L"SnapshotTimeout";
|
|
HANDLE hKey;
|
|
DWORD dwSize;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
Status = SnapshotRegOpenKey(ReliabilityKey, KEY_READ, &hKey);
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( Status ) );
|
|
return GetLastError();
|
|
}
|
|
dwSize = sizeof(DWORD);
|
|
Status = SnapshotRegQueryValueKey(hKey, TimeOutVal, dwSize, pv, &dwSize);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( Status ) );
|
|
NtClose(hKey);
|
|
return GetLastError();
|
|
}
|
|
NtClose(hKey);
|
|
return 0;
|
|
}
|