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

📄 device.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
            
            // Until this problem gets fixed in the loader, we can just "predict"
            // when this will happen and do an extra FreeLibrary on FSDMGR.DLL. -JTP

            //if (fInitEx && pfsd->hFSDLibEx)
            //    FreeLibrary(hFSDLib);   // perform an "extra" FreeLibrary

            DEBUGMSG(ZONE_FSD,(TEXT("DEVICE!GetFSD found existing instance (%x)\n"), pfsd));
            return pfsd;
        }
        pfsd = pfsd->next;
    }

    //
    // Remember this newly loaded file system driver dll
    //
    pfsd = LocalAlloc(LPTR, sizeof(fsd_t));
    if (pfsd) {
        pfsd->hFSDLib = hFSDLib;
        if (!fInitEx) {
            pfsd->pfnFSDInit =
                (pInitFn)GetProcAddress(pfsd->hFSDLib, L"FSD_Init");
            pfsd->pfnFSDDeinit =
                (pDeinitFn)GetProcAddress(pfsd->hFSDLib, L"FSD_Deinit");
        }
        //
        // Link it into the global list
        //
        pfsd->next = g_lpFSDChain;
        g_lpFSDChain = pfsd;
    }
    else {
        FreeLibrary(hFSDLib);   // if we don't have enough memory, free the library
        DEBUGMSG(TRUE,(TEXT("DEVICE!GetFSD freed 0x%08x (ran out of memory)\n"), hFSDLib));
    }

    DEBUGMSG(ZONE_FSD,(TEXT("DEVICE!GetFSD created new instance (%x)\n"), pfsd));
    return pfsd;
}


#define DEVICE_NAME_SIZE 6  // i.e. "COM1:" (includes space for 0 terminator)

void FormatDeviceName(LPWSTR lpszName, fsdev_t * lpdev)
{
    memcpy(lpszName, lpdev->type, sizeof(lpdev->type));
    lpszName[sizeof(lpdev->type)/sizeof(WCHAR)+0] = (WCHAR)(L'0' + lpdev->index);
    lpszName[sizeof(lpdev->type)/sizeof(WCHAR)+1] = L':';
    lpszName[sizeof(lpdev->type)/sizeof(WCHAR)+2] = 0;
}

//
// Context structure FS_LoadFSD passes to LoadFSDThread
//
typedef struct _FSD_LOAD_CONTEXT {
    HANDLE hDevice;
    LPWSTR lpFSDName;
} FSD_LOAD_CONTEXT, * PFSD_LOAD_CONTEXT;

//
// LoadFSDThread - Function to perform the actual work of FS_LoadFSD in case
// FSD displays a dialog requiring a user response.
//
DWORD
LoadFSDThread(
    PFSD_LOAD_CONTEXT pContext
    )
{
	fsdev_t *lpdev;
    pfsd_t pfsd;
    lpdev = (fsdev_t *)pContext->hDevice;

    DEBUGMSG(ZONE_FSD,(TEXT("DEVICE!LoadFSDThread(0x%x, %s)\n"), lpdev, pContext->lpFSDName));

    EnterCriticalSection(&g_devcs);
    //
    // Try to load the FSD DLL for this device now.
    //
    lpdev->pfsd = pfsd = GetFSD(pContext->lpFSDName, FALSE);
    if (pfsd) {
        WCHAR wsDev[DEVICE_NAME_SIZE];
        FormatDeviceName(wsDev, lpdev);

        // We're ready to call the FSD now, and we want to release device.exe's
        // global critical section before doing so, but lest another driver using
        // the same FSD try to unload in the meantime, we must pre-increment
        // the FSD's ref count (cFSDDevices) beforehand, to prevent the FSD getting
        // unloaded out from under us.

        pfsd->cFSDDevices++;
        LeaveCriticalSection(&g_devcs);
        if (pfsd->pfnFSDInit)
            lpdev->dwFSDData = pfsd->pfnFSDInit((DWORD)wsDev);
        else if (pfsd->pfnFSDInitEx)
            lpdev->dwFSDData = pfsd->pfnFSDInitEx(pfsd->hFSDLibEx, wsDev, NULL);
        EnterCriticalSection(&g_devcs);

        // dwFSDData will be zero if the mount failed, and it will be
        // ODD if pfnFSDInit simply remounted an existing volume, so in both those
        // cases, we must back off the increment we applied to the FSD's ref count above.

        if (lpdev->dwFSDData == 0 || (lpdev->dwFSDData & 0x1))
            pfsd->cFSDDevices--;    // either the mount failed or it was actually a remount
        
        if (lpdev->dwFSDData == 0) {
            DoFreeFSD(pfsd);
            lpdev->pfsd = pfsd = NULL;
        }
    }

    // Clear DEVFLAGS_FSD_NEEDTOWAIT before releasing g_devcs to avoid unnecessary context switching
    lpdev->wFlags &= ~DEVFLAGS_FSD_NEEDTOWAIT;
    LeaveCriticalSection(&g_devcs);

    LocalFree(pContext->lpFSDName);
    LocalFree(pContext);
    DEBUGMSG(ZONE_FSD,(TEXT("DEVICE!LoadFSDThread: done\n")));
    return 0;
}

//
//  @func   BOOL | LoadFSD | Load a file system driver
//  @parm   HANDLE | hDevice | handle to registered device, from RegisterDevice
//  @parm   LPCWSTR | lpFSDName | Name of file system driver DLL to load
//  @rdesc  Returns TRUE for success, FALSE for failure
//  @comm   LoadFSD is used by a device driver to load its associated file
//                  system driver (e.g. ATADISK.DLL loads FATFS.DLL)
//                  An example would be:<nl>
//                      <tab>LoadFSD(h1, FSDName);<nl>
//                      where h1 is the handle returned by RegisterDevice
//                      and FSDName points to the name of the FSD DLL.
//
BOOL FS_LoadFSD(HANDLE hDevice, LPCWSTR lpFSDName)
{
    return FS_LoadFSDEx(hDevice, lpFSDName, LOADFSD_ASYNCH);
}


//
//  @func   BOOL | LoadFSDEx | Load a file system driver synch or asynch
//  @parm   HANDLE | hDevice | handle to registered device, from RegisterDevice
//  @parm   LPCWSTR | lpFSDName | Name of file system driver DLL to load
//  @parm	DWORD | dwFlag | indicates synchronous or asynchronous load of file system 
//  @rdesc  Returns TRUE for success, FALSE for failure
//  @comm   LoadFSDEx is used by a device driver to load its associated file
//                  system driver (e.g. ATADISK.DLL loads FATFS.DLL)
//                  An example would be:<nl>
//                      <tab>LoadFSDEx(h1, FSDName, Flag);<nl>
//                      where h1 is the handle returned by RegisterDevice
//                      and FSDName points to the name of the FSD DLL.
//						and Flag is one of the following:<nl>
//						<tab>LOADFSD_ASYNCH creates a thread to load the requested DLL<nl>
//						<tab>LOADFSD_SYNCH waits for the requested DLL to load before continuing<nl>
//
BOOL FS_LoadFSDEx(HANDLE hDevice, LPCWSTR lpFSDName, DWORD dwFlag)
{
    HANDLE hThd;
    PFSD_LOAD_CONTEXT pContext;
    fsdev_t *lpdev = (fsdev_t *)hDevice;

    pContext = LocalAlloc(LPTR, sizeof(FSD_LOAD_CONTEXT));
    if (pContext == NULL) {
        return FALSE;
    }

    pContext->lpFSDName = LocalAlloc(LPTR,
                                   (_tcslen(lpFSDName) + 1) * sizeof(TCHAR));
    if (pContext->lpFSDName == NULL) {
        LocalFree(pContext);
        return FALSE;
    }

    wcscpy(pContext->lpFSDName, lpFSDName);
    pContext->hDevice = hDevice;
    lpdev->wFlags |= DEVFLAGS_FSD_NEEDTOWAIT;

    switch(dwFlag)
    	{
    	case LOADFSD_SYNCH:
    		{
    		LoadFSDThread(pContext);
			hThd = NULL;
			return TRUE;
			break;
    		}
    	case LOADFSD_ASYNCH:
    	default:
    		{

		    hThd = CreateThread(NULL, 0,
                     (LPTHREAD_START_ROUTINE)&LoadFSDThread,
                     (LPVOID) pContext, 0, NULL);
    		if (hThd != NULL) 
    			{
        		CloseHandle(hThd);
        		return TRUE;
    			}
    		break;
    		}
    	}

    lpdev->wFlags &= ~DEVFLAGS_FSD_NEEDTOWAIT;
    LocalFree(pContext->lpFSDName);
    LocalFree(pContext);
    return FALSE;
}


//
//  @func   BOOL | CeResyncFilesys | Cause a file system driver to remount a device because of media change.
//  @parm   HANDLE | hDevice | handle to registered device from RegisterDevice
//  @rdesc  Returns TRUE for success, FALSE for failure
//  @comm   CeResyncFilesys is used by a device driver to indicate to its associated file
//                  system driver that a new volume/media has been inserted. The handle can be retrieved from
//                  the device's active key in the registry or from the p_hDevice field of the POST_INIT_BUF
//                  structure passed to the post-initialization IOCTL.
//                  
//
BOOL FS_CeResyncFilesys(HANDLE hDevice)
{
    fsdev_t *lpdev;
    pfsd_t pfsd;
    WCHAR wsDev[DEVICE_NAME_SIZE];
    BOOL bDeinit;

    lpdev = (fsdev_t *)hDevice;
    if (!IsValidDevice(lpdev)) {
        DEBUGMSG(ZONE_ERROR,(L"DEVICE: CeResyncFilesys - invalid handle\n"));
        return FALSE;   // Invalid device handle
    }

    pfsd = lpdev->pfsd;
    if (pfsd == NULL) {
        DEBUGMSG(ZONE_ERROR, (L"DEVICE: CeResyncFilesys - No associated FSD\n"));
        return FALSE;   // No associated FSD
    }

    InterlockedIncrement(&lpdev->dwRefCnt);

    bDeinit = FALSE;
    if (pfsd->pfnFSDDeinit)
        bDeinit = pfsd->pfnFSDDeinit(lpdev->dwFSDData);
    else if (pfsd->pfnFSDDeinitEx)
        bDeinit = pfsd->pfnFSDDeinitEx(lpdev->dwFSDData);
    else{ 
        DEBUGMSG(ZONE_ERROR, (L"DEVICE: CeResyncFilesys - No FSDDeinit\n"));
        goto fcrf_fail;
    }

    FormatDeviceName(wsDev, lpdev);

    if (pfsd->pfnFSDInit)
        lpdev->dwFSDData = pfsd->pfnFSDInit((DWORD)wsDev);
    else if (pfsd->pfnFSDInitEx)
        lpdev->dwFSDData = pfsd->pfnFSDInitEx(pfsd->hFSDLibEx, wsDev, NULL);
    else {
        DEBUGMSG(ZONE_ERROR, (L"DEVICE: CeResyncFilesys - No FSDInit\n"));
        goto fcrf_fail;
    }

    InterlockedDecrement(&lpdev->dwRefCnt);
    return TRUE;

fcrf_fail:
    if (bDeinit)
        lpdev->pfsd->cFSDDevices--;
    InterlockedDecrement(&lpdev->dwRefCnt);
    return FALSE;

}


void FS_PowerAllDevices(BOOL bOff) {
	fsdev_t *lpdev;

    //
    // Power on the PCMCIA system before powering on devices
    //
    if (!bOff && pfnSystemPower)
	    pfnSystemPower(bOff);

    if (bOff) {
        //
        // Notify drivers of power off in reverse order from their LoadOrder
        //
        for (lpdev = (fsdev_t *)g_DevChain.Blink;
             lpdev != (fsdev_t *)&g_DevChain;
             lpdev = (fsdev_t *)lpdev->list.Blink) {
			if (lpdev->PwrOn) {
				if (lpdev->fnPowerdn) {
					ENTER_INSTRUM {
	                lpdev->fnPowerdn(lpdev->dwData);
					} EXIT_INSTRUM_POWERDOWN;
				}
				lpdev->PwrOn = FALSE;
			}
		}
	} else {
        //
        // Notify drivers of power on according to their LoadOrder
        //
        for (lpdev = (fsdev_t *)g_DevChain.Flink;
             lpdev != (fsdev_t *)&g_DevChain;
             lpdev = (fsdev_t *)lpdev->list.Flink) {
			if (!lpdev->PwrOn) {
				if (lpdev->fnPowerup) {
					ENTER_INSTRUM {
					lpdev->fnPowerup(lpdev->dwData);
					} EXIT_INSTRUM_POWERUP;
				}
				lpdev->PwrOn = TRUE;
			}
		}
	}

    //
    // Power off the PCMCIA system after powering off devices
    //
    if (bOff && pfnSystemPower)
	    pfnSystemPower(bOff);
}

BOOL FS_GetDeviceByIndex(DWORD dwIndex, LPWIN32_FIND_DATA lpFindFileData) {
	fsdev_t *lpdev;
	BOOL bRet = FALSE;
	ENTER_DEVICE_FUNCTION {
		lpdev = (fsdev_t *)g_DevChain.Flink;
		while (dwIndex && lpdev != (fsdev_t *)&g_DevChain) {
			dwIndex--;
			lpdev = (fsdev_t *)lpdev->list.Flink;
		}
		if (lpdev != (fsdev_t *)&g_DevChain) {
			lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
		    *(__int64 *)&lpFindFileData->ftCreationTime = 0;
		    *(__int64 *)&lpFindFileData->ftLastAccessTime = 0;
		    *(__int64 *)&lpFindFileData->ftLastWriteTime = 0;
		    lpFindFileData->nFileSizeHigh = 0;
		    lpFindFileData->nFileSizeLow = 0;
		    lpFindFileData->dwOID = 0xffffffff;
            FormatDeviceName(lpFindFileData->cFileName, lpdev);
		    bRet = TRUE;
		}
	} EXIT_DEVICE_FUNCTION;
	return bRet;
}

// assumes len == 5 and lpnew[4] == ':'
HANDLE FS_CreateDeviceHandle(LPCWSTR lpNew, DWORD dwAccess, DWORD dwShareMode, HPROCESS hProc)
{
	HANDLE hDev = INVALID_HANDLE_VALUE;
    DWORD dwErrCode = ERROR_DEV_NOT_EXIST;
	fsopendev_t *lpopendev;
	fsdev_t *lpdev;
    
	ENTER_DEVICE_FUNCTION {
        for (lpdev = (fsdev_t *)g_DevChain.Flink;
             lpdev != (fsdev_t *)&g_DevChain;
             lpdev = (fsdev_t *)lpdev->list.Flink) {
	        if (!_wcsnicmp(lpNew,lpdev->type,
                     sizeof(lpdev->type)/sizeof(WCHAR))) {
				if ((DWORD)(lpNew[3]-L'0') == lpdev->index) {
					if (!(lpopendev = LocalAlloc(LPTR,sizeof(fsopendev_t)))) {
                        dwErrCode = ERROR_OUTOFMEMORY;
						goto errret;
					}
					lpopendev->lpDev = lpdev;
					lpopendev->lpdwDevRefCnt = &lpdev->dwRefCnt;
                    LeaveCriticalSection(&g_devcs);
					ENTER_INSTRUM {
					lpopendev->dwOpenData = lpdev->fnOpen(lpdev->dwData,dwAccess,dwShareMode);
					} EXIT_INSTRUM_OPEN;
                    EnterCriticalSection(&g_devcs);
					if ((!IsValidDevice(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;
					break;
				}
			}
		}
errret:
        if( dwErrCode ) {
            SetLastError( dwErrCode );
            // This debugmsg occurs too frequently on a system without a sound device (eg, CEPC)
            DEBUGMSG(0, (TEXT("ERROR (device.c:FS_CreateDeviceHandle): %s, %d\r\n"), lpNew, dwErrCode));
        }
        
	} EXIT_DEVICE_FUNCTION;
	return hDev;
}

BOOL FS_DevCloseFileHandle(fsopendev_t *fsodev)
{
	BOOL retval = FALSE;
	fsopendev_t *fsTrav;
    fsdev_t *lpdev;

	ENTER_DEVICE_FUNCTION {
		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 {

⌨️ 快捷键说明

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