下面转个老外写的介绍FSDMGR的文章,不错,转到这里,权当备份。
INTERACTING WITH FSDMGR
In interacting with the FSDMGR and its helper functions, there are two pseudo-handle types that will be used: HDSK and HVOL (these types are defined in fsdmgr.h). While there is a one-to-one mapping of HDSK to HVOL, they are not the same construct.
The HDSK is a reference to the disk object beneath the file system and is required for performing any disk-base I/O operations. The HDSK exists regardless of whether or not the partition is mounted.
Unlike the HDSK, the HVOL is a reference to the volume object associated with an instance of an FSD mounted on an HDSK. The HVOL can be though of as a virtual link between the mount point in the root file system exposed to user applications (e.g. “/Storage Card”) and a physical partition on a disk (“Part00” on “DSK1:”).
Mounting a Volume
To establish the link between an HVOL and an HDSK, the FSD_MountDisk export of an FSD is invoked and the HDSK parameter is passed to this function. During the FSD_MountDisk function, the FSD must call the helper function FSDMGR_RegisterVolume to instantiate a new HVOL, associate it with the specified HDSK, and assign it a mount point in the root file system.
When calling FSDMGR_RegisterVolume, the FSD can supply its own context to FSDMGR. This context will be passed back to the FSD on subsequent file API calls. Typically, the FSD will use this context to point to a heap-allocated structure describing a particular instance of the FSD associated with an HVOL and HDSK. A well-designed FSD should encapsulate all information in this context so that it can support multiple instances simultaneously using the same driver.
The following code sample illustrates how an FSD might implement its FSD_MountDisk function:
#include <windows.h>
#include <fsdmgr.h>
// A structure used to track an instance of a volume managed by this FSD.
typedef struct __InternalVolumeObject {
HDSK hDsk; // Disk psuedo-handle passed to FSD_MountDisk
HVOL hVol; // Volume psuedo-handle returned from FSDMGR_RegisterVolume.
CRITICAL_SECTION csVolume;
WCHAR szFolderName[MAX_PATH];
SHELLFILECHANGEFUNC_t pNotifyCallBack;
InternalFileObject* pOpenFileList; // List of currently open files.
/*
* Additional volume context information goes here.
*/
// A pointer to the next InternalVolumeObject object on the global
// volume list (g_pVolumeList).
struct __InternalVolumeObject* pNext;
} InternalVolumeObject;
// A global list to track all currently mounted volumes managed by this FSD.
static InternalVolumeObject* g_pVolumeList = NULL;
// A global critical section to protect the global volume list during
// asyncrhonous access from multiple threads. This critical section should
// be initialized in DllMain.
static CRITICAL_SECTION g_csVolumeList;
// DetectBootSectorFormat
//
// TBD: Define this function to detect a valid boot sector. This function
// will be dependent on the file system driver.
BOOL DetectBootSectorFormat (BYTE* pBootSector);
// FSD_MountDisk
//
// Called to mount a new volume on a partition. If the FSD is unable to
// mount the partition, this function should return FALSE. Otherwise, it
// should return TRUE.
//
BOOL FSD_MountDisk (HDSK hDsk)
{
DWORD dwFormat = 0;
FSD_DISK_INFO fdi;
BYTE* pSectorBuffer = NULL;
InternalVolumeObject* pVolume = NULL;
// Query disk information.
if (!FSDMGR_GetDiskInfo (hDsk, &fdi)) {
// Failed to retrieve disk geometry.
return FALSE;
}
// Allocate a sector buffer.
pSectorBuffer = (BYTE*)LocalAlloc (LMEM_FIXED, fdi.cbSector);
if (!pSectorBuffer) {
return FALSE;
}
// Read sector zero (bootsector) and evaluate the format.
if (!FSDMGR_ReadDisk (hDsk, 0, 1, pSectorBuffer, fdi.cbSector)) {
// Failed to read from disk.
LocalFree (pSectorBuffer);
return FALSE;
}
// Check the registry to see if we should auto-format.
FSDMGR_GetRegistryValue (hDsk, L"Format", &dwFormat);
if (!DetectBootSectorFormat (pSectorBuffer)) {
DEBUGMSG (ZONE_INIT, (L"MyFSD!FSD_MountDisk: Invalid format!"));
// Did not recognize the disk format.
if (dwFormat) {
// NOTE: We must have a utility library specified in the
// registry and the library must export FormatVolumeEx for
// this format call to succeed.
if (!FSDMGR_FormatVolume (hDsk, NULL)) {
LocalFree (pSectorBuffer);
return FALSE;
}
}
LocalFree (pSectorBuffer);
return FALSE;
}
LocalFree (pSectorBuffer);
pSectorBuffer = NULL;
// At this point we have a valid format. Allocate a new volume
// structure and register it.
pVolume = (InternalVolumeObject*)LocalAlloc (LPTR,
sizeof (InternalVolumeObject));
if (!pVolume) {
return FALSE;
}
// Populate the volume structure.
pVolume->hDsk = hDsk;
// Try to get the volume name from our "MountName" registry value.
if (!FSDMGR_GetRegistryString (hDsk, L"MountName",
&pVolume->szFolderName, MAX_PATH)) {
// Unable to read the registry value, try IOCTL_DISK_GETNAME.
if (!FSDMGR_DiskIoControl (hDsk, IOCTL_DISK_GETNAME, NULL, 0,
pVolume->szFolderName, sizeof (pVolume->szFolderName),
NULL, NULL)) {
// Still unable to find a mount name, so use our default string.
wcscpy (pVolume->szFolderName, L"Mounted Volume");
}
}
// Register the volume.
pVolume->hVol = FSDMGR_RegisterVolume (hDsk, pVolume->szFolderName,
pVolume);
if (!pVolume->hVol) {
// Failed to register the volume.
LocalFree (pVolume);
return FALSE;
}
// Read back the real volume name we registered with. If we registered
// as "Hard Disk" and this mount name already existed, we might get back
// "Hard Disk2" as the true mount name. We will need this value later on
// for posting file notifications.
FSDMGR_GetVolumeName (pVolume->hVol, pVolume->szFolderName, MAX_PATH);
DEBUGMSG (ZONE_INIT, (L"MyFSD!FSD_MountDisk: Mounted new volume as /"%s/"",
pVolume->szFolderName));
// Initialize a new critical section used to guard the pVolume object
// during asynchronous access.
InitializeCriticalSection (&pVolume->csVolume);
// Add this volume to the front of our global volume list.
EnterCriticalSection (&g_csVolumeList);
pVolume->pNext = g_pVolumeList;
g_pVolumeList = pVolume;
LeaveCriticalSection (&g_csVolumeList);
// The volume was successfully registered; pVolume will be passed to
// subsequent API calls performed on this volume.
return TRUE;
}
Dismounting a Volume
To remove the link between an HVOL and an HDSK, the FSD_UnmountDisk export of an FSD is invoked and the HDSK parameter is passed to this function. During this call, the FSD must deallocate all resources associated with this HDSK. This call occurs in response to programmatic partition dismounting (DismountStore or DismountPartition invoked by an application) or after media removal.
Typically, a global list of HDSK-to-Volume Context mappings must be maintained in the FSD so that the appropriate volume can be deregistered during FSD_UnmountDisk. This is necessary because FSD_UnmountDisk receives an HDSK parameter instead of a Volume-Context like other FSD APIs.
The following code sample illustrates how an FSD might implement its FSD_UnmountDisk function:
// FSD_UnmountDisk
//
// Called when an FSD is to be unloaded, typically due to a partition being
// dismounted either programatically or due to media removal. This function
// should always return TRUE.
//
BOOL FSD_UnmountDisk (HDSK hDsk)
{
InternalVolumeObject* pPrev = NULL;
InternalVolumeObject* pCurrent;
// Locate the volume object matching this disk.
EnterCriticalSection (&g_csVolumeList);
pCurrent = g_pVolumeList;
while (pCurrent) {
if (pCurrent->hDsk == hDsk) {
// Found a volume with a matching HDSK on our list.
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->pNext;
}
if (pCurrent) {
// Remove this item from the list.
if (pPrev) {
pPrev->pNext = pCurrent->pNext;
} else {
g_pVolumeList = pCurrent->pNext;
}
}
LeaveCriticalSection (&g_csVolumeList);
if (!pCurrent) {
// This is not a disk we have mounted. This should never happen.
return FALSE;
}
// Deregister the volume.
FSDMGR_DeregisterVolume (pCurrent);
// Free the internal volume structure.
LocalFree (pCurrent);
// Always succeed FSD_UnmountDisk.
return TRUE;
}
File and Search Handle Context Objects
A HANDLE value is required to be returned from FSD_CreateFileW and FSD_FindFirstFileW APIs. A HANDLE is essentially just an entry in a table that refers to an object. The object associated with any handles returned by your FSD should be a heap allocated structure with information about the object. The following example shows what the objects associated with file and search handles might look like:
// Context representing a handle to a file. This structure encapsulates
// all information associated with a single handle. Multiple handles can
// refer to the same InternalFileObject object (assuming sharing modes
// are correct). A pointer to one of these structures will always be passed
// as the first parameter to all handle-based file APIs.
typedef struct __FileHandleContext {
InternalVolumeObject* pVolume; // A reference to the parent volume.
DWORD dwAccess; // GENERIC_READ, GENERIC_WRITE
DWORD dwSharing; // FILE_SHARE_READ, FILE_SHARE_WRITE
LARGE_INTEGER FileOffset; // 64-bit file position.
InternalFileObject* pFileObject; // Reference to the file object.
// A pointer to the next FindHandleContxt object on a file object's
// file handle list (InternalFileObject.pHandleList).
struct __FileHandleContext* pNext;
} FileHandleContext;
// Context representing a handle to a directory enumeration instance.
// This structure encapsulates all information associated with a single
// search. A pointer to one of these structures will always be passed
// as the first parameter to all handle-based search APIs.
typedef struct __SearchHandleContext {
InternalVolumeObject* pVolume; // A reference to the parent volume.
DWORD dwEnumPosition; // Enumeration position.
WCHAR szSearchSpec[MAX_PATH]; // Search specification including wildcards.
} SearchHandleContext;
Creating Handle Context Object
A handle object should be allocated each time FSD_FindFirstFileW or FSD_CreateFileW is called and freed when FSD_FindClose or FSD_CloseFile is called, respectively. The following example shows how these functions might be definied:
// A structure used to track information about a specific file.
typedef struct __InternalFileObject {
// A pointer to the parent volume that owns this open file.
InternalVolumeObject* pVolume;
// A pointer to the head of the list of handles open to this file.
// Once this list goes to zero, this file object can be destroyed.
FileHandleContext* pHandleList;
// A critical section to guard asyncrhonous access to this file
// object.
CRITICAL_SECTION csFile;
/*
* Additional file object information goes here. This includes
* things such as a pointer to the file's directory entry, etc.
*/
// A pointer to the next InternalFileObject object on the volume's
// open file list (InternalVolumeObject.pOpenFileList).
struct __InternalFileObject* pNext;
} InternalFileObject;
// Internal FSD function used to open a file. If the file is already open,
// this should return a pointer to the existing InternalFileObject structure.
// If the file is not currently open, instantiate a new InternalFileObject for
// it and add it to the InternalVolumeObject's open file list.
InternalFileObject* CreateOrOpenFileObject (InternalVolumeObject* pVolume,
LPCWSTR pszFileName, DWORD dwAccess, DWORD dwShareMode, DWORD dwCreate
DWORD dwFlagsAndAttributes);
// Internal FSD funciton used to remove a reference from a file object.
void CloseFileObject (InternalFileObject* pFile);
// FSD_CreateFileW
//
// Create or open a file. Parallels the Win32 CreateFileW API.
//
HANDLE FSD_CreateFileW (
DWORD dwVolume,
HANDLE hProcess,
LPCWSTR pszFileName,
DWORD dwAccess,
DWORD dwShareMode,
PSECURITY_ATTRIBUTES pSecurityAttributes,
DWORD dwCreate,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile )
{
// Parameter 1 is always a pointer to our volume structure.
InternalVolumeObject* pVolume = (InternalVolumeObject*)dwVolume;
// Invoke our internal function to create or open the file on this
// volume.
InternalFileObject* pFile = CreateOrOpenFileObject (pVolume, pszFileName,
dwAccess, dwShareMode, dwCreate, dwFlagsAndAttributes);
if (!pFile) {
// Failed to open or create the file.
return INVALID_HANDLE_VALUE;
}
// Allocate a new handle context.
FileHandleContext* pFileHandle;
pFileHandle = (FileHandleContext*)LocalAlloc (LMEM_FIXED,
sizeof (FileHandleContext));
if (!pFileHandle) {
CloseFileObject (pFile);
return INVALID_HANDLE_VALUE;
}
// Populate the file handle context structure.
pFileHandle->pFile = pFile;
pFileHandle->dwShareMode = dwShareMode;
pFileHandle->dwAccess = dwAccess;
pFileHandle->FilePosition.QuadPart = 0;
// Add this handle to the open file's handle list.
EnterCriticalSection (&pFile->csFile);
pFileHandle->pNext = pFile->pHandleList;
pFile->pHandleList = pNext;
LeaveCriticalSection (&pFile->csFile);
// Use the FSDMGR helper function to convert the pointer to an
// InternalFileObject into a handle before returning.
return FSDMGR_CreateFileHandle (pVolume->hVol, hProcess, (PFILE)pFile);
}
In the above example, the CreateOrOpenFileObject and CloseFileObject functions would be FSD specific and would be implemented by the FSD developer. The FSD_FindFirstFileW would be implemented similarly, but it would use the FSDMGR_CreateSearchHandle helper function to create the handle to be returned instead.
Destroying Handle Context Objects
Handle cleanup is performed in the FSD_FindClose and FSD_CloseFile functions. The following example illustrates how this functionality might be implemented for file handles:
// FSD_CloseFile
//
// Cleanup an open handle to a file and commit any buffered portions
// of the open file.
//
BOOL FSD_CloseFile (DWORD dwFile)
{
// Parameter 1 is always a pointer to our file handle structure.
FileHandleContext* pFileHandle = (FileHandleContext*)dwFile;
// Get a reference to the current open file.
InternalFileObject* pFile = pFileHandle->pFile;
FileHandleContext* pPrev = NULL
FileHandleContext* pCurrent;
EnterCriticalSection (&pFile->csFile);
pCurrent = pFile->pHandleList;
while (pCurrent) {
if (pCurrent == pFileHandle) {
// Found the requested handle on the list.
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->pNext;
}
if (pCurrent) {
// Remove this handle from the list.
if (pPrev) {
pPrev->pNext = pCurrent->pNext;
} else {
pFile->pHandleList = pCurrent->pNext;
}
}
LeaveCriticalSection (&pFile->csFile);
if (!pCurrent) {
// This is not a handle we're aware of. This should never happen.
return FALSE;
}
// Free the closed handle object.
LocalFree (pFileHandle);
// Cleanup the file object. This will do nothing if there are remaining
// references to the file from other open handles.
CloseFileObject (pFile);
// Always succeed, even if the file could not be flushed/committed.
return TRUE;
}
相关推荐
Python library for interacting with FreeIPA network protocols
Golang client for interacting with Moov API server side
interacting with data This lecture covers the basics of core concepts in probability and statistics to be used in the course. These include random variables, continuous and discrete distributions, ...
【应用】★★★★★-manzana-.NET API for interacting with the Apple iPhone【应用】★★★★★-manzana-.NET API for interacting with the Apple iPhone 1.适合学生学习研究参考 2.适合个人学习研究参考 3.适合...
《manzana-.NET API for interacting with the Apple iPhone》是一个专为与苹果iPhone进行交互而设计的.NET API库。这个源码包对于那些希望在iOS平台上构建应用的开发者来说,是一份宝贵的资源,特别是对.NET框架有...
C++作为一款强大的系统编程语言,虽然原生不支持JSON解析和生成,但有许多第三方库可以帮助开发者处理JSON,其中之一就是这个"A C++ library for interacting with JSON"。 在C++中,与JSON交互的库通常提供了解析...
【标题】"IOS应用源码之manzana-.NET API for interacting with the Apple iPhone" 提供了一种使用.NET框架与苹果iPhone进行交互的途径。manzana是一个.NET库,它为开发者提供了方便的API,使得在iOS应用开发过程中...
Nitrogen fixation of faba bean interacting with a non-legume in two contrasting intercropping systems,范分良,余常兵,A field experiment was carried out to quantify biological nitrogen fixation (BNF)...
The module has two 32-bit MCUs - an x86 Intel Quark processor and an ARC EM4 processor along with 384kB flash memory and 80kB SRAM. These onboard MCUs combine a variety of new technologies including ...
本文将深入探讨标题为“【应用】-manzana-.NET API for interacting with the Apple iPhone.7z”的压缩包,其中包含了一个名为“Manzana”的.NET库,它为开发者提供了一种与Apple iPhone进行交互的方式。 首先,...
《ISO IEC TR 23187:2020 Information technology - Cloud computing - Interacting with cloud service partners (CSNs)》是国际标准化组织(ISO)和国际电工委员会(IEC)联合发布的一份技术报告,旨在为云计算...
在Android开发中,应用程序通常由多个Activity组成,每个Activity对应一个用户界面,并负责完成特定的任务。例如,一个Activity可以专门用于显示地图,而另一个可能用于拍照功能。当需要在不同的Activity之间转换,...
两个关联腔模与两分立原子相互作用后的非经典性质,郑小兰,缪龙,本文利用Jaynes-Cummings 模型讨论了初始处于对相干态的叠加态的两个模分别与两个二能级原子共振相互作用后的非经典性质,包括压缩性�
《苹果iPhone交互.NET API——Manzana库详解》 在当今移动开发领域,iOS系统以其稳定性和用户友好性获得了广大开发者和用户的喜爱。对于非Objective-C或Swift开发者来说,想要与苹果iPhone进行交互可能会遇到一些...
《2016-Interacting Multiview Tracker》是一个针对多视图交互追踪技术的研究项目,由韩国国立釜山大学计算机视觉实验室(CVL@GIST)的团队开发。这个项目的主要目标是解决在多个视角下同时跟踪多个目标物体的问题,...
UNIT 2 - STRINGS, TUPLES, AND INTERACTING WITH THE USER Lesson 7 - Introducing string objects: sequences of characters Lesson 8 - Advanced string operations Lesson 9 - Simple error messages Lesson 10 ...
Interacting With Your Users CHAPTER 4. Introducing MySQL CHAPTER 5. Introducing the Zend Framework CHAPTER 6. Talking to the Database with Zend_Db CHAPTER 7. Processing Forms and Sending Email ...
As with all classes derived from SocketClient, you must first connect to the server with connect before doing anything, and finally disconnect after you're completely finished interacting with the ...
We will then learn how to build learning agents that can learn from interacting with the environment. We will use Deep Learning with Convolutional Neural Networks, and use TensorFlow to build neural ...