📄 fsdapis.cpp
字号:
*
* ENTRY
* pVol -> VOL structure
* pwsPathName - pointer to name of new subdirectory
* pSecurityAttributes - pointer to security attributes (ignored)
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_CreateDirectoryW(PVOL pVol, PCWSTR pwsPathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
{
BOOL f=FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PCREATEDIRECTORYW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_CREATEDIRECTORYW])(pVol->dwVolData, pwsPathName, pSecurityAttributes);
if (f && pVol->hNotifyHandle) {
NotifyPathChange(pVol->hNotifyHandle, pwsPathName, TRUE, FILE_ACTION_ADDED);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_RemoveDirectoryW - Destroy an existing subdirectory
*
* ENTRY
* pVol -> VOL structure
* pwsPathName - pointer to name of existing subdirectory
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_RemoveDirectoryW(PVOL pVol, PCWSTR pwsPathName)
{
BOOL f=FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PREMOVEDIRECTORYW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_REMOVEDIRECTORYW])(pVol->dwVolData, pwsPathName);
if (f && pVol->hNotifyHandle) {
NotifyPathChange(pVol->hNotifyHandle, pwsPathName, TRUE, FILE_ACTION_REMOVED);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_GetFileAttributesW - Get file/subdirectory attributes
*
* ENTRY
* pVol -> VOL structure
* pwsFileName - pointer to name of existing file/subdirectory
*
* EXIT
* Attributes of file/subdirectory if it exists, 0xFFFFFFFF if it
* does not (call GetLastError for error code).
*/
DWORD FSDMGR_GetFileAttributesW(PVOL pVol, PCWSTR pwsFileName)
{
DWORD dw=0xffffffff;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
if (wcscmp( pwsFileName, L"\\") == 0) {
dw = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_TEMPORARY;
} else {
dw = ((PGETFILEATTRIBUTESW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_GETFILEATTRIBUTESW])(pVol->dwVolData, pwsFileName);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
dw = -1;
}
ExitVolume(pVol);
}
return dw;
}
/* FSDMGR_SetFileAttributesW - Set file/subdirectory attributes
*
* ENTRY
* pVol -> VOL structure
* pwsFileName - pointer to name of existing file/subdirectory
* dwAttributes - new attributes for file/subdirectory
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_SetFileAttributesW(PVOL pVol, PCWSTR pwsFileName, DWORD dwAttributes)
{
BOOL f=FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PSETFILEATTRIBUTESW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_SETFILEATTRIBUTESW])(pVol->dwVolData, pwsFileName, dwAttributes);
if (f && pVol->hNotifyHandle) {
NotifyPathChange(pVol->hNotifyHandle, pwsFileName, FALSE, FILE_ACTION_MODIFIED);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_DeleteFileW - Delete file
*
* ENTRY
* pVol -> VOL structure
* pwsFileName - pointer to name of existing file
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*
* NOTES
* A file marked FILE_ATTRIBUTE_READONLY cannot be deleted. You have to
* remove that attribute first, with SetFileAttributes.
*
* An open file cannot be deleted. All open handles must be closed first.
*
* A subdirectory cannot be deleted with this call either. You have to
* use RemoveDirectory instead.
*/
BOOL FSDMGR_DeleteFileW(PVOL pVol, PCWSTR pwsFileName)
{
BOOL f = FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PDELETEFILEW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_DELETEFILEW])(pVol->dwVolData, pwsFileName);
if (f && pVol->hNotifyHandle) {
NotifyPathChange(pVol->hNotifyHandle, pwsFileName, FALSE, FILE_ACTION_REMOVED);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_MoveFileW
*
* ENTRY
* pVol -> VOL structure
* pwsOldFileName - pointer to name of existing file
* pwsNewFileName - pointer to new name for file
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*
* NOTES
* We call FindFirst once to obtain the source directory stream for the
* for the existing file, and if it really exists, we call FindFirst
* again to obtain the destination directory stream for the new file,
* verifying that the new name does NOT exist. Then we create the new
* name and destroy the old.
*
* When moving a directory, we must make sure that our traversal
* of the destination path does not cross the source directory, otherwise
* we will end up creating a circular directory chain.
*/
BOOL FSDMGR_MoveFileW(PVOL pVol, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName)
{
BOOL f = FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PMOVEFILEW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_MOVEFILEW])(pVol->dwVolData, pwsOldFileName, pwsNewFileName);
if (f && pVol->hNotifyHandle) {
NotifyMoveFile(pVol->hNotifyHandle, pwsOldFileName, pwsNewFileName);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_DeleteAndRenameFileW
*
* ENTRY
* pVol -> VOL structure
* pwsDestFileName - pointer to name of existing file
* pwsSourceFileName - pointer to name of file to be renamed to existing file
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_DeleteAndRenameFileW(PVOL pVol, PCWSTR pwsDestFileName, PCWSTR pwsSourceFileName)
{
BOOL f=FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PDELETEANDRENAMEFILEW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_PRESTOCHANGOFILENAME])(pVol->dwVolData, pwsDestFileName, pwsSourceFileName);
if (f && pVol->hNotifyHandle) {
NotifyPathChange( pVol->hNotifyHandle, pwsDestFileName, FALSE, FILE_ACTION_REMOVED);
NotifyMoveFile(pVol->hNotifyHandle, pwsSourceFileName, pwsDestFileName);
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_GetFreeDiskSpaceW
*
* ENTRY
* pVol -> VOL structure
* pwsPathName -> volume name (eg, "\Storage Card")
* pSectorsPerCluster -> DWORD to receive sectors/cluster
* pBytesPerSector -> DWORD to receive bytes/sector
* pFreeClusters -> DWORD to receive available clusters on volume
* pClusters -> DWORD to receive total clusters on volume
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_GetDiskFreeSpaceW(PVOL pVol, PCWSTR pwsPathName, PDWORD pSectorsPerCluster, PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters)
{
BOOL f = FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
f = ((PGETDISKFREESPACEW)pVol->pDsk->pFSD->apfnAFS[AFSAPI_GETDISKFREESPACE])(pVol->dwVolData, pwsPathName, pSectorsPerCluster, pBytesPerSector, pFreeClusters, pClusters);
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
ExitVolume(pVol);
}
return f;
}
/* FSDMGR_CloseAllFiles (no FSD equivalent)
*
* ENTRY
* pVol -> VOL structure
* hProc == handle of terminating process
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_CloseAllFiles(PVOL pVol, HANDLE hProc)
{
return TRUE;
}
/* FSDMGR_CommitAllFiles (no FSD equivalent)
*
* ENTRY
* pVol -> VOL structure
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FSDMGR_CommitAllFiles(PVOL pVol)
{
PHDL pHdl;
__try {
pHdl = pVol->dlHdlList.pHdlNext;
while (pHdl != (PHDL)&pVol->dlHdlList) {
((PFLUSHFILEBUFFERS)pHdl->pVol->pDsk->pFSD->apfnFile[FILEAPI_FLUSHFILEBUFFERS])(pHdl->dwHdlData);
pHdl = pHdl->dlHdl.pHdlNext;
}
} __except(ReportFault(GetExceptionInformation(), 0), EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
return TRUE;
}
/* FSDMGR_Notify - FSD notification handler
*
* ENTRY
* pVol -> VOL structure
* dwFlags == one or more FSNOTIFY_* flags
*
* EXIT
* None.
*
* NOTES
* This function is invoked once per registered volume every time the
* power goes off, comes back, or devices have finished initializing. I'm
* only interested in hooking the FSNOTIFY_POWER_ON notification, so that I
* can flag all relevant disks as UNCERTAIN, but unfortunately, I cannot
* avoid being called for all events, not to mention multiple times per disk
* if there are multiple volumes per disk.
*/
void Disk_PowerOn(HANDLE hDsk);
void Disk_PowerOff(HANDLE hDsk);
void FSDMGR_Notify(PVOL pVol, DWORD dwFlags)
{
extern DWORD g_dwWaitIODelay;
PREFAST_ASSERT(VALIDSIG(pVol, VOL_SIG));
// Do not use TryEnterVolume/ExitVolume for the notify API because we don't
// want to modify the volume reference count. Instead, just catch invalid or
// removed volumes using exception handling.
__try {
if (dwFlags & FSNOTIFY_POWER_OFF) {
DEBUGMSG( ZONE_APIS, (L"FSDMGR_Notfiy - PowerDown on volume %08X\r\n", pVol));
ResetEvent( g_hResumeEvent);
FSDMGR_CommitAllFiles(pVol); // NOTE: This must come before setting the powerdown flag !!!
MarkVolume(pVol, VOL_POWERDOWN);
Disk_PowerOff(pVol->pDsk->hDsk);
} else
if (dwFlags & FSNOTIFY_POWER_ON) {
DEBUGMSG( ZONE_APIS, (L"FSDMGR_Notfiy - Powerup on volume %08X\r\n", pVol));
Disk_PowerOn(pVol->pDsk->hDsk);
UnmarkVolume(pVol, VOL_POWERDOWN);
SetEvent( g_hResumeEvent);
}
// Now pass the notification on to the FSD as well; in general, they shouldn't
// need to do very much on these events, because we've tried to take care of the
// hard problems already, and these events need to be responsive.
// However, one common requirement is flushing all non-handle-based data (eg,
// dirty buffers) on the FSNOTIFY_POWER_OFF event. We could ask the FSDs to
// export a special "Flush" interface that we can call from here, but that seems
// like a pointless abstraction, especially given that other interesting FSNOTIFY
// events may be added in the future and I'd rather not have to rev FSDMGR just
// for that.
((PNOTIFY)pVol->pDsk->pFSD->apfnAFS[AFSAPI_NOTIFY])(pVol->dwVolData, dwFlags);
// We don't ReportFault for this specifically since we can hit a legit exception if the device goes away
} __except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_ACCESS_DENIED);
}
}
/* FSDMGR_RegisterFileSystemFunction
*
* ENTRY
* pVol -> VOL structure
* pfn -> function address to call
*
* EXIT
* TRUE if supported, FALSE if not
*/
BOOL FSDMGR_RegisterFileSystemFunction(PVOL pVol, SHELLFILECHANGEFUNC_t pfn)
{
BOOL f=FALSE;
WaitForVolume(pVol);
if (TryEnterVolume(pVol)) {
__try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -