📄 device.c
字号:
// 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.//DWORDLoadFSDThread( 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 + -