WindowsXP-SP1/admin/services/sched/service/daytona/pfsvc.h
2020-09-30 16:53:49 +02:00

2050 lines
42 KiB
C

/*++
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 prefetch 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_REALLOC(Buffer,NumBytes) (HeapReAlloc(GetProcessHeap(),0,(Buffer),(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 chunk 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 {
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 section records.
//
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 scenarion 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 {
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 1 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 discrad 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
);
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_