Windows 98 added a new feature, PageFile_Call_Async_Manager, that allows the Memory Manager to asynchronously write out page file (swap file) buffers during periods of time when VFAT file system activity is not busy.
This feature can affect the behavior of VxDs that monitor and/or otherwise intercept PageFile VxD functions. This article is applicable to you if your VxD hooks PageFile_Read_Or_Write, and you discover that you are not seeing all the page file traffic when using Windows 98.
You can disable this feature, causing the system to behave as Windows 95 does, at some cost in overall system performance. Add the following entry to the System.ini file, in its [386Enh] section:
When the above Boolean is set to TRUE as shown, PageFile_Call_Async_Manager is never called. If this entry is absent from System.ini, the default setting for ConservativeSwapfileUsage is 1 for Windows 95, and 0 (zero) for Windows 98.
When Windows 98 performs asynchronous writes to the swapfile, this activity is not captured by hooking PageFile_Read_Or_Write(). The PageFile_Set_Async_Manager service is called by VFAT to notify PageFile that VFAT is the manager of Async swap file activity; in fact, this makes the PageFile_Call_Async_Manager service become handled by a routine inside VFAT.
Memory Manager calls PageFile_Call_Async_Manager, supplying the service with a pointer to a Filesystem Idle routine mmFsIdle (in the Memory Manager). VFAT later calls this function when VFAT is completely idle (all pending VFAT writes have been written), so Memory Manager can execute asynchronous writes:
ULONG INTERNAL mmFsIdle(void);
In return, PageFile_Call_Async_Manager returns a pointer to a function that Memory Manager uses to perform the (async) writes to the pagefile:
extern int (CDECL *pfnAsyncPageOut)(PVOID pvBuffer, ULONG bFileOffset);
This function is actually inside VFAT (WriteAsyncSwapPage), which copies one page into its cache buffer and writes it. mmFsIdle uses an algorithm that generates pfnAsyncPageOut calls (that are actually calls to the internal VFAT routine).
Following is how the Memory Manager registers itself with VFAT:
mov eax, offset32 _mmFsIdle@0 ; Our idle callback.
VxDCall PageFile_Call_Async_Manager ; NOTE: the manager is VFAT.
jc DICDoneP ; Failed.
mov _pfnAsyncPageOut, eax