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.
2063 lines
43 KiB
2063 lines
43 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pfsvc.h
|
|
|
|
Abstract:
|
|
|
|
This module contains private declarations for the prefetcher
|
|
service responsible for maintaining prefetch scenario files.
|
|
|
|
Author:
|
|
|
|
Stuart Sechrest (stuartse)
|
|
Cenk Ergan (cenke)
|
|
Chuck Leinzmeier (chuckl)
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#ifndef _PFSVC_H_
|
|
#define _PFSVC_H_
|
|
|
|
//
|
|
// This is the version of the prefetcher maintenance service. It does
|
|
// not have to be in sync with the the prefetcher PF_CURRENT_VERSION.
|
|
//
|
|
|
|
#define PFSVC_SERVICE_VERSION 15
|
|
|
|
//
|
|
// This is the maximum number of traces that will be acquired from the
|
|
// kernel and put on the list in the service waiting to be processed.
|
|
//
|
|
|
|
#define PFSVC_MAX_NUM_QUEUED_TRACES 100
|
|
|
|
//
|
|
// If the number of faults in a trace period falls below this, that
|
|
// marks the end of the trace for some scenario types.
|
|
//
|
|
|
|
#define PFSVC_MIN_FAULT_THRESHOLD 10
|
|
|
|
//
|
|
// What the rate of usage for the pages we prefetched should be
|
|
// greater than for us not to increase scenario sensitivity.
|
|
//
|
|
|
|
#define PFSVC_MIN_HIT_PERCENTAGE 90
|
|
|
|
//
|
|
// What the rate of usage for the pages we knew about but ignored
|
|
// should be less than for us not to decrease scenario sensitivity.
|
|
//
|
|
|
|
#define PFSVC_MAX_IGNORED_PERCENTAGE 30
|
|
|
|
//
|
|
// This is the number of launches after which we will set the
|
|
// MinReTraceTime and MinRePrefetchTime's on the scenario's header to
|
|
// limit prefetch activity if a scenario gets launched very
|
|
// frequently. This allows short training scenarios to be run before
|
|
// benchmarking after deleting the prefetch files.
|
|
//
|
|
|
|
#define PFSVC_MIN_LAUNCHES_FOR_LAUNCH_FREQ_CHECK 10
|
|
|
|
//
|
|
// This is the default time in 100ns that has to pass from the last
|
|
// launch of a scenario before we prefetch it again.
|
|
//
|
|
|
|
#define PFSVC_DEFAULT_MIN_REPREFETCH_TIME (1i64 * 120 * 1000 * 1000 * 10)
|
|
|
|
//
|
|
// This is the default time in 100ns that has to pass from the last
|
|
// launch of a scenario before we re-trace it again.
|
|
//
|
|
|
|
#define PFSVC_DEFAULT_MIN_RETRACE_TIME (1i64 * 120 * 1000 * 1000 * 10)
|
|
|
|
//
|
|
// This is the maximum number of prefetch scenario files we'll have in
|
|
// the prefetch directory. Once we reach this amount we won't create
|
|
// new scenario files until we clean up the old ones.
|
|
//
|
|
|
|
#if DBG
|
|
#define PFSVC_MAX_PREFETCH_FILES 12
|
|
#else // DBG
|
|
#define PFSVC_MAX_PREFETCH_FILES 128
|
|
#endif // DBG
|
|
|
|
//
|
|
// Path to the registry key and name of the value that specifies the
|
|
// file the defragger uses to determine optimal layout of files on the
|
|
// disk.
|
|
//
|
|
|
|
#define PFSVC_OPTIMAL_LAYOUT_REG_KEY_PATH \
|
|
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OptimalLayout"
|
|
#define PFSVC_OPTIMAL_LAYOUT_REG_VALUE_NAME \
|
|
L"LayoutFilePath"
|
|
#define PFSVC_OPTIMAL_LAYOUT_FILE_DEFAULT_NAME \
|
|
L"Layout.ini"
|
|
#define PFSVC_OPTIMAL_LAYOUT_ENABLE_VALUE_NAME \
|
|
L"EnableAutoLayout"
|
|
|
|
//
|
|
// Path to the registry key under which we store various service data,
|
|
// e.g. version, last time the defragger was run successfully to
|
|
// update layout etc.
|
|
//
|
|
|
|
#define PFSVC_SERVICE_DATA_KEY \
|
|
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Prefetcher"
|
|
|
|
//
|
|
// These are the value names under PFSVC_SERVICE_DATA_KEY in which we
|
|
// store various prefetcher service data.
|
|
//
|
|
|
|
#define PFSVC_VERSION_VALUE_NAME \
|
|
L"Version"
|
|
|
|
#define PFSVC_START_TIME_VALUE_NAME \
|
|
L"StartTime"
|
|
|
|
#define PFSVC_EXIT_TIME_VALUE_NAME \
|
|
L"ExitTime"
|
|
|
|
#define PFSVC_EXIT_CODE_VALUE_NAME \
|
|
L"ExitCode"
|
|
|
|
#define PFSVC_LAST_DISK_LAYOUT_TIME_STRING_VALUE_NAME \
|
|
L"LastDiskLayoutTimeString"
|
|
|
|
#define PFSVC_TRACES_PROCESSED_VALUE_NAME \
|
|
L"TracesProcessed"
|
|
|
|
#define PFSVC_TRACES_SUCCESSFUL_VALUE_NAME \
|
|
L"TracesSuccessful"
|
|
|
|
#define PFSVC_LAST_TRACE_FAILURE_VALUE_NAME \
|
|
L"LastTraceFailure"
|
|
|
|
#define PFSVC_BOOT_FILES_OPTIMIZED_VALUE_NAME \
|
|
L"BootFilesOptimized"
|
|
|
|
#define PFSVC_MIN_RELAYOUT_HOURS_VALUE_NAME \
|
|
L"MinRelayoutHours"
|
|
|
|
//
|
|
// This is the value name under PFSVC_SERVICE_DATA_KEY in which we
|
|
// store the last time the defragger was run successfully to update
|
|
// layout.
|
|
//
|
|
|
|
#define PFSVC_LAST_DISK_LAYOUT_TIME_VALUE_NAME \
|
|
L"LastDiskLayoutTime"
|
|
|
|
//
|
|
// This is the registry path to the NLS configuration key.
|
|
//
|
|
|
|
#define PFSVC_NLS_REG_KEY_PATH \
|
|
L"SYSTEM\\CurrentControlSet\\Control\\Nls"
|
|
|
|
//
|
|
// This is the name of the named manual-reset event that can be set to
|
|
// override waiting for system to be idle before processing traces.
|
|
//
|
|
|
|
#define PFSVC_OVERRIDE_IDLE_EVENT_NAME L"PrefetchOverrideIdle"
|
|
|
|
//
|
|
// This is the name of the named manual-reset event that will be set
|
|
// when there are no traces left to process.
|
|
//
|
|
|
|
#define PFSVC_PROCESSING_COMPLETE_EVENT_NAME L"PrefetchProcessingComplete"
|
|
|
|
//
|
|
// When we have run the defragger for all drives after a setup / upgrade,
|
|
// we set the build status registry value to this string:
|
|
//
|
|
|
|
#define PFSVC_DEFRAG_DRIVES_DONE L"DefragDone"
|
|
|
|
//
|
|
// Number of 100ns in an hour.
|
|
//
|
|
|
|
#define PFSVC_NUM_100NS_IN_AN_HOUR (1i64 * 60 * 60 * 1000 * 1000 * 10)
|
|
|
|
//
|
|
// This is how many 100ns have to pass since last disk layout for us to do
|
|
// another one, if we are not being explicitly run.
|
|
//
|
|
|
|
#define PFSVC_MIN_TIME_BEFORE_DISK_RELAYOUT (1i64 * 3 * 24 * PFSVC_NUM_100NS_IN_AN_HOUR)
|
|
|
|
//
|
|
// Allocation granularity for trace buffers.
|
|
//
|
|
|
|
#define ROUND_TRACE_BUFFER_SIZE(_required) (((_required) + 16384 - 1) & ~(16384 - 1))
|
|
|
|
//
|
|
// Define useful macros. As with all macros, must be careful of parameter
|
|
// reevalation. Don't use expressions as macro parameters.
|
|
//
|
|
|
|
#define PFSVC_ALLOC(NumBytes) (HeapAlloc(GetProcessHeap(),0,(NumBytes)))
|
|
#define PFSVC_FREE(Buffer) (HeapFree(GetProcessHeap(),0,(Buffer)))
|
|
|
|
//
|
|
// This magic is used to mark free'd memory in chunk allocator.
|
|
//
|
|
|
|
#define PFSVC_CHUNK_ALLOCATOR_FREED_MAGIC 0xFEEDCEED
|
|
|
|
//
|
|
// This magic is used to mark free'd memory in string allocator.
|
|
//
|
|
|
|
#define PFSVC_STRING_ALLOCATOR_FREED_MAGIC 0xFEED
|
|
|
|
//
|
|
// This is the max size for the strings allocated from the string
|
|
// allocator that will be allocated from the preallocated buffer, so we
|
|
// can save the size of the allocation with the header in a USHORT.
|
|
//
|
|
|
|
#define PFSVC_STRING_ALLOCATOR_MAX_BUFFER_ALLOCATION_SIZE 60000
|
|
|
|
//
|
|
// These macros are used to acquire/release a mutex.
|
|
//
|
|
|
|
#define PFSVC_ACQUIRE_LOCK(Lock) \
|
|
DBGPR((PFID,PFLOCK,"PFSVC: AcquireLock-Begin(%s,%d,%s)\n",#Lock,__LINE__,__FILE__));\
|
|
WaitForSingleObject((Lock), INFINITE); \
|
|
DBGPR((PFID,PFLOCK,"PFSVC: AcquireLock-End(%s,%d,%s)\n",#Lock,__LINE__,__FILE__)); \
|
|
|
|
#define PFSVC_RELEASE_LOCK(Lock) \
|
|
ReleaseMutex((Lock)); \
|
|
DBGPR((PFID,PFLOCK,"PFSVC: ReleaseLock(%s,%d,%s)\n",#Lock,__LINE__,__FILE__)); \
|
|
|
|
//
|
|
// Internal type and constant definitions: Entries in the trace and in
|
|
// the existing scenario file are put into these structures for easier
|
|
// manipulation and policy implementation.
|
|
//
|
|
|
|
typedef struct _PFSVC_SECTION_NODE {
|
|
|
|
// ISSUE-2002/03/29-ScottMa -- Anonymous unions are no longer supported by
|
|
// the compiler. They are a non-standard extension (see MSDN -- C4201).
|
|
// There are three such unions/structs below.
|
|
|
|
union {
|
|
|
|
//
|
|
// Link in the scenarios list of section nodes.
|
|
//
|
|
|
|
LIST_ENTRY SectionLink;
|
|
|
|
//
|
|
// These fields are used to sort section nodes by first
|
|
// access.
|
|
//
|
|
|
|
struct {
|
|
struct _PFSVC_SECTION_NODE *LeftChild;
|
|
struct _PFSVC_SECTION_NODE *RightChild;
|
|
};
|
|
};
|
|
|
|
//
|
|
// Filesystem index number for this section is saved here if it is
|
|
// retrieved. If the section node is for the MFT for the volume we
|
|
// save the number of pages to prefetch from it here.
|
|
//
|
|
|
|
union {
|
|
LARGE_INTEGER FileIndexNumber;
|
|
ULONG MFTNumPagesToPrefetch;
|
|
};
|
|
|
|
//
|
|
// This is the section record that we will setup and save in the
|
|
// scenario file.
|
|
//
|
|
|
|
PF_SECTION_RECORD SectionRecord;
|
|
|
|
//
|
|
// File path for this section.
|
|
//
|
|
|
|
WCHAR *FilePath;
|
|
|
|
//
|
|
// List of page nodes belonging to this section.
|
|
//
|
|
|
|
LIST_ENTRY PageList;
|
|
|
|
//
|
|
// This is the index of the section in the new trace file when
|
|
// ordered by first access [i.e. page fault].
|
|
//
|
|
|
|
ULONG NewSectionIndex;
|
|
|
|
//
|
|
// This is the index of the section in the original scenario file.
|
|
//
|
|
|
|
ULONG OrgSectionIndex;
|
|
|
|
//
|
|
// Link in the volume's list of section nodes.
|
|
//
|
|
|
|
LIST_ENTRY SectionVolumeLink;
|
|
|
|
} PFSVC_SECTION_NODE, *PPFSVC_SECTION_NODE;
|
|
|
|
//
|
|
// This structure contains a path and is used with the path list below.
|
|
//
|
|
|
|
typedef struct _PFSVC_PATH {
|
|
|
|
//
|
|
// Link in the path list sorted by insertion order.
|
|
//
|
|
|
|
LIST_ENTRY InOrderLink;
|
|
|
|
//
|
|
// Link in the path list sorted lexically.
|
|
//
|
|
|
|
LIST_ENTRY SortedLink;
|
|
|
|
//
|
|
// Number of characters in the path excluding terminating NUL.
|
|
//
|
|
|
|
ULONG Length;
|
|
|
|
//
|
|
// NUL terminated path.
|
|
//
|
|
|
|
WCHAR Path[1];
|
|
|
|
} PFSVC_PATH, *PPFSVC_PATH;
|
|
|
|
//
|
|
// This structure holds a list paths. You should manipulate the
|
|
// list or walk through paths in it only using the PathList APIs
|
|
// (e.g. GetNextPathInOrder).
|
|
//
|
|
|
|
//
|
|
// Wrapper around path lists.
|
|
//
|
|
|
|
typedef struct _PFSVC_PATH_LIST {
|
|
|
|
//
|
|
// The list of paths sorted by insertion order.
|
|
//
|
|
|
|
LIST_ENTRY InOrderList;
|
|
|
|
//
|
|
// The list of paths sorted lexically.
|
|
//
|
|
|
|
LIST_ENTRY SortedList;
|
|
|
|
//
|
|
// If non NULL, we will make allocations for new entries from it
|
|
// instead of hitting the heap.
|
|
//
|
|
|
|
struct _PFSVC_STRING_ALLOCATOR *Allocator;
|
|
|
|
//
|
|
// Number of paths in the list.
|
|
//
|
|
|
|
ULONG NumPaths;
|
|
|
|
//
|
|
// Total length of the paths in the list excluding NULs.
|
|
//
|
|
|
|
ULONG TotalLength;
|
|
|
|
//
|
|
// Whether list will be case sensitive or not.
|
|
//
|
|
|
|
BOOLEAN CaseSensitive;
|
|
|
|
} PFSVC_PATH_LIST, *PPFSVC_PATH_LIST;
|
|
|
|
//
|
|
// This structure is used to divide sections in a scenario to
|
|
// different disk volumes (i.e. c:, d:) they are on.
|
|
//
|
|
|
|
typedef struct _PFSVC_VOLUME_NODE {
|
|
|
|
//
|
|
// Link in the scenario's list of volume nodes.
|
|
//
|
|
|
|
LIST_ENTRY VolumeLink;
|
|
|
|
//
|
|
// Volume path and length in number of characters excluding NUL.
|
|
//
|
|
|
|
WCHAR *VolumePath;
|
|
ULONG VolumePathLength;
|
|
|
|
//
|
|
// List of sections that are on this volume that will be prefetched.
|
|
//
|
|
|
|
LIST_ENTRY SectionList;
|
|
ULONG NumSections;
|
|
|
|
//
|
|
// This is the total number of sections on this volume, including
|
|
// those that won't be prefetched.
|
|
//
|
|
|
|
ULONG NumAllSections;
|
|
|
|
//
|
|
// List of directories accessed on this volume.
|
|
//
|
|
|
|
PFSVC_PATH_LIST DirectoryList;
|
|
|
|
//
|
|
// Serial Number/Creation time for this volume. This is retrieved
|
|
// either from a new trace or from the existing scenario file
|
|
// (both should match or the scenario file gets discarded.)
|
|
//
|
|
|
|
LARGE_INTEGER CreationTime;
|
|
ULONG SerialNumber;
|
|
|
|
//
|
|
// Pointer to section node for the MFT for this volume (if there is one).
|
|
//
|
|
|
|
PPFSVC_SECTION_NODE MFTSectionNode;
|
|
|
|
} PFSVC_VOLUME_NODE, *PPFSVC_VOLUME_NODE;
|
|
|
|
//
|
|
// Wrapper around page records.
|
|
//
|
|
|
|
typedef struct _PFSVC_PAGE_NODE {
|
|
|
|
//
|
|
// Link in the section node's list of pages.
|
|
//
|
|
|
|
LIST_ENTRY PageLink;
|
|
|
|
//
|
|
// Page record from previous scenario instructions or a new one
|
|
// initialized for a trace log entry.
|
|
//
|
|
|
|
PF_PAGE_RECORD PageRecord;
|
|
|
|
} PFSVC_PAGE_NODE, *PPFSVC_PAGE_NODE;
|
|
|
|
//
|
|
// This structure is used to make a single big allocation and give it away
|
|
// in small chunks to be used as strings. It is very simple and will not reclaim
|
|
// freed memory for future allocs. The whole allocation will be freed in cleanup.
|
|
// There is no synchronization.
|
|
//
|
|
|
|
typedef struct _PFSVC_STRING_ALLOCATOR {
|
|
|
|
//
|
|
// Actual allocation to be divided up and given away in small chunks.
|
|
//
|
|
|
|
PCHAR Buffer;
|
|
|
|
//
|
|
// End of buffer. If FreePointer is equal to beyond this we can't give
|
|
// away more from this buffer.
|
|
//
|
|
|
|
PCHAR BufferEnd;
|
|
|
|
//
|
|
// Pointer to start of free memory in Buffer.
|
|
//
|
|
|
|
PCHAR FreePointer;
|
|
|
|
//
|
|
// Number of times we had to hit the heap because we ran out of space
|
|
// and the current outstanding such allocations.
|
|
//
|
|
|
|
ULONG MaxHeapAllocs;
|
|
ULONG NumHeapAllocs;
|
|
|
|
//
|
|
// Size of the last allocation that was made from the buffer.
|
|
//
|
|
|
|
USHORT LastAllocationSize;
|
|
|
|
//
|
|
// Whether user has passed in Buffer (so we don't free it when
|
|
// cleaning up.
|
|
//
|
|
|
|
ULONG UserSpecifiedBuffer:1;
|
|
|
|
} PFSVC_STRING_ALLOCATOR, *PPFSVC_STRING_ALLOCATOR;
|
|
|
|
//
|
|
// This structure comes before allocations from the string allocator buffer.
|
|
//
|
|
|
|
typedef struct _PFSVC_STRING_ALLOCATION_HEADER {
|
|
|
|
// ISSUE-2002/03/29-ScottMa -- Anonymous unions are no longer supported by
|
|
// the compiler. They are a non-standard extension (see MSDN -- C4201).
|
|
// There are two such unions/structs below.
|
|
|
|
union {
|
|
|
|
//
|
|
// This structure contains the actual fields.
|
|
//
|
|
|
|
struct {
|
|
|
|
//
|
|
// Size of the preceding allocation.
|
|
//
|
|
|
|
USHORT PrecedingAllocationSize;
|
|
|
|
//
|
|
// Size of this allocation.
|
|
//
|
|
|
|
USHORT AllocationSize;
|
|
|
|
};
|
|
|
|
//
|
|
// Require pointer alignment for this structure, so allocations
|
|
// from the string allocator end up pointer aligned.
|
|
//
|
|
|
|
PVOID FieldToRequirePointerAlignment;
|
|
};
|
|
|
|
} PFSVC_STRING_ALLOCATION_HEADER, *PPFSVC_STRING_ALLOCATION_HEADER;
|
|
|
|
//
|
|
// This structure is used to make a single big allocation and give it away
|
|
// to be used as page nodes, sections nodes etc in small chunks. It is very
|
|
// simple and will not reclaim freed small chunks for future allocs. The whole
|
|
// allocation will be freed in cleanup. The chunk size and max allocs to satisfy
|
|
// is fixed at initialization. There is no synchronization.
|
|
//
|
|
|
|
typedef struct _PFSVC_CHUNK_ALLOCATOR {
|
|
|
|
//
|
|
// Actual allocation to be divided up and given away in small chunks.
|
|
//
|
|
|
|
PCHAR Buffer;
|
|
|
|
//
|
|
// End of buffer. If FreePointer is equal to beyond this we can't give
|
|
// away more from this buffer.
|
|
//
|
|
|
|
PCHAR BufferEnd;
|
|
|
|
//
|
|
// Pointer to start of free memory in Buffer.
|
|
//
|
|
|
|
PCHAR FreePointer;
|
|
|
|
//
|
|
// How big each chunk will be in bytes.
|
|
//
|
|
|
|
ULONG ChunkSize;
|
|
|
|
//
|
|
// Number of times we had to hit the heap because we ran out of space
|
|
// and the current outstanding such allocations.
|
|
//
|
|
|
|
ULONG MaxHeapAllocs;
|
|
ULONG NumHeapAllocs;
|
|
|
|
//
|
|
// Whether user has passed in Buffer (so we don't free it when
|
|
// cleaning up.
|
|
//
|
|
|
|
ULONG UserSpecifiedBuffer:1;
|
|
|
|
} PFSVC_CHUNK_ALLOCATOR, *PPFSVC_CHUNK_ALLOCATOR;
|
|
|
|
//
|
|
// Wrapper around a scenario structure.
|
|
//
|
|
|
|
typedef struct _PFSVC_SCENARIO_INFO {
|
|
|
|
//
|
|
// Header information for the scenario instructions in preparation.
|
|
//
|
|
|
|
PF_SCENARIO_HEADER ScenHeader;
|
|
|
|
//
|
|
// Allocators used to make allocations for scenario processing efficient.
|
|
//
|
|
|
|
PVOID OneBigAllocation;
|
|
PFSVC_CHUNK_ALLOCATOR SectionNodeAllocator;
|
|
PFSVC_CHUNK_ALLOCATOR PageNodeAllocator;
|
|
PFSVC_CHUNK_ALLOCATOR VolumeNodeAllocator;
|
|
PFSVC_STRING_ALLOCATOR PathAllocator;
|
|
|
|
//
|
|
// Container for the sections in this scenario.
|
|
//
|
|
|
|
LIST_ENTRY SectionList;
|
|
|
|
//
|
|
// List of disk volumes that the scenario's sections are on. This
|
|
// list is sorted lexically.
|
|
//
|
|
|
|
LIST_ENTRY VolumeList;
|
|
|
|
//
|
|
// Various statistics acquired from the trace information and used
|
|
// in applying prefetch policy.
|
|
//
|
|
|
|
ULONG NewPages;
|
|
ULONG HitPages;
|
|
ULONG MissedOpportunityPages;
|
|
ULONG IgnoredPages;
|
|
ULONG PrefetchedPages;
|
|
|
|
} PFSVC_SCENARIO_INFO, *PPFSVC_SCENARIO_INFO;
|
|
|
|
//
|
|
// This is a priority queue used for sorting section nodes by first
|
|
// access.
|
|
//
|
|
|
|
typedef struct _PFSV_SECTNODE_PRIORITY_QUEUE {
|
|
|
|
//
|
|
// Think of this priority queue as a Head node and a binary sorted
|
|
// tree at the right child of the Head node. The left child of the
|
|
// Head node always stays NULL. If we need to add a new node
|
|
// smaller than Head, the new node becames the new Head. This way
|
|
// we always have binary sorted tree rooted at Head as well.
|
|
//
|
|
|
|
PPFSVC_SECTION_NODE Head;
|
|
|
|
} PFSV_SECTNODE_PRIORITY_QUEUE, *PPFSV_SECTNODE_PRIORITY_QUEUE;
|
|
|
|
//
|
|
// A list of these may be used to convert the prefix of a path from NT
|
|
// to DOS style. [e.g. \Device\HarddiskVolume1 to C:]
|
|
//
|
|
|
|
typedef struct _NTPATH_TRANSLATION_ENTRY {
|
|
|
|
//
|
|
// Link in a list of translation entries.
|
|
//
|
|
|
|
LIST_ENTRY Link;
|
|
|
|
//
|
|
// NT path prefix to convert and its length in number of
|
|
// characters excluding NUL.
|
|
//
|
|
|
|
WCHAR *NtPrefix;
|
|
ULONG NtPrefixLength;
|
|
|
|
//
|
|
// A DOS path prefix that the NT Path translates to. Note that
|
|
// this not the only possible DOS name translation as a volume may
|
|
// be mounted anywhere.
|
|
//
|
|
|
|
WCHAR *DosPrefix;
|
|
ULONG DosPrefixLength;
|
|
|
|
//
|
|
// This is the volume string returned by FindNextVolume.
|
|
//
|
|
|
|
WCHAR *VolumeName;
|
|
ULONG VolumeNameLength;
|
|
|
|
} NTPATH_TRANSLATION_ENTRY, *PNTPATH_TRANSLATION_ENTRY;
|
|
|
|
typedef LIST_ENTRY NTPATH_TRANSLATION_LIST;
|
|
typedef NTPATH_TRANSLATION_LIST *PNTPATH_TRANSLATION_LIST;
|
|
|
|
//
|
|
// Define structure that wraps traces from the kernel.
|
|
//
|
|
|
|
typedef struct _PFSVC_TRACE_BUFFER {
|
|
|
|
//
|
|
// Traces are saved on the list via this link.
|
|
//
|
|
|
|
LIST_ENTRY TracesLink;
|
|
|
|
//
|
|
// The real trace from kernel starts here and extends for traces
|
|
// size.
|
|
//
|
|
|
|
PF_TRACE_HEADER Trace;
|
|
|
|
} PFSVC_TRACE_BUFFER, *PPFSVC_TRACE_BUFFER;
|
|
|
|
//
|
|
// Define the globals structure.
|
|
//
|
|
|
|
typedef struct _PFSVC_GLOBALS {
|
|
|
|
//
|
|
// Prefetch parameters. These won't be initialized when globals are
|
|
// initialized and have to be explicitly acquired from the kernel.
|
|
// Use PrefetchRoot below instead of RootDirPath in this structure.
|
|
//
|
|
|
|
PF_SYSTEM_PREFETCH_PARAMETERS Parameters;
|
|
|
|
//
|
|
// OS Version information.
|
|
//
|
|
|
|
OSVERSIONINFOEXW OsVersion;
|
|
|
|
//
|
|
// An array of path suffices to recognize files we don't want to prefetch
|
|
// for boot. It is UPCASE and sorted lexically going from last character
|
|
// to first.
|
|
//
|
|
|
|
WCHAR **FilesToIgnoreForBoot;
|
|
ULONG NumFilesToIgnoreForBoot;
|
|
ULONG *FileSuffixLengths;
|
|
|
|
//
|
|
// This manual reset event gets set when the prefetcher service is
|
|
// asked to go away.
|
|
//
|
|
|
|
HANDLE TerminateServiceEvent;
|
|
|
|
//
|
|
// This is the list of traces acquired from the kernel that have
|
|
// to be processed, number of them and the lock to protect the
|
|
// list.
|
|
//
|
|
|
|
LIST_ENTRY Traces;
|
|
ULONG NumTraces;
|
|
HANDLE TracesLock;
|
|
|
|
//
|
|
// This auto-clearing event is set when new traces are put on the
|
|
// list.
|
|
//
|
|
|
|
HANDLE NewTracesToProcessEvent;
|
|
|
|
//
|
|
// This auto-clearing event is set when we had max number of
|
|
// queued traces and we process one. It signifies that we should
|
|
// check for any traces we could not pick up because the queue was
|
|
// maxed.
|
|
//
|
|
|
|
HANDLE CheckForMissedTracesEvent;
|
|
|
|
//
|
|
// This named manual-reset event is set to force the prefetcher
|
|
// service to process the traces without waiting for an idle
|
|
// system.
|
|
//
|
|
|
|
HANDLE OverrideIdleProcessingEvent;
|
|
|
|
//
|
|
// This named manual-reset event is set when processing of the
|
|
// currently available traces are done.
|
|
//
|
|
|
|
HANDLE ProcessingCompleteEvent;
|
|
|
|
//
|
|
// This is the path to the directory where prefetch files are
|
|
// kept and the lock to protect it.
|
|
//
|
|
|
|
WCHAR PrefetchRoot[MAX_PATH + 1];
|
|
HANDLE PrefetchRootLock;
|
|
|
|
//
|
|
// Number of prefetch files in the prefetch directory. This is an estimate
|
|
// (i.e. may not be exact) used to make sure the prefetch directory does
|
|
// not grow too big.
|
|
//
|
|
|
|
ULONG NumPrefetchFiles;
|
|
|
|
//
|
|
// This is a registry handle to the data key under which some
|
|
// prefetch service data is stored.
|
|
//
|
|
|
|
HKEY ServiceDataKey;
|
|
|
|
//
|
|
// This is the number of total traces we attempted to process.
|
|
//
|
|
|
|
ULONG NumTracesProcessed;
|
|
|
|
//
|
|
// This is the number of traces processed successfully.
|
|
//
|
|
|
|
ULONG NumTracesSuccessful;
|
|
|
|
//
|
|
// This is the last error code with which we failed processing a
|
|
// trace.
|
|
//
|
|
|
|
DWORD LastTraceFailure;
|
|
|
|
//
|
|
// Did the defragger crash last time we ran it?
|
|
//
|
|
|
|
DWORD DefraggerErrorCode;
|
|
|
|
//
|
|
// Whether we are asked not to run the defragger in the registry.
|
|
//
|
|
|
|
DWORD DontRunDefragger;
|
|
|
|
//
|
|
// Pointer to path where CSC (client side caching) files are stored.
|
|
//
|
|
|
|
WCHAR *CSCRootPath;
|
|
|
|
} PFSVC_GLOBALS, *PPFSVC_GLOBALS;
|
|
|
|
//
|
|
// This describes a worker function called when it is time for an idle
|
|
// task to run.
|
|
//
|
|
|
|
typedef
|
|
DWORD
|
|
(*PFSVC_IDLE_TASK_WORKER_FUNCTION) (
|
|
struct _PFSVC_IDLE_TASK *Task
|
|
);
|
|
|
|
//
|
|
// This structure is used to keep context for a registered idle task.
|
|
//
|
|
|
|
typedef struct _PFSVC_IDLE_TASK {
|
|
|
|
//
|
|
// Parameters filled in by RegisterIdleTask call.
|
|
//
|
|
|
|
HANDLE ItHandle;
|
|
HANDLE StartEvent;
|
|
HANDLE StopEvent;
|
|
|
|
//
|
|
// Handle for the registered wait.
|
|
//
|
|
|
|
HANDLE WaitHandle;
|
|
|
|
//
|
|
// The registered callback function that will be called when the start
|
|
// event is signaled.
|
|
//
|
|
|
|
WAITORTIMERCALLBACK Callback;
|
|
|
|
//
|
|
// If the common callback function is specified, it calls this function
|
|
// to do the actual work.
|
|
//
|
|
|
|
PFSVC_IDLE_TASK_WORKER_FUNCTION DoWorkFunction;
|
|
|
|
//
|
|
// This is a manual reset event that will be set when the wait/callback
|
|
// on the start event is fully unregistered.
|
|
//
|
|
|
|
HANDLE WaitUnregisteredEvent;
|
|
|
|
//
|
|
// This manual reset event gets reset when a callback starts running and
|
|
// gets signaled when the callback stops running. Signaling of this event
|
|
// is not protected so you can't purely rely on it. It is useful as a
|
|
// shortcut.
|
|
//
|
|
|
|
HANDLE CallbackStoppedEvent;
|
|
|
|
//
|
|
// This manual reset event gets signaled when somebody starts unregistering.
|
|
//
|
|
|
|
HANDLE StartedUnregisteringEvent;
|
|
|
|
//
|
|
// This manual reset event gets signaled when somebody completes unregistering.
|
|
//
|
|
|
|
HANDLE CompletedUnregisteringEvent;
|
|
|
|
//
|
|
// The first one to interlocked set this from 0 to an integer is responsible
|
|
// for unregistering the wait & task and cleaning up.
|
|
//
|
|
|
|
LONG Unregistering;
|
|
|
|
//
|
|
// This is interlocked set from 0 to an integer when a callback is running,
|
|
// or when the main thread is unregistering.
|
|
//
|
|
|
|
LONG CallbackRunning;
|
|
|
|
//
|
|
// Whether this task is registered (i.e. and has to be unregistered.)
|
|
//
|
|
|
|
BOOLEAN Registered;
|
|
|
|
//
|
|
// Whether this task has been initialized, used as a sanity check.
|
|
//
|
|
|
|
BOOLEAN Initialized;
|
|
|
|
} PFSVC_IDLE_TASK, *PPFSVC_IDLE_TASK;
|
|
|
|
//
|
|
// Values for the Unregistering field of PFSVC_IDLE_TASK.
|
|
//
|
|
|
|
typedef enum _PFSVC_TASK_UNREGISTERING_VALUES {
|
|
PfSvcNotUnregisteringTask = 0,
|
|
PfSvcUnregisteringTaskFromCallback,
|
|
PfSvcUnregisteringTaskFromMainThread,
|
|
PfSvcUnregisteringTaskMaxValue
|
|
} PFSVC_TASK_UNREGISTERING_VALUES, *PPFSVC_TASK_UNREGISTERING_VALUES;
|
|
|
|
//
|
|
// Values for the CallbackRunning field of PFSVC_IDLE_TASK.
|
|
//
|
|
|
|
typedef enum _PFSVC_TASK_CALLBACKRUNNING_VALUES {
|
|
PfSvcTaskCallbackNotRunning = 0,
|
|
PfSvcTaskCallbackRunning,
|
|
PfSvcTaskCallbackDisabled,
|
|
PfSvcTaskCallbackMaxValue
|
|
} PFSVC_TASK_CALLBACKRUNNING_VALUES, *PPFSVC_TASK_CALLBACKRUNNING_VALUES;
|
|
|
|
|
|
//
|
|
// Information on a scenario file's age, number of launches etc. used in
|
|
// discarding old scenario files in the prefetch directory.
|
|
//
|
|
|
|
typedef struct _PFSVC_SCENARIO_AGE_INFO {
|
|
|
|
//
|
|
// Weight calculated based on the launch information. Larger weight is
|
|
// better. We'd rather discard scenario with smaller weight.
|
|
//
|
|
|
|
ULONG Weight;
|
|
|
|
//
|
|
// Scenario file path.
|
|
//
|
|
|
|
WCHAR *FilePath;
|
|
|
|
} PFSVC_SCENARIO_AGE_INFO, *PPFSVC_SCENARIO_AGE_INFO;
|
|
|
|
//
|
|
// This structure is used to enumerate through the scenario files
|
|
// in the prefetch directory. None of the fields of this function
|
|
// should be modified outside the file cursor routines.
|
|
//
|
|
|
|
typedef struct _PFSVC_SCENARIO_FILE_CURSOR {
|
|
|
|
//
|
|
// Data returned from FindFile calls for the current prefetch file.
|
|
//
|
|
|
|
WIN32_FIND_DATA FileData;
|
|
|
|
//
|
|
// The current prefetch file's full path.
|
|
//
|
|
|
|
WCHAR *FilePath;
|
|
|
|
//
|
|
// File name & path length in number of characters excluding NUL.
|
|
//
|
|
|
|
ULONG FileNameLength;
|
|
ULONG FilePathLength;
|
|
|
|
//
|
|
// Index of the current file.
|
|
//
|
|
|
|
ULONG CurrentFileIdx;
|
|
|
|
//
|
|
// The fields below are used privately by the scenario file cursor
|
|
// functions.
|
|
//
|
|
|
|
//
|
|
// FindFile handle.
|
|
//
|
|
|
|
HANDLE FindFileHandle;
|
|
|
|
//
|
|
// Where we are looking for prefetch files.
|
|
//
|
|
|
|
WCHAR *PrefetchRoot;
|
|
ULONG PrefetchRootLength;
|
|
|
|
//
|
|
// This is the maximum length string the allocated FilePath can store.
|
|
//
|
|
|
|
ULONG FilePathMaxLength;
|
|
|
|
//
|
|
// This is where the file name starts in the file path. The base of
|
|
// the file path does not change (i.e. PrefetchRoot) and we copy
|
|
// the new enumerated file name starting at FilePath+FileNameStart.
|
|
//
|
|
|
|
ULONG FileNameStart;
|
|
|
|
} PFSVC_SCENARIO_FILE_CURSOR, *PPFSVC_SCENARIO_FILE_CURSOR;
|
|
|
|
//
|
|
// Return values from CompareSuffix.
|
|
//
|
|
|
|
typedef enum _PFSV_SUFFIX_COMPARISON_RESULT {
|
|
PfSvSuffixIdentical,
|
|
PfSvSuffixLongerThan,
|
|
PfSvSuffixLessThan,
|
|
PfSvSuffixGreaterThan
|
|
} PFSV_SUFFIX_COMPARISON_RESULT, *PPFSV_SUFFIX_COMPARISON_RESULT;
|
|
|
|
//
|
|
// Return values from ComparePrefix.
|
|
//
|
|
|
|
typedef enum _PFSV_PREFIX_COMPARISON_RESULT {
|
|
PfSvPrefixIdentical,
|
|
PfSvPrefixLongerThan,
|
|
PfSvPrefixLessThan,
|
|
PfSvPrefixGreaterThan
|
|
} PFSV_PREFIX_COMPARISON_RESULT, *PPFSV_PREFIX_COMPARISON_RESULT;
|
|
|
|
//
|
|
// Return values from SectionNodeComparisonRoutine.
|
|
//
|
|
|
|
typedef enum _PFSV_SECTION_NODE_COMPARISON_RESULT {
|
|
PfSvSectNode1LessThanSectNode2 = -1,
|
|
PfSvSectNode1EqualToSectNode2 = 0,
|
|
PfSvSectNode1GreaterThanSectNode2 = 1,
|
|
} PFSV_SECTION_NODE_COMPARISON_RESULT, *PPFSV_SECTION_NODE_COMPARISON_RESULT;
|
|
|
|
//
|
|
// Local function prototypes:
|
|
//
|
|
|
|
//
|
|
// Exposed routines:
|
|
//
|
|
|
|
DWORD
|
|
WINAPI
|
|
PfSvcMainThread(
|
|
VOID *Param
|
|
);
|
|
|
|
|
|
//
|
|
// Internal service routines:
|
|
//
|
|
|
|
//
|
|
// Thread routines:
|
|
//
|
|
|
|
DWORD
|
|
WINAPI
|
|
PfSvProcessTraceThread(
|
|
VOID *Param
|
|
);
|
|
|
|
DWORD
|
|
WINAPI
|
|
PfSvPollShellReadyWorker(
|
|
VOID *Param
|
|
);
|
|
|
|
//
|
|
// Routines called by the main prefetcher thread.
|
|
//
|
|
|
|
DWORD
|
|
PfSvGetRawTraces(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
PfSvInitializeGlobals(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
PfSvCleanupGlobals(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetCSCRootPath (
|
|
WCHAR *CSCRootPath,
|
|
ULONG CSCRootPathMaxChars
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetDontRunDefragger(
|
|
DWORD *DontRunDefragger
|
|
);
|
|
|
|
DWORD
|
|
PfSvSetPrefetchParameters(
|
|
PPF_SYSTEM_PREFETCH_PARAMETERS Parameters
|
|
);
|
|
|
|
DWORD
|
|
PfSvQueryPrefetchParameters(
|
|
PPF_SYSTEM_PREFETCH_PARAMETERS Parameters
|
|
);
|
|
|
|
DWORD
|
|
PfSvInitializePrefetchDirectory(
|
|
WCHAR *PathFromSystemRoot
|
|
);
|
|
|
|
DWORD
|
|
PfSvCountFilesInDirectory(
|
|
WCHAR *DirectoryPath,
|
|
WCHAR *MatchExpression,
|
|
PULONG NumFiles
|
|
);
|
|
|
|
//
|
|
// Routines to process acquired traces:
|
|
//
|
|
|
|
DWORD
|
|
PfSvProcessTrace(
|
|
PPF_TRACE_HEADER Trace
|
|
);
|
|
|
|
VOID
|
|
PfSvInitializeScenarioInfo (
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPF_SCENARIO_ID ScenarioId,
|
|
PF_SCENARIO_TYPE ScenarioType
|
|
);
|
|
|
|
VOID
|
|
PfSvCleanupScenarioInfo(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo
|
|
);
|
|
|
|
DWORD
|
|
PfSvScenarioOpen (
|
|
IN PWCHAR FilePath,
|
|
IN PPF_SCENARIO_ID ScenarioId,
|
|
IN PF_SCENARIO_TYPE ScenarioType,
|
|
OUT PPF_SCENARIO_HEADER *Scenario
|
|
);
|
|
|
|
DWORD
|
|
PfSvScenarioGetFilePath(
|
|
OUT PWCHAR FilePath,
|
|
IN ULONG FilePathMaxChars,
|
|
IN PPF_SCENARIO_ID ScenarioId
|
|
);
|
|
|
|
DWORD
|
|
PfSvScenarioInfoPreallocate(
|
|
IN PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
OPTIONAL IN PPF_SCENARIO_HEADER Scenario,
|
|
IN PPF_TRACE_HEADER Trace
|
|
);
|
|
|
|
DWORD
|
|
PfSvAddExistingScenarioInfo(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPF_SCENARIO_HEADER Scenario
|
|
);
|
|
|
|
DWORD
|
|
PfSvVerifyVolumeMagics(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPF_TRACE_HEADER Trace
|
|
);
|
|
|
|
DWORD
|
|
PfSvAddTraceInfo(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPF_TRACE_HEADER Trace
|
|
);
|
|
|
|
PPFSVC_SECTION_NODE
|
|
PfSvGetSectionRecord(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
WCHAR *FilePath,
|
|
ULONG FilePathLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvAddFaultInfoToSection(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPF_LOG_ENTRY LogEntry,
|
|
PPFSVC_SECTION_NODE SectionNode
|
|
);
|
|
|
|
DWORD
|
|
PfSvApplyPrefetchPolicy(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo
|
|
);
|
|
|
|
ULONG
|
|
PfSvGetNumTimesUsed(
|
|
ULONG UsageHistory,
|
|
ULONG UsageHistorySize
|
|
);
|
|
|
|
ULONG
|
|
PfSvGetTraceEndIdx(
|
|
PPF_TRACE_HEADER Trace
|
|
);
|
|
|
|
//
|
|
// Routines to write updated scenario instructions to the scenario
|
|
// file.
|
|
//
|
|
|
|
DWORD
|
|
PfSvWriteScenario(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PWCHAR ScenarioFilePath
|
|
);
|
|
|
|
DWORD
|
|
PfSvPrepareScenarioDump(
|
|
IN PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
OUT PPF_SCENARIO_HEADER *ScenarioPtr
|
|
);
|
|
|
|
//
|
|
// Routines to maintain the optimal disk layout file and update disk
|
|
// layout.
|
|
//
|
|
|
|
DWORD
|
|
PfSvUpdateOptimalLayout(
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
DWORD
|
|
PfSvUpdateLayout (
|
|
PPFSVC_PATH_LIST CurrentLayout,
|
|
PPFSVC_PATH_LIST OptimalLayout,
|
|
PBOOLEAN LayoutChanged
|
|
);
|
|
|
|
DWORD
|
|
PfSvDetermineOptimalLayout (
|
|
PPFSVC_IDLE_TASK Task,
|
|
PPFSVC_PATH_LIST OptimalLayout,
|
|
BOOL *BootScenarioProcessed
|
|
);
|
|
|
|
DWORD
|
|
PfSvUpdateLayoutForScenario (
|
|
PPFSVC_PATH_LIST OptimalLayout,
|
|
WCHAR *ScenarioFilePath,
|
|
PNTPATH_TRANSLATION_LIST TranslationList,
|
|
PWCHAR *DosPathBuffer,
|
|
PULONG DosPathBufferSize
|
|
);
|
|
|
|
DWORD
|
|
PfSvReadLayout(
|
|
IN WCHAR *FilePath,
|
|
OUT PPFSVC_PATH_LIST Layout,
|
|
OUT FILETIME *LastWriteTime
|
|
);
|
|
|
|
DWORD
|
|
PfSvSaveLayout(
|
|
IN WCHAR *FilePath,
|
|
IN PPFSVC_PATH_LIST Layout,
|
|
OUT FILETIME *LastWriteTime
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetLayoutFilePath(
|
|
PWCHAR *FilePathBuffer,
|
|
PULONG FilePathBufferSize
|
|
);
|
|
|
|
//
|
|
// Routines to defrag the disks once after setup when the system is idle.
|
|
//
|
|
|
|
DWORD
|
|
PfSvDefragDisks(
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
DWORD
|
|
PfSvLaunchDefragger(
|
|
PPFSVC_IDLE_TASK Task,
|
|
BOOLEAN ForLayoutOptimization,
|
|
PWCHAR TargetDrive
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetBuildDefragStatusValueName (
|
|
OSVERSIONINFOEXW *OsVersion,
|
|
PWCHAR *ValueName
|
|
);
|
|
|
|
DWORD
|
|
PfSvSetBuildDefragStatus(
|
|
OSVERSIONINFOEXW *OsVersion,
|
|
PWCHAR BuildDefragStatus,
|
|
ULONG Size
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetBuildDefragStatus(
|
|
OSVERSIONINFOEXW *OsVersion,
|
|
PWCHAR *BuildDefragStatus,
|
|
PULONG ReturnSize
|
|
);
|
|
|
|
//
|
|
// Routines to cleanup old scenario files in the prefetch directory.
|
|
//
|
|
|
|
DWORD
|
|
PfSvCleanupPrefetchDirectory(
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
int
|
|
__cdecl
|
|
PfSvCompareScenarioAgeInfo(
|
|
const void *Param1,
|
|
const void *Param2
|
|
);
|
|
|
|
//
|
|
// Routines to enumerate scenario files.
|
|
//
|
|
|
|
VOID
|
|
PfSvInitializeScenarioFileCursor (
|
|
PPFSVC_SCENARIO_FILE_CURSOR FileCursor
|
|
);
|
|
|
|
VOID
|
|
PfSvCleanupScenarioFileCursor(
|
|
PPFSVC_SCENARIO_FILE_CURSOR FileCursor
|
|
);
|
|
|
|
DWORD
|
|
PfSvStartScenarioFileCursor(
|
|
PPFSVC_SCENARIO_FILE_CURSOR FileCursor,
|
|
WCHAR *PrefetchRoot
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetNextScenarioFileInfo(
|
|
PPFSVC_SCENARIO_FILE_CURSOR FileCursor
|
|
);
|
|
|
|
//
|
|
// File I/O utility routines.
|
|
//
|
|
|
|
DWORD
|
|
PfSvGetViewOfFile(
|
|
IN WCHAR *FilePath,
|
|
OUT PVOID *BasePointer,
|
|
OUT PULONG FileSize
|
|
);
|
|
|
|
DWORD
|
|
PfSvWriteBuffer(
|
|
PWCHAR FilePath,
|
|
PVOID Buffer,
|
|
ULONG Length
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetLastWriteTime (
|
|
WCHAR *FilePath,
|
|
PFILETIME LastWriteTime
|
|
);
|
|
|
|
DWORD
|
|
PfSvReadLine (
|
|
FILE *File,
|
|
WCHAR **LineBuffer,
|
|
ULONG *LineBufferMaxChars,
|
|
ULONG *LineLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetFileBasicInformation (
|
|
WCHAR *FilePath,
|
|
PFILE_BASIC_INFORMATION FileInformation
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetFileIndexNumber(
|
|
WCHAR *FilePath,
|
|
PLARGE_INTEGER FileIndexNumber
|
|
);
|
|
|
|
//
|
|
// String utility routines.
|
|
//
|
|
|
|
PFSV_SUFFIX_COMPARISON_RESULT
|
|
PfSvCompareSuffix(
|
|
WCHAR *String,
|
|
ULONG StringLength,
|
|
WCHAR *Suffix,
|
|
ULONG SuffixLength,
|
|
BOOLEAN CaseSensitive
|
|
);
|
|
|
|
PFSV_PREFIX_COMPARISON_RESULT
|
|
PfSvComparePrefix(
|
|
WCHAR *String,
|
|
ULONG StringLength,
|
|
WCHAR *Prefix,
|
|
ULONG PrefixLength,
|
|
BOOLEAN CaseSensitive
|
|
);
|
|
|
|
VOID
|
|
FASTCALL
|
|
PfSvRemoveEndOfLineChars (
|
|
WCHAR *Line,
|
|
ULONG *LineLength
|
|
);
|
|
|
|
PWCHAR
|
|
PfSvcAnsiToUnicode(
|
|
PCHAR str
|
|
);
|
|
|
|
PCHAR
|
|
PfSvcUnicodeToAnsi(
|
|
PWCHAR wstr
|
|
);
|
|
|
|
VOID
|
|
PfSvcFreeString(
|
|
PVOID String
|
|
);
|
|
|
|
//
|
|
// Routines that deal with information in the registry.
|
|
//
|
|
|
|
DWORD
|
|
PfSvSaveStartInfo (
|
|
HKEY ServiceDataKey
|
|
);
|
|
|
|
DWORD
|
|
PfSvSaveExitInfo (
|
|
HKEY ServiceDataKey,
|
|
DWORD ExitCode
|
|
);
|
|
|
|
DWORD
|
|
PfSvSaveTraceProcessingStatistics (
|
|
HKEY ServiceDataKey
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetLastDiskLayoutTime(
|
|
FILETIME *LastDiskLayoutTime
|
|
);
|
|
|
|
DWORD
|
|
PfSvSetLastDiskLayoutTime(
|
|
FILETIME *LastDiskLayoutTime
|
|
);
|
|
|
|
BOOLEAN
|
|
PfSvAllowedToRunDefragger(
|
|
BOOLEAN CheckRegistry
|
|
);
|
|
|
|
//
|
|
// Routines that deal with security.
|
|
//
|
|
|
|
BOOL
|
|
PfSvSetPrivilege(
|
|
HANDLE hToken,
|
|
LPCTSTR lpszPrivilege,
|
|
ULONG ulPrivilege,
|
|
BOOL bEnablePrivilege
|
|
);
|
|
|
|
DWORD
|
|
PfSvSetAdminOnlyPermissions(
|
|
WCHAR *ObjectPath,
|
|
HANDLE ObjectHandle,
|
|
SE_OBJECT_TYPE ObjectType
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetPrefetchServiceThreadPrivileges (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Routines that deal with volume node structures.
|
|
//
|
|
|
|
DWORD
|
|
PfSvCreateVolumeNode (
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
WCHAR *VolumePath,
|
|
ULONG VolumePathLength,
|
|
PLARGE_INTEGER CreationTime,
|
|
ULONG SerialNumber
|
|
);
|
|
|
|
PPFSVC_VOLUME_NODE
|
|
PfSvGetVolumeNode (
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
WCHAR *FilePath,
|
|
ULONG FilePathLength
|
|
);
|
|
|
|
VOID
|
|
PfSvCleanupVolumeNode(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPFSVC_VOLUME_NODE VolumeNode
|
|
);
|
|
|
|
DWORD
|
|
PfSvAddParentDirectoriesToList(
|
|
PPFSVC_PATH_LIST DirectoryList,
|
|
ULONG VolumePathLength,
|
|
WCHAR *FilePath,
|
|
ULONG FilePathLength
|
|
);
|
|
|
|
//
|
|
// Routines used to allocate / free section & page nodes etc. efficiently.
|
|
//
|
|
|
|
VOID
|
|
PfSvChunkAllocatorInitialize (
|
|
PPFSVC_CHUNK_ALLOCATOR Allocator
|
|
);
|
|
|
|
DWORD
|
|
PfSvChunkAllocatorStart (
|
|
PPFSVC_CHUNK_ALLOCATOR Allocator,
|
|
PVOID Buffer,
|
|
ULONG ChunkSize,
|
|
ULONG MaxChunks
|
|
);
|
|
|
|
PVOID
|
|
PfSvChunkAllocatorAllocate (
|
|
PPFSVC_CHUNK_ALLOCATOR Allocator
|
|
);
|
|
|
|
VOID
|
|
PfSvChunkAllocatorFree (
|
|
PPFSVC_CHUNK_ALLOCATOR Allocator,
|
|
PVOID Allocation
|
|
);
|
|
|
|
VOID
|
|
PfSvChunkAllocatorCleanup (
|
|
PPFSVC_CHUNK_ALLOCATOR Allocator
|
|
);
|
|
|
|
//
|
|
// Routines used to allocate / free file / directory / volume paths fast.
|
|
//
|
|
|
|
VOID
|
|
PfSvStringAllocatorInitialize (
|
|
PPFSVC_STRING_ALLOCATOR Allocator
|
|
);
|
|
|
|
DWORD
|
|
PfSvStringAllocatorStart (
|
|
PPFSVC_STRING_ALLOCATOR Allocator,
|
|
PVOID Buffer,
|
|
ULONG MaxSize
|
|
);
|
|
|
|
PVOID
|
|
PfSvStringAllocatorAllocate (
|
|
PPFSVC_STRING_ALLOCATOR Allocator,
|
|
ULONG NumBytes
|
|
);
|
|
|
|
VOID
|
|
PfSvStringAllocatorFree (
|
|
PPFSVC_STRING_ALLOCATOR Allocator,
|
|
PVOID Allocation
|
|
);
|
|
|
|
VOID
|
|
PfSvStringAllocatorCleanup (
|
|
PPFSVC_STRING_ALLOCATOR Allocator
|
|
);
|
|
|
|
//
|
|
// Routines that deal with section node structures.
|
|
//
|
|
|
|
VOID
|
|
PfSvCleanupSectionNode(
|
|
PPFSVC_SCENARIO_INFO ScenarioInfo,
|
|
PPFSVC_SECTION_NODE SectionNode
|
|
);
|
|
|
|
//
|
|
// Routines used to sort scenario's section nodes.
|
|
//
|
|
|
|
DWORD
|
|
PfSvSortSectionNodesByFirstAccess(
|
|
PLIST_ENTRY SectionNodeList
|
|
);
|
|
|
|
PFSV_SECTION_NODE_COMPARISON_RESULT
|
|
FASTCALL
|
|
PfSvSectionNodeComparisonRoutine(
|
|
PPFSVC_SECTION_NODE Element1,
|
|
PPFSVC_SECTION_NODE Element2
|
|
);
|
|
|
|
//
|
|
// Routines that implement a priority queue used to sort section nodes
|
|
// for a scenario.
|
|
//
|
|
|
|
VOID
|
|
PfSvInitializeSectNodePriorityQueue(
|
|
PPFSV_SECTNODE_PRIORITY_QUEUE PriorityQueue
|
|
);
|
|
|
|
VOID
|
|
PfSvInsertSectNodePriorityQueue(
|
|
PPFSV_SECTNODE_PRIORITY_QUEUE PriorityQueue,
|
|
PPFSVC_SECTION_NODE NewElement
|
|
);
|
|
|
|
PPFSVC_SECTION_NODE
|
|
PfSvRemoveMinSectNodePriorityQueue(
|
|
PPFSV_SECTNODE_PRIORITY_QUEUE PriorityQueue
|
|
);
|
|
|
|
//
|
|
// Implementation of the Nt path to Dos path translation API.
|
|
//
|
|
|
|
DWORD
|
|
PfSvBuildNtPathTranslationList(
|
|
PNTPATH_TRANSLATION_LIST *NtPathTranslationList
|
|
);
|
|
|
|
VOID
|
|
PfSvFreeNtPathTranslationList(
|
|
PNTPATH_TRANSLATION_LIST TranslationList
|
|
);
|
|
|
|
DWORD
|
|
PfSvTranslateNtPath(
|
|
PNTPATH_TRANSLATION_LIST TranslationList,
|
|
WCHAR *NtPath,
|
|
ULONG NtPathLength,
|
|
PWCHAR *DosPathBuffer,
|
|
PULONG DosPathBufferSize
|
|
);
|
|
|
|
//
|
|
// Path list API.
|
|
//
|
|
|
|
VOID
|
|
PfSvInitializePathList(
|
|
PPFSVC_PATH_LIST PathList,
|
|
PPFSVC_STRING_ALLOCATOR PathAllocator,
|
|
BOOLEAN CaseSensitive
|
|
);
|
|
|
|
VOID
|
|
PfSvCleanupPathList(
|
|
PPFSVC_PATH_LIST PathList
|
|
);
|
|
|
|
BOOLEAN
|
|
PfSvIsInPathList(
|
|
PPFSVC_PATH_LIST PathList,
|
|
WCHAR *Path,
|
|
ULONG PathLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvAddToPathList(
|
|
PPFSVC_PATH_LIST PathList,
|
|
WCHAR *Path,
|
|
ULONG PathLength
|
|
);
|
|
|
|
PPFSVC_PATH
|
|
PfSvGetNextPathSorted (
|
|
PPFSVC_PATH_LIST PathList,
|
|
PPFSVC_PATH CurrentPath
|
|
);
|
|
|
|
PPFSVC_PATH
|
|
PfSvGetNextPathInOrder (
|
|
PPFSVC_PATH_LIST PathList,
|
|
PPFSVC_PATH CurrentPath
|
|
);
|
|
|
|
//
|
|
// Routines to build the list of files accessed by the boot loader.
|
|
//
|
|
|
|
DWORD
|
|
PfSvBuildBootLoaderFilesList (
|
|
PPFSVC_PATH_LIST PathList
|
|
);
|
|
|
|
ULONG
|
|
PfVerifyImageImportTable (
|
|
IN PVOID BaseAddress,
|
|
IN ULONG MappingSize,
|
|
IN BOOLEAN MappedAsImage
|
|
);
|
|
|
|
DWORD
|
|
PfSvAddBootImageAndImportsToList(
|
|
PPFSVC_PATH_LIST PathList,
|
|
WCHAR *FilePath,
|
|
ULONG FilePathLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvLocateBootServiceFile(
|
|
IN WCHAR *FileName,
|
|
IN ULONG FileNameLength,
|
|
OUT WCHAR *FullPathBuffer,
|
|
IN ULONG FullPathBufferLength,
|
|
OUT PULONG RequiredLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetBootServiceFullPath(
|
|
IN WCHAR *ServiceName,
|
|
IN WCHAR *BinaryPathName,
|
|
OUT WCHAR *FullPathBuffer,
|
|
IN ULONG FullPathBufferLength,
|
|
OUT PULONG RequiredLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvGetBootLoaderNlsFileNames (
|
|
PPFSVC_PATH_LIST PathList
|
|
);
|
|
|
|
DWORD
|
|
PfSvLocateNlsFile(
|
|
WCHAR *FileName,
|
|
WCHAR *FilePathBuffer,
|
|
ULONG FilePathBufferLength,
|
|
ULONG *RequiredLength
|
|
);
|
|
|
|
DWORD
|
|
PfSvQueryNlsFileName (
|
|
HKEY Key,
|
|
WCHAR *ValueName,
|
|
WCHAR *FileNameBuffer,
|
|
ULONG FileNameBufferSize,
|
|
ULONG *RequiredSize
|
|
);
|
|
|
|
//
|
|
// Routines to manage / run idle tasks.
|
|
//
|
|
|
|
VOID
|
|
PfSvInitializeTask (
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
DWORD
|
|
PfSvRegisterTask (
|
|
PPFSVC_IDLE_TASK Task,
|
|
IT_IDLE_TASK_ID TaskId,
|
|
WAITORTIMERCALLBACK Callback,
|
|
PFSVC_IDLE_TASK_WORKER_FUNCTION DoWorkFunction
|
|
);
|
|
|
|
DWORD
|
|
PfSvUnregisterTask (
|
|
PPFSVC_IDLE_TASK Task,
|
|
BOOLEAN CalledFromCallback
|
|
);
|
|
|
|
VOID
|
|
PfSvCleanupTask (
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
BOOL
|
|
PfSvStartTaskCallback(
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
VOID
|
|
PfSvStopTaskCallback(
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
VOID
|
|
CALLBACK
|
|
PfSvCommonTaskCallback(
|
|
PVOID lpParameter,
|
|
BOOLEAN TimerOrWaitFired
|
|
);
|
|
|
|
DWORD
|
|
PfSvContinueRunningTask(
|
|
PPFSVC_IDLE_TASK Task
|
|
);
|
|
|
|
//
|
|
// ProcessIdleTasks notify routine and its dependencies.
|
|
//
|
|
|
|
VOID
|
|
PfSvProcessIdleTasksCallback(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
PfSvForceWMIProcessIdleTasks(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
PfSvWaitForServiceToStart (
|
|
LPTSTR ServiceName,
|
|
DWORD MaxWait
|
|
);
|
|
|
|
//
|
|
// Wrappers around verify routines.
|
|
//
|
|
|
|
BOOLEAN
|
|
PfSvVerifyScenarioBuffer(
|
|
PPF_SCENARIO_HEADER Scenario,
|
|
ULONG BufferSize,
|
|
PULONG FailedCheck
|
|
);
|
|
|
|
//
|
|
// Debug definitions.
|
|
//
|
|
|
|
#if DBG
|
|
#ifndef PFSVC_DBG
|
|
#define PFSVC_DBG
|
|
#endif // !PFSVC_DBG
|
|
#endif // DBG
|
|
|
|
#ifdef PFSVC_DBG
|
|
|
|
//
|
|
// Define the component ID we use.
|
|
//
|
|
|
|
#define PFID DPFLTR_PREFETCHER_ID
|
|
|
|
//
|
|
// Define DbgPrintEx levels.
|
|
//
|
|
|
|
#define PFERR DPFLTR_ERROR_LEVEL
|
|
#define PFWARN DPFLTR_WARNING_LEVEL
|
|
#define PFTRC DPFLTR_TRACE_LEVEL
|
|
#define PFINFO DPFLTR_INFO_LEVEL
|
|
|
|
//
|
|
// DbgPrintEx levels 4 - 19 are reserved for the kernel mode component.
|
|
//
|
|
|
|
#define PFSTRC 20
|
|
#define PFWAIT 21
|
|
#define PFLOCK 22
|
|
#define PFPATH 23
|
|
#define PFNTRC 24
|
|
#define PFTASK 25
|
|
|
|
//
|
|
// This may help you determine what to set the DbgPrintEx mask.
|
|
//
|
|
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
|
|
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
|
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
//
|
|
|
|
NTSYSAPI
|
|
VOID
|
|
NTAPI
|
|
RtlAssert(
|
|
PVOID FailedAssertion,
|
|
PVOID FileName,
|
|
ULONG LineNumber,
|
|
PCHAR Message
|
|
);
|
|
|
|
#define DBGPR(x) DbgPrintEx x
|
|
#define PFSVC_ASSERT(x) if (!(x)) RtlAssert(#x, __FILE__, __LINE__, NULL )
|
|
|
|
//
|
|
// Variables used when saving traces acquired from the kernel. The
|
|
// traces are saved in the prefetch directory by appending the trace
|
|
// number % max number of saved traces to the base trace name.
|
|
//
|
|
|
|
WCHAR *PfSvcDbgTraceBaseName = L"PrefetchTrace";
|
|
LONG PfSvcDbgTraceNumber = 0;
|
|
LONG PfSvcDbgMaxNumSavedTraces = 20;
|
|
|
|
#else // PFSVC_DBG
|
|
|
|
#define DBGPR(x)
|
|
#define PFSVC_ASSERT(x)
|
|
|
|
#endif // PFSVC_DBG
|
|
|
|
#endif // _PFSVC_H_
|