|
|
/*++
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_
|