mirror of https://github.com/lianthony/NT4.0
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.
1149 lines
22 KiB
1149 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mod16.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code for tracking and profiling 16 bit modules.
|
|
|
|
Author:
|
|
|
|
Dave Hastings (daveh) 02-Nov-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "sprofp.h"
|
|
#include "sym16.h"
|
|
|
|
#define PROFILE_BUCKET_16 64
|
|
// bugbug
|
|
extern BOOL Profiling;
|
|
|
|
//
|
|
// Internal Structures
|
|
//
|
|
|
|
typedef struct _ListEntry {
|
|
struct _ListEntry *Flink;
|
|
struct _ListEntry *Blink;
|
|
} LISTENTRY, *PLISTENTRY;
|
|
|
|
typedef struct _Segment16 {
|
|
struct _Segment16 *Flink;
|
|
struct _Segment16 *Blink;
|
|
ULONG Selector;
|
|
ULONG Segment;
|
|
ULONG Type;
|
|
HANDLE ProfileObject;
|
|
PULONG ProfileBuffer;
|
|
ULONG ProfileBufferSize;
|
|
HANDLE Process;
|
|
} SEGMENT16, *PSEGMENT16;
|
|
|
|
typedef struct _Mod16 {
|
|
struct _Mod16 *Flink;
|
|
struct _Mod16 *Blink;
|
|
PUCHAR ModuleName;
|
|
PUCHAR ModuleFileName;
|
|
ULONG BaseSegment;
|
|
ULONG Length;
|
|
BOOL Mode;
|
|
HANDLE Process;
|
|
LISTENTRY Segments;
|
|
} MODULE16, *PMODULE16;
|
|
|
|
typedef struct _Mod16List {
|
|
LISTENTRY Modules;
|
|
HANDLE OutputWindow;
|
|
} MOD16LIST, *PMOD16LIST;
|
|
|
|
PVOID CreateModule16List(
|
|
HANDLE OutputWindow
|
|
)
|
|
{
|
|
return InitMod16(OutputWindow);
|
|
}
|
|
|
|
PVOID
|
|
InitMod16(
|
|
HANDLE DisplayWindow
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes an instance of the 16 bit module tracking code
|
|
|
|
Arguments:
|
|
|
|
DisplayWindow -- Handle of window to display any messages on
|
|
|
|
Return Value:
|
|
|
|
Handle to this module list.
|
|
|
|
--*/
|
|
{
|
|
PMOD16LIST ModuleList;
|
|
|
|
ModuleList = malloc(sizeof(MOD16LIST));
|
|
if (ModuleList) {
|
|
ModuleList->OutputWindow = DisplayWindow;
|
|
ModuleList->Modules.Flink = (PLISTENTRY)&(ModuleList->Modules);
|
|
ModuleList->Modules.Blink = (PLISTENTRY)&(ModuleList->Modules);
|
|
}
|
|
|
|
return ModuleList;
|
|
}
|
|
|
|
PVOID
|
|
Module16Loaded(
|
|
PVOID Instance,
|
|
PUCHAR ModuleName,
|
|
PUCHAR ModuleFileName,
|
|
ULONG StartingSegment,
|
|
ULONG Length,
|
|
BOOL Mode,
|
|
HANDLE Process
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine adds a module description to the loaded modules list.
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the module list
|
|
ModuleName -- Supplies the name of the module
|
|
ModuleFileName -- Supplies the file name and path of the module
|
|
StartingSegement -- Supplies the starting segment number of the module
|
|
Length -- Supplies the length in bytes of the module
|
|
Mode -- Supplies the mode of the module
|
|
|
|
Return Value:
|
|
|
|
Handle to the module description
|
|
|
|
--*/
|
|
{
|
|
PMODULE16 Module, CurrentModule;
|
|
PMOD16LIST ModuleList;
|
|
|
|
if (!Instance) {
|
|
return NULL;
|
|
}
|
|
|
|
ModuleList = Instance;
|
|
|
|
//
|
|
// Allocate a new module description
|
|
//
|
|
|
|
Module = malloc(sizeof(MODULE16));
|
|
if (!Module) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(Module, 0, sizeof(MODULE16));
|
|
|
|
Module->ModuleName = malloc(strlen(ModuleName) + 1);
|
|
Module->ModuleFileName = malloc(strlen(ModuleFileName) + 1);
|
|
|
|
if (!(Module->ModuleName) || !(Module->ModuleFileName)) {
|
|
free(Module);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Fill in the new module description
|
|
//
|
|
|
|
strcpy(Module->ModuleName, ModuleName);
|
|
strcpy(Module->ModuleFileName, ModuleFileName);
|
|
Module->BaseSegment = StartingSegment;
|
|
Module->Length = Length;
|
|
Module->Mode = Mode;
|
|
Module->Segments.Flink = (PLISTENTRY)&(Module->Segments);
|
|
Module->Segments.Blink = (PLISTENTRY)&(Module->Segments);
|
|
Module->Process = Process;
|
|
|
|
//
|
|
// Add to the module list
|
|
//
|
|
|
|
CurrentModule = (PMODULE16)(ModuleList->Modules.Flink);
|
|
|
|
while (CurrentModule->Flink != (PMODULE16)&(ModuleList->Modules)) {
|
|
if (strcmp(CurrentModule->ModuleName, ModuleName) < 0) {
|
|
break;
|
|
}
|
|
CurrentModule = CurrentModule->Flink;
|
|
}
|
|
|
|
Module->Flink = CurrentModule->Flink;
|
|
Module->Blink = CurrentModule;
|
|
CurrentModule->Flink->Blink = Module;
|
|
CurrentModule->Flink = Module;
|
|
|
|
return Module;
|
|
}
|
|
|
|
BOOL
|
|
Module16Unloaded(
|
|
PVOID Instance,
|
|
PUCHAR ModuleName,
|
|
PUCHAR ModuleFileName,
|
|
IN OPTIONAL PVOID ModuleHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine removes a module from the loaded module list. If there are
|
|
multiple instances of a module, they are deleted in fifo order.
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the module list
|
|
ModuleName -- Supplies the name of the module
|
|
ModuleFileName -- Supplies the path and file of the module
|
|
ModuleHandle -- Supplies an optional module handle
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PMODULE16 CurrentModule;
|
|
PMOD16LIST ModuleList;
|
|
PSEGMENT16 Segment;
|
|
|
|
if (!Instance) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Locate module to delete
|
|
//
|
|
if (ModuleHandle) {
|
|
CurrentModule = ModuleHandle;
|
|
//
|
|
// Remove from list
|
|
//
|
|
CurrentModule->Blink->Flink = CurrentModule->Flink;
|
|
CurrentModule->Flink->Blink = CurrentModule->Blink;
|
|
} else {
|
|
//
|
|
// Search the list
|
|
//
|
|
CurrentModule = (PMODULE16)(ModuleList->Modules.Flink);
|
|
|
|
while (CurrentModule->Flink != (PMODULE16)&(ModuleList->Modules)) {
|
|
if (strcmp(CurrentModule->ModuleName, ModuleName) == 0) {
|
|
break;
|
|
}
|
|
CurrentModule = CurrentModule->Flink;
|
|
}
|
|
|
|
if (strcmp(CurrentModule->ModuleName,ModuleName)) {
|
|
//
|
|
// Module not found
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Free the associated memory
|
|
//
|
|
free(CurrentModule->ModuleName);
|
|
free(CurrentModule->ModuleFileName);
|
|
while (EnumerateSegmentModule(CurrentModule, &Segment)) {
|
|
Segment16Unloaded(
|
|
ModuleList,
|
|
Segment->Selector
|
|
);
|
|
}
|
|
free(CurrentModule);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PVOID
|
|
FindModule16(
|
|
PVOID Instance,
|
|
PUCHAR ModuleName,
|
|
PUCHAR ModuleFileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine finds a module in the loaded module list.
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the loaded module list
|
|
ModuleName -- Supplies the module name
|
|
ModuleFileName -- Supplies the module file name
|
|
|
|
Return Value:
|
|
|
|
Pointer to the module description, or NULL
|
|
|
|
--*/
|
|
{
|
|
PMODULE16 Module;
|
|
|
|
Module = NULL;
|
|
while (EnumerateMod16(Instance, &Module)) {
|
|
if (!strcmp(Module->ModuleName, ModuleName)) {
|
|
return Module;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PVOID
|
|
Segment16Loaded(
|
|
PVOID Instance,
|
|
PVOID ModuleHandle,
|
|
ULONG Selector,
|
|
ULONG SegmentNumber,
|
|
ULONG Type
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine adds a selector to the list for the specified module.
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the loaded module list
|
|
ModuleHandle -- Supplies the module to add the selector to.
|
|
Selector -- Supplies the selector number
|
|
Segment -- Supplies the segment the selector maps to
|
|
Data -- TRUE for data FALSE for code
|
|
|
|
Return Value:
|
|
|
|
TRUE if the segment was added
|
|
|
|
--*/
|
|
{
|
|
PMODULE16 Module;
|
|
PSEGMENT16 Segment, CurrentSegment;
|
|
|
|
if (!Module) {
|
|
return NULL;
|
|
}
|
|
|
|
Module = ModuleHandle;
|
|
|
|
//
|
|
// Create a new Segment
|
|
//
|
|
Segment = malloc(sizeof(SEGMENT16));
|
|
if (!Segment) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(Segment, 0, sizeof(SEGMENT16));
|
|
|
|
Segment->Selector = Selector;
|
|
Segment->Segment = SegmentNumber;
|
|
Segment->Type = Type;
|
|
Segment->Process = Module->Process;
|
|
|
|
//
|
|
// Add the segment to the list
|
|
//
|
|
CurrentSegment = (PSEGMENT16)(Module->Segments.Flink);
|
|
|
|
while (CurrentSegment->Flink != (PSEGMENT16)(&Module->Segments)) {
|
|
if (CurrentSegment->Selector <= Selector) {
|
|
break;
|
|
}
|
|
CurrentSegment = CurrentSegment->Flink;
|
|
}
|
|
|
|
Segment->Flink = CurrentSegment->Flink;
|
|
Segment->Blink = CurrentSegment;
|
|
CurrentSegment->Flink->Blink = Segment;
|
|
CurrentSegment->Flink = Segment;
|
|
|
|
return Segment;
|
|
}
|
|
|
|
BOOL
|
|
Segment16Unloaded(
|
|
PVOID Instance,
|
|
ULONG Selector
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes the specified selector from all modules
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the loaded module list
|
|
Selector -- Supplies the selector number
|
|
|
|
Return Value:
|
|
|
|
TRUE if the selector is deleted
|
|
|
|
--*/
|
|
{
|
|
PMODULE16 Module;
|
|
PSEGMENT16 Segment;
|
|
|
|
if (!Instance) {
|
|
return FALSE;
|
|
}
|
|
|
|
Module = NULL;
|
|
|
|
//
|
|
// Find all of the modules with this segment
|
|
//
|
|
while (EnumerateModuleBySegment(Instance, &Module, Selector)) {
|
|
//
|
|
// remove the segment from this module
|
|
//
|
|
Segment = NULL;
|
|
while (EnumerateSegmentModule(Module, &Segment)) {
|
|
if (Segment->Selector = Selector) {
|
|
Segment->Flink->Blink = Segment->Blink;
|
|
Segment->Blink->Flink = Segment->Flink;
|
|
Segment = Segment->Blink;
|
|
free(Segment);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PVOID
|
|
FindSegment16(
|
|
PVOID Module,
|
|
ULONG Selector
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine finds a module in the loaded module list.
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies the module
|
|
Selector -- Supplies the selector to find
|
|
|
|
Return Value:
|
|
|
|
Pointer to the segment description, or NULL
|
|
|
|
--*/
|
|
{
|
|
PSEGMENT16 Segment;
|
|
|
|
Segment = NULL;
|
|
while (EnumerateSegmentModule(Module, &Segment)) {
|
|
if (Segment->Selector == Selector) {
|
|
return Segment;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
BOOL
|
|
EnumerateMod16(
|
|
PVOID Instance,
|
|
PVOID *Enumeration
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enumerates all of the modules in the specified loaded module
|
|
list. To continue the enumeration, pass in the pointer returned from
|
|
the last call. False is returned when the last moudle has been enumerated
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the loaded module list
|
|
Enumeration -- Supplies a pointer to the current module (null for first)
|
|
|
|
Return Value:
|
|
|
|
FALSE if the last module has been enumerated.
|
|
TRUE otherwise
|
|
|
|
--*/
|
|
{
|
|
PMOD16LIST ModuleList;
|
|
PMODULE16 Module;
|
|
|
|
if (!Instance) {
|
|
return FALSE;
|
|
}
|
|
|
|
ModuleList = Instance;
|
|
|
|
if (!(*Enumeration)) {
|
|
Module = (PMODULE16)(ModuleList->Modules.Flink);
|
|
} else {
|
|
Module = *Enumeration;
|
|
if (Module->Flink == (PMODULE16)&(ModuleList->Modules)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (Module == (PMODULE16)&(ModuleList->Modules)) {
|
|
return FALSE;
|
|
} else {
|
|
if ((*Enumeration)) {
|
|
Module = Module->Flink;
|
|
}
|
|
*Enumeration = Module;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
PUCHAR
|
|
GetNameMod16(
|
|
PVOID Module
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns a pointer to the module name for the specified module
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies a pointer to the module
|
|
|
|
Return Value:
|
|
|
|
Pointer to name string, or NULL
|
|
|
|
--*/
|
|
{
|
|
if (Module) {
|
|
return ((PMODULE16)Module)->ModuleName;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
PUCHAR
|
|
GetFileNameMod16(
|
|
PVOID Module
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns a pointer to the module file name for the
|
|
specified module
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies a pointer to the module
|
|
|
|
Return Value:
|
|
|
|
Pointer to file name string, or NULL
|
|
|
|
--*/
|
|
{
|
|
if (Module) {
|
|
return ((PMODULE16)Module)->ModuleFileName;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
GetBaseMod16(
|
|
PVOID Module
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the base segment for the specified module.
|
|
For protected mode, this value will be zero.
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies a pointer to the module
|
|
|
|
Return Value:
|
|
|
|
Base of the module
|
|
|
|
--*/
|
|
{
|
|
if (Module) {
|
|
return ((PMODULE16)Module)->BaseSegment;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
GetSizeMod16(
|
|
PVOID Module
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the size for the specified module.
|
|
For protected mode, this value will be zero.
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies a pointer to the module
|
|
|
|
Return Value:
|
|
|
|
Size of the module
|
|
|
|
--*/
|
|
{
|
|
if (Module) {
|
|
return ((PMODULE16)Module)->Length;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
GetModeMod16(
|
|
PVOID Module
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the mode for the specified module.
|
|
For v86 mode, this value will be zero.
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies a pointer to the module
|
|
|
|
Return Value:
|
|
|
|
Size of the module
|
|
|
|
--*/
|
|
{
|
|
if (Module) {
|
|
return ((PMODULE16)Module)->Mode;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
GetMapSegmentSegment16(
|
|
PVOID Segment
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the map segment for the specified selector
|
|
|
|
Arguments:
|
|
|
|
Segment -- Supplies a pointer to the segment descriptor
|
|
|
|
Return Value:
|
|
|
|
The map segment for the selector
|
|
|
|
--*/
|
|
{
|
|
if (Segment) {
|
|
return ((PSEGMENT16)Segment)->Segment;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
GetSegmentTypeSegment16(
|
|
PVOID Segment
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the segment type for the specified selector
|
|
|
|
Arguments:
|
|
|
|
Segment -- Supplies a pointer to the segment descriptor
|
|
|
|
Return Value:
|
|
|
|
The type for the selector
|
|
|
|
--*/
|
|
{
|
|
if (Segment) {
|
|
return ((PSEGMENT16)Segment)->Type;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
EnumerateModuleBySegment(
|
|
PVOID Instance,
|
|
PVOID *Enumeration,
|
|
ULONG Selector
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enumerates all of the modules that have a specified
|
|
segment in their segment list.
|
|
|
|
Arguments:
|
|
|
|
Instance -- Supplies the loaded module list
|
|
Enumeration -- Supplies a pointer to the current module
|
|
Segment -- Supplies the selector number
|
|
|
|
Return Value:
|
|
|
|
FALSE if last module already found
|
|
TRUE otherwise
|
|
|
|
--*/
|
|
{
|
|
PMODULE16 Module;
|
|
PMOD16LIST ModuleList;
|
|
PSEGMENT16 Segment;
|
|
|
|
if (!Instance) {
|
|
return FALSE;
|
|
}
|
|
|
|
ModuleList = Instance;
|
|
|
|
Module = *Enumeration;
|
|
|
|
while (EnumerateMod16(Instance, &Module)) {
|
|
Segment = NULL;
|
|
while (EnumerateSegmentModule(Module, &Segment)) {
|
|
if (Segment->Selector == Selector) {
|
|
*Enumeration = Module;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
EnumerateSegmentModule(
|
|
PVOID Module,
|
|
PVOID *Enumeration
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enumerates the modue
|
|
|
|
Arguments:
|
|
|
|
Module -- Supplies a handle to the module to enumerate the segments for
|
|
Enumeration -- Supplies a pointer to the last segment found
|
|
|
|
Return Value:
|
|
|
|
FALSE if the last segment has been enumerated
|
|
|
|
--*/
|
|
{
|
|
PSEGMENT16 Segment;
|
|
|
|
if (!(*Enumeration)) {
|
|
Segment = (PSEGMENT16)(((PMODULE16)Module)->Segments.Flink);
|
|
} else {
|
|
Segment = *Enumeration;
|
|
if (Segment->Flink == &(((PMODULE16)Module)->Segments)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (Segment == &(((PMODULE16)Module)->Segments)) {
|
|
return FALSE;
|
|
} else {
|
|
if ((*Enumeration)) {
|
|
Segment = Segment->Flink;
|
|
}
|
|
*Enumeration = Segment;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
StartProfileSegment16(
|
|
PVOID SegmentHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine starts profiling for a segment
|
|
|
|
Arguments:
|
|
|
|
Segment -- Supplies the segment to start profiling for
|
|
|
|
Return Value:
|
|
|
|
True if profiling was successfully started
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PSEGMENT16 Segment;
|
|
QUOTA_LIMITS QuotaLimits;
|
|
UCHAR StringBuffer[256];
|
|
|
|
if (!SegmentHandle) {
|
|
return FALSE;
|
|
}
|
|
|
|
Segment = SegmentHandle;
|
|
|
|
if (Segment->ProfileObject == NULL) {
|
|
// bugbug
|
|
Segment->ProfileBufferSize = 64 * 1024 /
|
|
PROFILE_BUCKET_16 * sizeof(ULONG);
|
|
|
|
Segment->ProfileBuffer = malloc(Segment->ProfileBufferSize);
|
|
|
|
if (!Segment->ProfileBuffer) {
|
|
return FALSE;
|
|
}
|
|
|
|
memset(Segment->ProfileBuffer, 0, Segment->ProfileBufferSize);
|
|
|
|
|
|
Status = NtCreateProfile(
|
|
&(Segment->ProfileObject),
|
|
Segment->Process,
|
|
(PVOID)Segment->Selector,
|
|
64 * 1024, // bugbug
|
|
0,
|
|
Segment->ProfileBuffer,
|
|
Segment->ProfileBufferSize,
|
|
ProfileTime,
|
|
(KAFFINITY)-1);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
sprintf(
|
|
StringBuffer,
|
|
"Failed to create profile object for segment %x, %lx",
|
|
Segment->Selector,
|
|
Status
|
|
);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
StringBuffer,
|
|
"Segmented Profiler",
|
|
MB_OK | MB_ICONSTOP
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
Status = NtStartProfile(Segment->ProfileObject);
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// If the working set is too small, grow it
|
|
//
|
|
if (Status == STATUS_WORKING_SET_QUOTA) {
|
|
Status = NtQueryInformationProcess(
|
|
NtCurrentProcess(),
|
|
// Segment->Process,
|
|
ProcessQuotaLimits,
|
|
&QuotaLimits,
|
|
sizeof(QUOTA_LIMITS),
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
sprintf(
|
|
StringBuffer,
|
|
"Failed to get working set size, %lx",
|
|
Status
|
|
);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
StringBuffer,
|
|
"Segmented Profiler",
|
|
MB_OK | MB_ICONSTOP
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
QuotaLimits.MaximumWorkingSetSize +=
|
|
((Segment->ProfileBufferSize > 64 * 1024) ?
|
|
Segment->ProfileBufferSize : 64 * 1024);
|
|
QuotaLimits.MinimumWorkingSetSize +=
|
|
((Segment->ProfileBufferSize > 64 * 1024) ?
|
|
Segment->ProfileBufferSize : 64 * 1024);
|
|
|
|
Status = NtSetInformationProcess(
|
|
NtCurrentProcess(),
|
|
// Segment->Process,
|
|
ProcessQuotaLimits,
|
|
&QuotaLimits,
|
|
sizeof(QUOTA_LIMITS)
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
sprintf(
|
|
StringBuffer,
|
|
"Failed to set working set size, %lx",
|
|
Status
|
|
);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
StringBuffer,
|
|
"Segmented Profiler",
|
|
MB_OK | MB_ICONSTOP
|
|
);
|
|
|
|
return FALSE;
|
|
} else if (Status == STATUS_WORKING_SET_LIMIT_RANGE) {
|
|
|
|
sprintf(
|
|
StringBuffer,
|
|
"Profile Bucket sizes too large. No more segments will be profiled"
|
|
);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
StringBuffer,
|
|
"Segmented Profiler",
|
|
MB_OK | MB_ICONSTOP
|
|
);
|
|
// bugbug
|
|
Profiling = FALSE;
|
|
}
|
|
|
|
Status = NtStartProfile(Segment->ProfileObject);
|
|
if (!NT_SUCCESS(Status)) {
|
|
sprintf(
|
|
StringBuffer,
|
|
"Failed to start profile object for segemnt %x, %lx",
|
|
Segment->Selector,
|
|
Status
|
|
);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
StringBuffer,
|
|
"Segmented Profiler",
|
|
MB_OK | MB_ICONSTOP
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sprintf(
|
|
StringBuffer,
|
|
"Failed to start profile object for segemnt %x, %lx",
|
|
Segment->Selector,
|
|
Status
|
|
);
|
|
|
|
MessageBox(
|
|
NULL,
|
|
StringBuffer,
|
|
"Segmented Profiler",
|
|
MB_OK | MB_ICONSTOP
|
|
);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
StopProfileSegment16(
|
|
PVOID SegmentHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine stops profiling for the specified segment
|
|
|
|
Arguments:
|
|
|
|
SegmentHandle -- Supplies the segment
|
|
|
|
Return Value:
|
|
|
|
True if profiling stopped
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PSEGMENT16 Segment;
|
|
|
|
if (!SegmentHandle) {
|
|
return FALSE;
|
|
}
|
|
|
|
Segment = SegmentHandle;
|
|
|
|
Status = NtStopProfile(Segment->ProfileObject);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DumpProfileSegment16(
|
|
PVOID SegmentHandle,
|
|
HANDLE OutputFile,
|
|
PUCHAR FileMappingBase
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine dumps the profile information for the specified
|
|
segment.
|
|
|
|
Arguments:
|
|
|
|
SegmentHandle -- Supplies the handle for the segment
|
|
OutputFile -- Supplies the handle for the output file.
|
|
|
|
Return Value:
|
|
|
|
TRUE if profiling dumped
|
|
|
|
--*/
|
|
{
|
|
PSEGMENT16 Segment;
|
|
ULONG SymbolAddress;
|
|
ULONG i;
|
|
UCHAR Buffer[256];
|
|
UCHAR SymbolName[80];
|
|
ULONG BytesWritten;
|
|
BOOL Success;
|
|
|
|
if (SegmentHandle == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
Segment = SegmentHandle;
|
|
|
|
for (i = 0; i < Segment->ProfileBufferSize / sizeof(ULONG); i++) {
|
|
|
|
if (Segment->ProfileBuffer[i] == 0) {
|
|
continue;
|
|
}
|
|
|
|
SymbolName[0] = '\0';
|
|
Success = GetSymbolByAddress(
|
|
Segment->Segment,
|
|
(64 * 1024 / (Segment->ProfileBufferSize / sizeof(ULONG))) * i,
|
|
SymbolName,
|
|
&SymbolAddress,
|
|
NULL,
|
|
NULL,
|
|
FileMappingBase
|
|
);
|
|
|
|
if ((!Success) || (SymbolName[0] == '\0')) {
|
|
sprintf(
|
|
Buffer,
|
|
"%10ld hits at %x:%lx\n",
|
|
Segment->ProfileBuffer[i],
|
|
Segment->Selector,
|
|
(64 * 1024 / (Segment->ProfileBufferSize / sizeof(ULONG))) * i
|
|
);
|
|
} else {
|
|
sprintf(
|
|
Buffer,
|
|
"%10ld hits at %s + %lx\n",
|
|
Segment->ProfileBuffer[i],
|
|
SymbolName,
|
|
(64 * 1024 / (Segment->ProfileBufferSize / sizeof(ULONG))) * i -
|
|
SymbolAddress
|
|
);
|
|
}
|
|
|
|
Success = WriteFile(
|
|
OutputFile,
|
|
Buffer,
|
|
strlen(Buffer),
|
|
&BytesWritten,
|
|
NULL
|
|
);
|
|
|
|
if (!Success || (BytesWritten != strlen(Buffer))) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
NtClose(Segment->ProfileObject);
|
|
free(Segment->ProfileBuffer);
|
|
Segment->ProfileBuffer = NULL;
|
|
Segment->ProfileObject = NULL;
|
|
Segment->ProfileBufferSize = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DestroyModule16List(
|
|
PVOID ModuleList
|
|
)
|
|
{
|
|
// BUGBUG
|
|
return TRUE;
|
|
}
|