⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devfile.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 <devload.h>
#include <console.h>
#include <errorrep.h>

#include "devmgrp.h"
#include "celogdev.h"
#include "devmgrif.h"
#include "devzones.h"

//
// This module contains PSL entry points for handling file I/O operations on 
// device drivers.
//

// This routine increments the refcount of an fsopendev_t as well as
// that of its associated device's fsdev_t.
void 
OpenAddRef(fsopendev_t *fsodev)
{
    InterlockedIncrement(&fsodev->dwOpenRefCnt);
    InterlockedIncrement(fsodev->lpdwDevRefCnt);
}

// This routine decrements the refcount of an fsopendev_t as well as
// that of its associated device's fsdev_t.
void 
OpenDelRef(fsopendev_t *fsodev)
{
    InterlockedDecrement(&fsodev->dwOpenRefCnt);
    InterlockedDecrement(fsodev->lpdwDevRefCnt);
}

//
// This routine opens a handle to a device based on its name.  The handle can be used
// to do I/O on the device using file operations.
//
HANDLE 
I_CreateDeviceHandle(LPCWSTR lpNew, NameSpaceType nameType, DWORD dwAccess, DWORD dwShareMode, HPROCESS hProc)
{
    HANDLE hDev = INVALID_HANDLE_VALUE;
    DWORD dwErrCode = ERROR_DEV_NOT_EXIST;
    fsopendev_t *lpopendev;
    fsdev_t *lpdev;
    LPEXCEPTION_POINTERS pep;

    DEBUGCHK((dwAccess & DEVACCESS_BUSNAMESPACE) == 0); // this access bit should never be set externally

    EnterCriticalSection(&g_devcs);
    __try {
        // look up the device
        lpdev = FindDeviceByName(lpNew, nameType);

        // validate the name type against the capabilities of the driver
        if(lpdev != NULL && nameType == NtBus) {
            if((lpdev->wFlags & DF_ENABLE_BUSNAMES) == 0) {
                // don't allow accesses to the $bus namespace -- the driver needs to advertise
                // the DMCLASS_PROTECTEDBUSNAMESPACE interface first.
                DEBUGMSG(ZONE_WARNING, (_T("DEVICE!I_CreateDeviceHandle: can't open '%s' because the driver doesn't advertise '%s'\r\n"),
                    lpNew, DMCLASS_PROTECTEDBUSNAMESPACE));
                lpdev = NULL;
            } else {
                // notify the driver that its handle is being opened using a protected namespace
                dwAccess |= DEVACCESS_BUSNAMESPACE;
            }
        }

        // did we find the device?
        if(lpdev != NULL) {
            if (!(lpopendev = LocalAlloc(LPTR,sizeof(fsopendev_t)))) {
                dwErrCode = ERROR_OUTOFMEMORY;
                goto errret;
            }
            lpopendev->lpDev = lpdev;
            lpopendev->lpdwDevRefCnt = &lpdev->dwRefCnt;
            LeaveCriticalSection(&g_devcs);
            SetLastError(ERROR_SUCCESS);
            lpopendev->dwOpenData = lpdev->fnOpen(lpdev->dwData,dwAccess,dwShareMode);
            if(!lpopendev->dwOpenData) {
                dwErrCode = GetLastError();
                if(dwErrCode == ERROR_SUCCESS) {
                    // driver didn't fill it in, use a default
                    dwErrCode = ERROR_OPEN_FAILED;
                }
            }
            EnterCriticalSection(&g_devcs);
            if ((!FindDeviceByHandle(lpdev)) || (!lpopendev->dwOpenData)) {
                LocalFree(lpopendev);
                // Don't set an error code, the driver should have done that.
                goto errret;
            }
            lpopendev->hProc = hProc;
            if (!(hDev = CreateAPIHandle(g_hDevFileApiHandle, lpopendev))) {
                hDev = INVALID_HANDLE_VALUE;
                dwErrCode = ERROR_OUTOFMEMORY;
                LocalFree(lpopendev);
                goto errret;
            }
            // OK, we managed to create the handle
            dwErrCode = 0;
            lpopendev->KHandle = hDev;
            lpopendev->nextptr = g_lpOpenDevs;
            g_lpOpenDevs = lpopendev;
        }
errret:
        if( dwErrCode ) {
            SetLastError( dwErrCode );
            // This debugmsg occurs too frequently on a system without a sound device (eg, CEPC)
            DEBUGMSG(0, (TEXT("ERROR (devfile.c:DM_CreateDeviceHandle): %s, %d\r\n"), lpNew, dwErrCode));
        }
        
    } 
    __except(pep = GetExceptionInformation(), ReportFault(pep,0), EXCEPTION_EXECUTE_HANDLER) {
        SetLastError(ERROR_INVALID_PARAMETER);
    }
    LeaveCriticalSection(&g_devcs);
    
    return hDev;
}

// When an application calls CreateFile() on a device driver using the legacy 
// name format (e.g., "COM1:"), filesys calls this API to set up an open file 
// object.  This routine looks up the device, calls its open entry point, creates
// an fsopendev_t structure to maintains the open handle's state, and wraps 
// the structure using a call to CreateAPIHandle().  This is the value it
// passes back to filesys.  On failure, the value is INVALID_HANDLE_VALUE and
// the system "last error" value is set with more information.  This routine
// assumes that len == 5 and lpnew[4] == ':'.
HANDLE 
DM_CreateDeviceHandle(LPCWSTR lpNew, DWORD dwAccess, DWORD dwShareMode, HPROCESS hProc)
{
    HANDLE hDev;
    DWORD dwErrCode = ERROR_SUCCESS;
    WCHAR szDeviceName[MAXDEVICENAME + 1];

    if(PSLGetCallerTrust() != OEM_CERTIFY_TRUST) {
        // untrusted caller can't set the auto-deregistered flag
        SetLastError(ERROR_ACCESS_DENIED);
        return INVALID_HANDLE_VALUE;
    }
    
    if(lpNew == NULL) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return INVALID_HANDLE_VALUE;
    }

    // copy the device name
    szDeviceName[ARRAYSIZE(szDeviceName) - 1] = 0; // Intialize last as terminate.
    __try {
        wcsncpy(szDeviceName, lpNew, ARRAYSIZE(szDeviceName));
        if(szDeviceName[ARRAYSIZE(szDeviceName) - 1] != 0) { // If there is no terminate, device name is too long. return error.
            dwErrCode = ERROR_INVALID_PARAMETER;
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        dwErrCode = ERROR_INVALID_PARAMETER;
    }
    if(dwErrCode != ERROR_SUCCESS) {
        SetLastError(dwErrCode);
        return INVALID_HANDLE_VALUE;
    }

    hDev = I_CreateDeviceHandle(szDeviceName, NtLegacy, dwAccess, dwShareMode, hProc);
   
    return hDev;
}

// This routine decrements the use count of an fsopendev_t structure 
// allocated by CreateDeviceHandle().  First it calls the associated
// driver's Close entry point.  If the refcount is zero, the
// structure is freed immediately.  If not, a thread is executing code
// in the driver using this handle; the fsopendev_t is put on the 
// "dying opens" queue to be freed later.
BOOL 
DM_DevCloseFileHandle(fsopendev_t *fsodev)
{
    BOOL retval;
    DWORD dwStatus = ERROR_SUCCESS;
    fsopendev_t *fsTrav;
    fsdev_t *lpdev;
    LPEXCEPTION_POINTERS pep;
    
    EnterCriticalSection(&g_devcs);

    // look for the device file handle in the list        
    if (g_lpOpenDevs == fsodev)
        g_lpOpenDevs = fsodev->nextptr;
    else {
        fsTrav = g_lpOpenDevs;
        while (fsTrav != NULL && fsTrav->nextptr != fsodev) {
            fsTrav = fsTrav->nextptr;
        }
        if (fsTrav != NULL) {
            fsTrav->nextptr = fsodev->nextptr;
        } else {
            DEBUGMSG(ZONE_WARNING, (TEXT("DM_DevCloseFileHandle: fsodev (0x%X) not in DEVICE.EXE list\r\n"), fsodev));
            dwStatus = ERROR_INVALID_HANDLE;
        }
    }

    // did we find the handle?
    if(dwStatus == ERROR_SUCCESS) {
        if (lpdev = fsodev->lpDev) {
            if(lpdev->fnPreClose != NULL) {
                // increment reference counts to make sure that fnDeinit is not called before
                // fnPreClose -- this guarantees that the context handle passed to fnPreClose
                // is valid.
                OpenAddRef(fsodev);

                LeaveCriticalSection(&g_devcs);
                __try {
                    lpdev->fnPreClose(fsodev->dwOpenData);
                }
                __except(pep = GetExceptionInformation(), ReportFault(pep,0), EXCEPTION_EXECUTE_HANDLER) {
                    DEBUGMSG(ZONE_WARNING, (_T("DM_DevCloseFileHandle: exception calling pre-close entry point\r\n")));
                }
                EnterCriticalSection(&g_devcs);

                // decrement reference counts if we incremented it before preClose
                if(lpdev->fnPreClose != NULL) {
                    OpenDelRef(fsodev);
                }
            } else {
                LeaveCriticalSection(&g_devcs);
                __try {
                    lpdev->fnClose(fsodev->dwOpenData);
                }
                __except(pep = GetExceptionInformation(), ReportFault(pep,0), EXCEPTION_EXECUTE_HANDLER) {
                    DEBUGMSG(ZONE_WARNING, (_T("DM_DevCloseFileHandle: exception calling close entry point\r\n")));
                }
                EnterCriticalSection(&g_devcs);
            }
        }
        
        if (fsodev->dwOpenRefCnt) {
            fsodev->nextptr = g_lpDyingOpens;
            g_lpDyingOpens = fsodev;
            SetEvent(g_hCleanEvt);
        } else {
            lpdev = fsodev->lpDev;
            if(lpdev != NULL && lpdev->fnPreClose != NULL) {
                OpenAddRef(fsodev);
                LeaveCriticalSection(&g_devcs);
                __try {
                    lpdev->fnClose(fsodev->dwOpenData);
                }
                __except(pep = GetExceptionInformation(), ReportFault(pep,0), EXCEPTION_EXECUTE_HANDLER) {
                    DEBUGMSG(ZONE_WARNING, (_T("DM_DevCloseFileHandle: exception calling final close entry point\r\n")));
                }
                EnterCriticalSection(&g_devcs);
                OpenDelRef(fsodev);
            }
            LocalFree(fsodev);
        }
    } 
    
    LeaveCriticalSection(&g_devcs);

    if(dwStatus == ERROR_SUCCESS) {
        retval = TRUE;
    } else {
        SetLastError(dwStatus);
        retval = FALSE;

⌨️ 快捷键说明

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