?? api.c
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
api.c
Abstract:
This file contains the file system API sets for the FAT file system.
Revision History:
--*/
#include "fatfs.h"
#include <storemgr.h>
#ifdef UNDER_CE
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXTW("FATFS"), {
TEXTW("Init"), // 0x0001
TEXTW("Errors"), // 0x0002
TEXTW("Shell Msgs"), // 0x0004
TEXTW("TFAT"), // 0x0008
TEXTW("Memory"), // 0x0010
TEXTW("APIs"), // 0x0020
TEXTW("Messages"), // 0x0040
TEXTW("Streams"), // 0x0080
TEXTW("Buffers"), // 0x0100
TEXTW("Clusters"), // 0x0200
TEXTW("FAT I/O"), // 0x0400
TEXTW("Disk I/O"), // 0x0800
TEXTW("Log I/O"), // 0x1000
TEXTW("Read Verify"), // 0x2000
TEXTW("Write Verify"), // 0x4000
TEXTW("Prompts"), // 0x8000
},
ZONEMASK_DEFAULT
};
#endif
#endif
CONST WCHAR awcFATFS[] = TEXTW("SYSTEM\\StorageManager\\FATFS");
CONST WCHAR awcCompVolID[] = TEXTW("CompVolID");
CONST WCHAR awcFlags[] = TEXTW("Flags"); // NOTE: "Flags" supercedes "UpdateAccess", but
CONST WCHAR awcCodePage[] = TEXTW("CodePage");
CONST WCHAR awcUpdateAccess[] = TEXTW("UpdateAccess"); // UpdateAccess was supported on v1.0, so we'll keep both -JTP
CONST WCHAR awcPathCacheEntries[] = TEXTW("PathCacheEntries");
CONST WCHAR awcFormatTfat[] = TEXTW("FormatTfat");
CONST WCHAR awcSecureWipe[] = TEXTW("SecureWipe");
#ifdef DEBUG
CONST WCHAR awcDebugZones[] = TEXTW("DebugZones");
#endif
/* Globals
*/
int cLoads; // count of DLL_PROCESS_ATTACH's
#ifdef SHELL_MESSAGE_NOTIFICATION
HWND hwndShellNotify; // from FAT_RegisterFileSystemNotification
#endif
#ifdef SHELL_CALLBACK_NOTIFICATION
SHELLFILECHANGEFUNC_t pfnShell; // from FAT_RegisterFileSystemFunction
#endif
HINSTANCE hFATFS;
DSK_DLINK dlDisks; // keeps track of every open FAT device
DWORD cFATThreads;
HANDLE hevStartup;
HANDLE hevShutdown;
CRITICAL_SECTION csFATFS;
HANDLE hHeap;
#ifdef DEBUG
int cbAlloc; // total bytes allocated
CRITICAL_SECTION csAlloc;
DWORD csecWrite = 0, creqWrite = 0;
#endif
/* FAT_CloseAllFiles
*
* Walk the open stream list, and for each open stream, walk the open
* handle list, and for each open handle, close it. Each CloseFileHandle
* becomes CloseHandle, which becomes FAT_CloseFile, which issues a
* CloseStream for the associated stream, and if that's the stream's last
* reference, CloseStream frees it.
*
* ENTRY
* pvol - pointer to VOLUME
* hProc - handle of terminating process;
* or NULL to close all file handles;
* or INVALID_HANDLE_VALUE to *commit* all file handles
*
* EXIT
* TRUE if successful, FALSE if not.
*/
BOOL FAT_CloseAllFiles(PVOLUME pvol, HANDLE hProc)
{
PFHANDLE pfh, pfhEnd;
PDSTREAM pstm, pstmEnd;
DEBUGMSG(ZONE_APIS,(DBGTEXT("FATFS!FAT_CloseAllFiles(0x%x,0x%x)\r\n"), pvol, hProc));
// We can't hold the volume's stream list critical section indefinitely (like
// while attempting to enter an arbitrary stream's critical section), so we
// have to let it go after selecting a stream to visit. So each stream has a
// VISITED bit that helps us remember which streams we have/have not visited.
// To protect the integrity of the VISITED bits, all functions that
// manipulate them must take the volume's critical section, too.
EnterCriticalSection(&pvol->v_cs);
// First, make sure the VISITED bit is clear in every stream currently
// open on this volume.
EnterCriticalSection(&pvol->v_csStms);
pstm = pvol->v_dlOpenStreams.pstmNext;
pstmEnd = (PDSTREAM)&pvol->v_dlOpenStreams;
while (pstm != pstmEnd) {
pstm->s_flags &= ~STF_VISITED;
// If all we're doing is committing, then we don't need to visit volume-based streams
// (just file-based streams).
if (hProc == INVALID_HANDLE_VALUE && (pstm->s_flags & STF_VOLUME))
pstm->s_flags |= STF_VISITED;
pstm = pstm->s_dlOpenStreams.pstmNext;
}
// Now find the next unvisited stream. Note that every iteration of the
// loop starts with the volume's "stream list" critical section held.
restart_streams_on_volume:
pstm = pvol->v_dlOpenStreams.pstmNext;
while (pstm != pstmEnd) {
if (pstm->s_flags & STF_VISITED) {
pstm = pstm->s_dlOpenStreams.pstmNext;
continue;
}
pstm->s_flags |= STF_VISITED;
// Add a ref to ensure that the stream can't go away once we
// let go of the volume's critical section.
pstm->s_refs++;
LeaveCriticalSection(&pvol->v_csStms);
EnterCriticalSection(&pstm->s_cs);
restart_files_on_stream:
pfh = pstm->s_dlOpenHandles.pfhNext;
pfhEnd = (PFHANDLE)&pstm->s_dlOpenHandles;
while (pfh != pfhEnd) {
if (pfh->fh_hProc == hProc || hProc == NULL || hProc == INVALID_HANDLE_VALUE) {
DEBUGMSGW(ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_CloseAllFiles: file %.11hs still open by 0x%08x\r\n"), pstm->s_achOEM, pfh->fh_hProc));
if (hProc != INVALID_HANDLE_VALUE) {
DEBUGMSGW(ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_CloseAllFiles: closing file now (0x%08x -> 0x%08x)\r\n"), pfh, pfh->fh_h));
SetHandleOwner(pfh->fh_h, GetCurrentProcess());
VERIFYTRUE(CloseFileHandle(pfh));
goto restart_files_on_stream;
}
else {
DEBUGMSGW(ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_CloseAllFiles: committing file now (0x%08x -> 0x%08x)\r\n"), pfh, pfh->fh_h));
FAT_FlushFileBuffers(pfh);
}
}
pfh = pfh->fh_dlOpenHandles.pfhNext;
}
CloseStream(pstm);
EnterCriticalSection(&pvol->v_csStms);
goto restart_streams_on_volume;
}
LeaveCriticalSection(&pvol->v_csStms);
LeaveCriticalSection(&pvol->v_cs);
DEBUGMSG(ZONE_APIS,(DBGTEXT("FATFS!FAT_CloseAllFiles returned TRUE\r\n")));
return TRUE;
}
/* FAT_Notify - Power off/device on notification handler
*
* ENTRY
* pvol - pointer to VOLUME (NULL if none)
* dwFlags - notification flags (see FSNOTIFY_*)
*
* EXIT
* None
*
* NOTES
* On FSNOTIFY_POWER_OFF notification, we want to make sure that all
* threads currently in FATFS that could, however briefly, put the
* disk into an inconsistent state, complete before we return from the
* power-off notification. This is accomplished by key FATFS APIs
* calling FATEnter and FATExit on entry and exit, so that we can (1)
* prevent new threads from entering, and (2) wake ourselves up when all
* old threads have left.
*
* On FSNOTIFY_POWER_ON notification, we simply set the volume's RETAIN
* flag, so that the next (imminent) FSD_Deinit will not cause the
* PC Card folder to be deregistered. After the FSNOTIFY_DEVICES_ON
* notification, DEVICE.EXE will call FSD_Deinit *again* with a special
* value (NULL) requesting us to completely close any volumes we no longer
* need to retain.
*
* On FSNOTIFY_DEVICES_ON notification, we simply clear our shutdown
* bit and allow any threads blocked in FATEnter to proceed. All driver(s)
* should once again be completely functional at that time.
*/
void FAT_Notify(PVOLUME pvol, DWORD dwFlags)
{
}
/* FATEnter - Gates threads entering FATFS
*
* ENTRY
* pvol - pointer to VOLUME
* idLog - one of the LOGID_* equates
*
* EXIT
* TRUE if successful, FALSE if not (SetLastError is already set)
*
*
* 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.
*
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -