fsnotify.cpp

来自「WinCE5.0部分核心源码」· C++ 代码 · 共 972 行 · 第 1/3 页

CPP
972
字号
//
// 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.
//
#include <windows.h>
#include "fsnotify.h"

HANDLE g_hNotifyAPI = NULL;
CRITICAL_SECTION g_csMain;
NOTVOLENTRY *g_pRootVolume = NULL;

#ifdef UNDER_CE

#define ARRAY_SIZE(a)           (sizeof(a)/sizeof(a[0]))


CONST PFNVOID apfnFindNotify[3] = {
        (PFNVOID)NotifyCloseEvent,
        (PFNVOID)NULL,
        (PFNVOID)NotifyReset,
};

CONST DWORD asigFindNotify[3] = {
        FNSIG1(DW),                                     // FindClose
        FNSIG0(),                                       //
        FNSIG2(DW, PTR)                                 // FindNextFileW
};
#endif

#ifndef UNDER_CE
#define FILE_NOTIFY_CHANGE_CEGETINFO 0x80000000
#endif

void AddFileToEvent(NOTEVENTENTRY *pEvent, WCHAR *szFileName, DWORD dwFlags, DWORD dwAction);
void CheckEventOnPath(NOTEVENTENTRY *pEvent, BOOL bSubTree, BOOL bPath);
void NotifyHandleChangeEx(HANDLE hVolume, HANDLE h, DWORD dwFlags, DWORD dwAction);

HANDLE FindNotifyHandleOnDirectory( NOTDIRENTRY *pDirectory, HANDLE hEvent) 
{
    HANDLE hNotify = NULL;
    while(pDirectory) {
        NOTEVENTENTRY *pEvent = pDirectory->pEvents;
        while(pEvent) {
            if (pEvent->hEvent == hEvent) {
                hNotify = pEvent->hNotify;
                break;
            }
            pEvent = pEvent->pNext;
        }
        if (hNotify || (pDirectory->pChild && (hNotify = FindNotifyHandleOnDirectory(pDirectory->pChild, hEvent)))) {
            break;
        }   
        pDirectory = pDirectory->pNext;
    }
    return hNotify;
}

HANDLE GetNotifiyHandle(HANDLE hEvent) 
{
    HANDLE hNotify = NULL;
    EnterCriticalSection( &g_csMain);
    NOTVOLENTRY *pVolume = g_pRootVolume;
    while(pVolume) {
        ENTERNOTIFY( pVolume);
        NOTEVENTENTRY *pEvent = pVolume->pEvents;
        while(pEvent) {
            if (pEvent->hEvent == hEvent) {
                hNotify = pEvent->hNotify;
                break;
            }
            pEvent = pEvent->pNext;
        }
        if (hNotify || (pVolume->pDirEntry && (hNotify = FindNotifyHandleOnDirectory( pVolume->pDirEntry, hEvent)))) {
            EXITNOTIFY(pVolume);
            break;
        } 
        EXITNOTIFY(pVolume);
        pVolume = pVolume->pNextVolume;
    }
    LeaveCriticalSection( &g_csMain);
    return hNotify;
}


inline BOOL IsValidData(HANDLE h, DWORD dwSig)
{
    BOOL bRet = TRUE;
    NOTHANDLEENTRY *pHandle = (NOTHANDLEENTRY *)h;
    if (!h || (h == INVALID_HANDLE_VALUE)) {
        bRet = FALSE;
    }
    if (bRet) {
        __try {
            if (pHandle->dwSig != dwSig) 
                bRet = FALSE;
        } __except(EXCEPTION_EXECUTE_HANDLER) {
            bRet = FALSE;
        }
    }
    return bRet;
}

NOTDIRENTRY *CreateDirEntry(WCHAR *szName, HANDLE hVolume)
{
    NOTDIRENTRY *pDirEntry = new NOTDIRENTRY;
    if (!pDirEntry) { 
        return NULL;
    }   
    DWORD dwSize = (wcslen(szName)+1)*sizeof(WCHAR);
    pDirEntry->dwSig = NOT_DIR_SIG;
    pDirEntry->pChild = NULL;
    pDirEntry->pParent = NULL;
    pDirEntry->pNext = NULL;
    pDirEntry->pPrevious = NULL;
    pDirEntry->pHandles = NULL;
    pDirEntry->hVolume = hVolume;
    pDirEntry->pEvents = NULL;
    pDirEntry->szDirectory = new WCHAR[dwSize];
    if (pDirEntry->szDirectory) {
        memcpy( pDirEntry->szDirectory, szName, dwSize);
    }     
    return pDirEntry;
}   

HANDLE NotifyCreateVolume( WCHAR *szNotifyPoint)
{
    DWORD dwSize = (wcslen(szNotifyPoint)+1)*sizeof(WCHAR);
    NOTVOLENTRY *pVolume = new NOTVOLENTRY;
    if (!pVolume) { 
        return INVALID_HANDLE_VALUE;
    }   
    InitializeCriticalSection(&pVolume->cs);
    pVolume->dwSig = NOT_VOL_SIG;
    pVolume->pDirEntry = NULL;
    pVolume->szVolumeName = new WCHAR[dwSize];
    pVolume->pHandles = NULL;
    pVolume->pEvents = NULL;
    pVolume->pNextVolume = NULL;
    if (pVolume->szVolumeName) {
        memcpy( pVolume->szVolumeName, szNotifyPoint, dwSize);
    }   
#ifdef UNDER_CE    
    if (!g_hNotifyAPI) {
        InitializeCriticalSection( &g_csMain);
        g_hNotifyAPI = CreateAPISet("FNOT", ARRAY_SIZE(apfnFindNotify), (const PFNVOID * )apfnFindNotify, asigFindNotify);
        RegisterAPISet(g_hNotifyAPI, HT_FIND | REGISTER_APISET_TYPE);
    }
    EnterCriticalSection( &g_csMain);
    if (g_pRootVolume) {
        pVolume->pNextVolume = g_pRootVolume;
    }
    g_pRootVolume = pVolume;
    LeaveCriticalSection( &g_csMain);
#endif    
    return (HANDLE)pVolume;
}

void DeleteHandles(NOTHANDLEENTRY *pHandles)
{
    while(pHandles) {
        NOTHANDLEENTRY *pHandle;
        pHandle = pHandles;
        pHandles = pHandle->pNext;
        if (pHandle->szFileName)
            delete [] pHandle->szFileName;
        delete pHandle;
    }
}

void DeleteFileInfos(NOTEVENTENTRY *pEvent)
{
    while (pEvent->pFileInfo) {
        NOTFILEINFO *pFileInfo;
        pFileInfo = pEvent->pFileInfo;
        pEvent->pFileInfo = pFileInfo->pNext;
        delete [] pFileInfo->szFileName;
        delete pFileInfo;
    }
}

void DeleteEvents(NOTEVENTENTRY *pEvents)
{
    while(pEvents) {
        NOTEVENTENTRY *pEvent;
        pEvent = pEvents;
        DeleteFileInfos(pEvent);
        pEvents = pEvent->pNext;
#ifdef UNDER_CE        
        SetHandleOwner( pEvent->hEvent, GetCurrentProcess());
#endif        
//      NKDbgPrintfW( L"Deleting event %08X\r\n", pEvent->hEvent);
        CloseHandle( pEvent->hEvent);
        pEvent->hEvent = NULL;
        delete pEvent;
    }
}

void ClearEvents(NOTEVENTENTRY *pEvents)
{
    NOTEVENTENTRY *pEvent = pEvents;
    while(pEvent) {
        pEvent->pVolume = NULL;
        pEvent = pEvent->pNext;
    }
    AddFileToEvent( pEvents, 
                    L"\\", 
                    FILE_NOTIFY_CHANGE_DIR_NAME, 
                    FILE_ACTION_REMOVED);
    CheckEventOnPath(pEvents, TRUE, TRUE);
}


void DeleteNotDirEntry(NOTDIRENTRY *pNotify)
{
    pNotify->pParent = NULL; 
    while(pNotify) {
        DeleteHandles( pNotify->pHandles);
        ClearEvents( pNotify->pEvents);
        NOTDIRENTRY *pNext;
        if (pNotify->pChild) {
            DeleteNotDirEntry(pNotify->pChild);
        }
        pNext = pNotify->pNext;
        pNotify->pPrevious = NULL; 
        if (pNotify->szDirectory) {
            delete [] pNotify->szDirectory;
        }   
        delete pNotify;     
        pNotify = pNext;
    }   
}

#if 0
WCHAR g_szDumpPath[MAX_PATH];
void DumpDirEntry(NOTDIRENTRY *pNotify)
{
    pNotify->pParent = NULL; 
    while(pNotify) {
        if (!pNotify->bDepth) {
            wcscpy( g_szDumpPath, L"\\");
            wcscat( g_szDumpPath, pNotify->szDirectory);
        } else {
            wcscat(g_szDumpPath, L"\\");
            wcscat(g_szDumpPath, pNotify->szDirectory);
        }    
        if (pNotify->pChild) {
            DumpDirEntry(pNotify->pChild);
        }
        if (!pNotify->bDepth) {
//          NKDbgPrintfW( L"%s\r\n",szPath);
        }    
        pNotify = pNotify->pNext;
    }   
}
#endif

void NotifyDeleteVolume(HANDLE hVolume)
{
    NOTVOLENTRY *pVolume = (NOTVOLENTRY *)hVolume;
    if (pVolume) {
        ENTERNOTIFY(hVolume);
        if (pVolume->pDirEntry) {
#if 0        
            DumpDirEntry(pVolume->pDirEntry);
#endif            
            DeleteNotDirEntry( pVolume->pDirEntry);
        }   
        DeleteHandles(pVolume->pHandles);
        ClearEvents(pVolume->pEvents);
        EXITNOTIFY(hVolume);
        EnterCriticalSection( &g_csMain);
        if (g_pRootVolume == pVolume) {
            g_pRootVolume = pVolume->pNextVolume;
        } else {
            NOTVOLENTRY * pCurVolume = g_pRootVolume;
            while(pCurVolume) {
                if (pCurVolume->pNextVolume == pVolume) {
                    pCurVolume->pNextVolume = pVolume->pNextVolume;
                    break;
                }
                pCurVolume = pCurVolume->pNextVolume;
            }
        }    
        LeaveCriticalSection( &g_csMain);
        DeleteCriticalSection(&pVolume->cs);
        if (pVolume->szVolumeName) {
            delete [] pVolume->szVolumeName;
        }   
        delete pVolume;
    }
}


NOTDIRENTRY *InsertOrFindDirEntry(HANDLE hVolume,const WCHAR *szFullPath, WCHAR **pszFileName, BOOL bPath, BOOL bFind, BOOL *pbSubTree = NULL) 
{
    NOTVOLENTRY *pVolume = (NOTVOLENTRY *)hVolume;
    NOTDIRENTRY *pDirectory = pVolume->pDirEntry;
    WCHAR *szPath = NULL;
    while(*szFullPath && (*szFullPath == L'\\'))
        szFullPath++;
    szPath = new WCHAR[wcslen(szFullPath)+1];    
    if (!szPath) {
        return NULL;
    }   
    wcscpy( szPath, szFullPath);                
    WCHAR *szCurrent = szPath;
    NOTDIRENTRY *pParent = NULL;
    NOTDIRENTRY *pCurrent = NULL;
    if (pszFileName)
        *pszFileName = NULL;
    BYTE bDepth = 0;
    while(*szCurrent) {
        WCHAR *szTemp = szCurrent;
        while(*szTemp && (*szTemp != L'\\'))
            szTemp++;
        if (*szTemp || bPath) {                 
            if (*szTemp) {
                *szTemp = L'\0';
                szTemp++;
            } else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?