📄 api.c
字号:
InterlockedIncrement(&cFATThreads);
}
/* FATExit - Gates threads exiting FATFS
*
* ENTRY
* idLog - one of the LOGID_* equates
*
* EXIT
* None
*
* NOTES
* Called at the end of most FATFS API entry points. If we are
* the last thread, and the shutdown bit is set, then we will signal
* the shutdown event. The shutdown event is initially reset AND
* auto-reset.
*
* Also, if there is any risk of code inside here modifying the error code
* we set via SetLastError (if any), then that code must always save/restore
* the last error code. I think even if all the APIs it calls succeeds, some
* of those APIs may do something like "SetLastError(0)" when they initialize,
* so we have to guard against that.
*
* QUALIFICATIONS
* This is currently called only on every FATFS API entry point that
* could possibly generate I/O (with the exception of commit/close). If
* a thread slips into GetFileTime, for example, who cares? This could be
* restricted even further, and called only on entry points that could
* possibly generate WRITES, but since we ALSO want to ensure that shutdowns
* are timely (as well as safe), preventing as much I/O as possible seems
* worthwhile.
*
* Commit/close functions are exempted simply to allow us to block all
* threads and cleanly flush/unmount a volume without deadlocking.
*/
void FATExit(BYTE idLog)
{
BufExit();
if (InterlockedDecrement(&cFATThreads) == 0) {
}
}
void FATExitQuick(void)
{
InterlockedDecrement(&cFATThreads);
}
/* FATAttach - DLL_PROCESS_ATTACH handler
*
* ENTRY
* None
*
* EXIT
* TRUE if successful, FALSE if not. Most failures can probably
* be attributed to insufficient memory.
*
* NOTES
* This is assumed to be protected by a critical section. Since it is
* currently called only by FATMain, we are protected by the loader's
* critical section.
*/
BOOL FATAttach()
{
BOOL fInit = TRUE;
if (cLoads++ == 0) {
HKEY hKeyFATFS;
BYTE b;
DWORD dwFlags;
DWORD cb, dw, dwError;
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, awcFATFS, 0, KEY_ALL_ACCESS, &hKeyFATFS);
if (!dwError) {
cb = sizeof(dwFlags);
if (RegQueryValueEx(hKeyFATFS, awcFlags, NULL, &dw, (PBYTE)&dwFlags, &cb) == ERROR_SUCCESS && cb == sizeof(dwFlags)) {
flFATFS |= (dwFlags & FATFS_REGISTRY_FLAGS);
DEBUGMSG(ZONE_INIT && (dwFlags & ~FATFS_REGISTRY_FLAGS),(DBGTEXT("FATFS!FATAttach: unsupported bits set in registry flags: 0x%08x\n"), dwFlags & ~FATFS_REGISTRY_FLAGS));
}
cb = sizeof(b);
if (RegQueryValueEx(hKeyFATFS, awcUpdateAccess, NULL, &dw, &b, &cb) == ERROR_SUCCESS && cb == sizeof(b)) {
if (b)
flFATFS |= FATFS_UPDATE_ACCESS;
}
RegCloseKey(hKeyFATFS);
}
DEBUGREGISTER(hFATFS);
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!FATAttach: access time updates %s\n"), flFATFS & FATFS_UPDATE_ACCESS? TEXTW("enabled") : TEXTW("disabled")));
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!FATAttach: event logging %s\n"), flFATFS & FATFS_DISABLE_LOG? TEXTW("disabled") : TEXTW("enabled")));
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!FATAttach: automatic scanning %s\n"), flFATFS & FATFS_DISABLE_AUTOSCAN? TEXTW("disabled") : TEXTW("enabled")));
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!FATAttach: write verify %s\n"), flFATFS & FATFS_VERIFY_WRITES? TEXTW("enabled") : (flFATFS & FATFS_DISABLE_AUTOSCAN? TEXTW("disabled") : TEXTW("enabled on first 3 writes"))));
DEBUGMSGW(ZONE_INIT,(DBGTEXTW("FATFS!FATAttach: extra FAT on format %s\n"), flFATFS & FATFS_ENABLE_BACKUP_FAT? TEXTW("enabled") : TEXTW("disabled")));
InitList((PDLINK)&dlDisks);
#ifdef DEBUG
InitializeCriticalSection(&csAlloc);
DEBUGALLOC(DEBUGALLOC_CS);
#endif
InitializeCriticalSection(&csFATFS);
DEBUGALLOC(DEBUGALLOC_CS);
fInit = BufInit();
hevStartup = CreateEvent(NULL, TRUE, TRUE, NULL);
DEBUGALLOC(DEBUGALLOC_EVENT);
hevShutdown = CreateEvent(NULL, FALSE, FALSE, NULL);
DEBUGALLOC(DEBUGALLOC_EVENT);
}
return hevStartup && hevShutdown && fInit;
}
/* FATDetach - DLL_PROCESS_DETACH handler
*
* ENTRY
* None
*
* EXIT
* TRUE if successful, FALSE if not (currently, it always returns TRUE)
*
* NOTES
* This is assumed to be protected by a critical section. Since it is
* currently called only by FATMain, we are protected by the loader's
* critical section.
*/
BOOL FATDetach()
{
#if 0
ASSERT(cLoads > 0);
if (--cLoads == 0) {
int n = 300;
// Since we're being unloaded, make absolutely sure every thread
// is out, so that we leave the volume in a consistent state. The
// first step in preventing anyone NEW from getting in is closing
// all our API handles.
do {
// Give hevBufThreads a kick in case we've got any threads
// stacked up inside BufEnter; no *new* threads should be stacking
// up, since cLoads == 0 now. Do the same to get rid of the lazy-writer.
SetEvent(hevBufThreads);
#ifndef UNDER_CE
Sleep(0);
#else
Sleep(50);
#endif
if (cFATThreads == 0 && cBufThreads == cBufThreadsOrig || --n == 0)
break;
DEBUGMSGBREAK(TRUE, (DBGTEXT("FATFS!FATDetach: %d threads still active (%d using buffers) even after sleeping!\n"), cFATThreads, cBufThreadsOrig-cBufThreads));
}
while (TRUE);
// Simulating a power-off notification now will make sure that any other
// threads that were ALREADY inside are gone by the time this returns.
// As always, the most important reason for doing this is trying to insure
// that all volumes are left in a consistent state. WARNING: you don't
// want to do this *before* the sleep loop above, because otherwise one of
// those hypothetical "just *about* to enter us" threads will see that
// FATFS_SHUTDOWN is set and block forever. -JTP
FAT_Notify(NULL, FSNOTIFY_POWER_OFF);
#endif
// Now make sure every file is closed and every volume is freed,
// so that we don't leak any memory. We have deliberately omitted
// FATEnter/FATExit from FAT_CloseAllFiles and FAT_CloseFile
// to avoid deadlocking if any files *do* need to be closed.
UnmountAllDisks(FALSE);
BufDeinit();
DEBUGFREE(DEBUGALLOC_EVENT);
CloseHandle(hevShutdown);
DEBUGFREE(DEBUGALLOC_EVENT);
CloseHandle(hevStartup);
DEBUGFREE(DEBUGALLOC_CS);
DeleteCriticalSection(&csFATFS);
#ifdef DEBUG
DEBUGFREE(DEBUGALLOC_CS);
DeleteCriticalSection(&csAlloc);
#endif
// Assert that all allocations, buffers, etc, were freed
//YG DEBUGMSGBREAK(cbAlloc != 0, (DBGTEXT("FATFS!FATDetach: cbAlloc(0x%x) != 0\n"), cbAlloc));
ASSERT(cbufTotal == 0 && cbufError == 0);
DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!FATDetach complete (%d sectors written in %d requests)\n"), csecWrite, creqWrite));
#if 0
}
#endif
return TRUE;
}
BOOL FSD_MountDisk(HDSK hDsk)
{
DWORD flVol;
PDSK pdsk = NULL;
TCHAR szName[MAX_PATH];
wsprintf(szName, L"%08X", hDsk);
DEBUGMSGW(ZONE_INIT || ZONE_APIS,(DBGTEXTW("FSD_MountDisk: mounting volumes for hDsk=%08X\n"), hDsk));
flVol = VOLF_NONE;
// TODO: Add a function to FSDMGR to figure out READONLY Volumes
// TODO: flVol = VOLF_READONLY;
DEBUGALLOC(DEBUGALLOC_HANDLE);
pdsk = MountDisk((HANDLE)hDsk, szName, flVol);
if (pdsk) {
pdsk->d_flags |= flVol; // VOLF_READONLY maps to DSKF_READONLY
if (pdsk->d_flags & (DSKF_REMOUNTED | DSKF_RECYCLED)) {
// Make sure the REMOUNT bit in the VOLUME pointer is set
(DWORD)pdsk |= 0x1;
}
}
DEBUGMSG(ZONE_APIS,(DBGTEXT("FSD_Init returned 0x%x\n"), pdsk));
return (pdsk != NULL);
}
BOOL FSD_UnmountDisk(HDSK hDsk)
{
BOOL fSuccess = FALSE;
PDSK pdsk = NULL;
DEBUGMSG(ZONE_INIT || ZONE_APIS,(DBGTEXT("FSD_UnmountDisk(0x%x): unmounting...\n"), hDsk));
EnterCriticalSection(&csFATFS);
if (!hDsk) {
// Unmount all volumes still marked frozen on all disks
fSuccess = UnmountAllDisks(TRUE);
}
else if (pdsk = FindDisk((HANDLE)hDsk, NULL, NULL)) {
// Make sure the REMOUNT bit in the VOLUME pointer is clear
(DWORD)pdsk &= ~1;
fSuccess = UnmountDisk(pdsk, FALSE);
}
LeaveCriticalSection( &csFATFS);
DEBUGMSG(ZONE_APIS,(DBGTEXT("FSD_Deinit(0x%x) returned %d\n"), pdsk, fSuccess));
return fSuccess;
}
/* FATMain - FATFS.DLL initialization entry point
*
* ENTRY
* DllInstance - DLL module handle
* Reason - DLL_* initialization message
* Reserved - reserved
*
* EXIT
* TRUE if successful, FALSE if not. Most failures can probably
* be attributed to insufficient memory.
*/
BOOL WINAPI DllMain(HANDLE DllInstance, DWORD Reason, LPVOID Reserved)
{
switch(Reason) {
case DLL_PROCESS_ATTACH:
//DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!FATMain: DLL_PROCESS_ATTACH\n")));
hFATFS = (HINSTANCE)DllInstance;
return FATAttach();
case DLL_PROCESS_DETACH:
//DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!FATMain: DLL_PROCESS_DETACH\n")));
return FATDetach();
default:
//DEBUGMSG(ZONE_INIT,(DBGTEXT("FATFS!FATMain: Reason #%d ignored\n"), Reason));
break;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -