📄 apis.c
字号:
/*++
Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
Module Name:
apis.c
Abstract:
This file contains the FSDMGR entry points for all supported file
system APIs.
--*/
#define KEEP_SYSCALLS // for kernel.h only
#define NO_DEFINE_KCALL // for kernel.h only
#include "kernel.h"
#include "fsdmgrp.h"
#define KERNELCALLSTACK(pcstk) (((DWORD)(pcstk)->retAddr & 0xf0000000) == 0x80000000)
/* FSDMGR_SystemCanDeadlock - Determine if caller is kernel
*
* ENTRY
* pvol -> VOL structure
*
* EXIT
* TRUE if caller is kernel, FALSE if not
*
* NOTES
* We need this special power-down test before calling FSDMGR_Enter so
* that if/when the loader tries to open PCMCIA drivers before we have
* received the FSNOTIFY_DEVICES_ON notification, we will fail the
* call instead of blocking it.
*/
BOOL FSDMGR_SystemCanDeadlock(PVOL pVol)
{
// If we're in a "shutdown" state, meaning all calls to FATEnter will
// block until FSNOTIFY_DEVICES_ON is issued, then we need to make this
// check in a few key places (ie, where the kernel may call us) in order
// to prevent a deadlock.
//#if 0
PTHREAD pth;
PCALLSTACK pcstk;
if (!(pVol->dwFlags & VOL_POWERDOWN))
return FALSE;
pth = ((PHDATA)((GetCurrentThreadId() & HANDLE_ADDRESS_MASK) + 0x80000000))->pvObj;
if (pcstk = pth->pcstkTop) {
if (KERNELCALLSTACK(pcstk) || (pcstk = pcstk->pcstkNext) && KERNELCALLSTACK(pcstk)) {
SetLastError(ERROR_ACCESS_DENIED);
return TRUE;
}
}
//#endif
return FALSE;
}
/* FSDMGR_Enter - Tracks (and potentially blocks) threads entering an FSD
*
* ENTRY
* pVol -> VOL structure
*
* EXIT
* None
*
* NOTES
* It's not strictly necessary to keep track of threads entering
* an FSD on a per-volume basis, or to block them on such a basis --
* these functions could just as easily perform their task using globals.
*/
void FSDMGR_Enter(PVOL pVol)
{
ASSERT(VALIDSIG(pVol, VOL_SIG));
if (pVol->dwFlags & VOL_POWERDOWN)
WaitForSingleObject(pVol->hevPowerUp, INFINITE);
InterlockedIncrement(&pVol->cThreads);
}
/* FSDMGR_Exit - Tracks threads leaving an FSD (and can signal when the last one leaves)
*
* ENTRY
* pVol -> VOL structure
*
* EXIT
* None
*
* NOTES
* See FSDMGR_Enter for notes.
*/
void FSDMGR_Exit(PVOL pVol)
{
ASSERT(VALIDSIG(pVol, VOL_SIG));
if (InterlockedDecrement(&pVol->cThreads) == 0) {
if (pVol->dwFlags & VOL_POWERDOWN)
SetEvent(pVol->hevPowerDown);
}
}
/* FSDMGR_CloseVolume - Called when a volume is being deregistered
*
* ENTRY
* pVol -> VOL structure
*
* EXIT
* Always returns TRUE (that's what OUR stub always does, and it's
* expected that that's what FSDs will do too, if they even care to hook
* this entry point).
*/
BOOL FSDMGR_CloseVolume(PVOL pVol)
{
return pVol->pDsk->pFSD->apfnAFS[AFSAPI_CLOSEVOLUME](pVol->dwVolData);
}
/* FSDMGR_CreateDirectoryW - Create a new subdirectory
*
* 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;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_CREATEDIRECTORYW](pVol->dwVolData, pwsPathName, pSecurityAttributes);
FSDMGR_Exit(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;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_REMOVEDIRECTORYW](pVol->dwVolData, pwsPathName);
FSDMGR_Exit(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;
FSDMGR_Enter(pVol);
dw = pVol->pDsk->pFSD->apfnAFS[AFSAPI_GETFILEATTRIBUTESW](pVol->dwVolData, pwsFileName);
FSDMGR_Exit(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;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_SETFILEATTRIBUTESW](pVol->dwVolData, pwsFileName, dwAttributes);
FSDMGR_Exit(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;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_DELETEFILEW](pVol->dwVolData, pwsFileName);
FSDMGR_Exit(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;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_MOVEFILEW](pVol->dwVolData, pwsOldFileName, pwsNewFileName);
FSDMGR_Exit(pVol);
return f;
}
/* FSDMGR_DeleteAndRenameFileW
*
* ENTRY
* pVol -> VOL structure
* pwsOldFileName - pointer to name of existing file
* pwsNewFileName - 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 pwsOldFileName, PCWSTR pwsNewFileName)
{
BOOL f;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_PRESTOCHANGOFILENAME](pVol->dwVolData, pwsOldFileName, pwsNewFileName);
FSDMGR_Exit(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;
FSDMGR_Enter(pVol);
f = pVol->pDsk->pFSD->apfnAFS[AFSAPI_GETDISKFREESPACE](pVol->dwVolData, pwsPathName, pSectorsPerCluster, pBytesPerSector, pFreeClusters, pClusters);
FSDMGR_Exit(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)
{
PHDL pHdl;
FSDMGR_Enter(pVol);
loop1:
pHdl = pVol->dlHdlList.pHdlNext;
while (pHdl != (PHDL)&pVol->dlHdlList) {
if (pHdl->hProc == hProc) {
SetHandleOwner(pHdl->h, GetCurrentProcess());
if (CloseHandle(pHdl->h))
goto loop1; // handle was freed, state of our list has changed
}
pHdl = pHdl->dlHdl.pHdlNext;
}
FSDMGR_Exit(pVol);
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;
// There ain't no steenkin' FSDMGR_Enter/FSDMGR_Exit calls in this function
// because it's called during FSNOTIFY_POWER_OFF and we don't want to hang ourselves.
pHdl = pVol->dlHdlList.pHdlNext;
while (pHdl != (PHDL)&pVol->dlHdlList) {
pHdl->pVol->pDsk->pFSD->apfnFile[FILEAPI_FLUSHFILEBUFFERS](pHdl->dwHdlData);
pHdl = pHdl->dlHdl.pHdlNext;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -