📄 device.c
字号:
DEBUGMSG(1, (TEXT("WARNING (device.c): fsodev (0x%X) not in DEVICE.EXE list\r\n"), fsodev)); } } if (lpdev = fsodev->lpDev) { LeaveCriticalSection(&g_devcs); ENTER_INSTRUM { lpdev->fnClose(fsodev->dwOpenData); } EXIT_INSTRUM_CLOSE; EnterCriticalSection(&g_devcs); } if (fsodev->dwOpenRefCnt) { fsodev->nextptr = g_lpDyingOpens; g_lpDyingOpens = fsodev; SetEvent(g_hCleanEvt); } else { LocalFree(fsodev); } retval = TRUE; } EXIT_DEVICE_FUNCTION; return retval;}void OpenAddRef(fsopendev_t *fsodev){ InterlockedIncrement(&fsodev->dwOpenRefCnt); InterlockedIncrement(fsodev->lpdwDevRefCnt);}void OpenDelRef(fsopendev_t *fsodev){ InterlockedDecrement(&fsodev->dwOpenRefCnt); InterlockedDecrement(fsodev->lpdwDevRefCnt);}BOOL FS_DevReadFile(fsopendev_t *fsodev, LPVOID buffer, DWORD nBytesToRead, LPDWORD lpNumBytesRead, LPOVERLAPPED lpOverlapped){ BOOL retval = FALSE; DWORD dodec = 0; __try { if (!fsodev->lpDev) SetLastError(ERROR_GEN_FAILURE); else { OpenAddRef(fsodev); dodec = 1; ENTER_INSTRUM { *lpNumBytesRead = fsodev->lpDev->fnRead(fsodev->dwOpenData,buffer,nBytesToRead); } EXIT_INSTRUM_READ; OpenDelRef(fsodev); dodec = 0; if (*lpNumBytesRead == 0xffffffff) { retval = FALSE; *lpNumBytesRead = 0; } else retval = TRUE; } } __except (EXCEPTION_EXECUTE_HANDLER) { if (dodec) OpenDelRef(fsodev); SetLastError(ERROR_INVALID_PARAMETER); } return retval;}BOOL FS_DevWriteFile(fsopendev_t *fsodev, LPCVOID buffer, DWORD nBytesToWrite, LPDWORD lpNumBytesWritten, LPOVERLAPPED lpOverlapped){ BOOL retval = FALSE; DWORD dodec = 0; __try { if (!fsodev->lpDev) SetLastError(ERROR_GEN_FAILURE); else { OpenAddRef(fsodev); dodec = 1; ENTER_INSTRUM { *lpNumBytesWritten = fsodev->lpDev->fnWrite(fsodev->dwOpenData,buffer,nBytesToWrite); } EXIT_INSTRUM_WRITE; OpenDelRef(fsodev); dodec = 0; if (*lpNumBytesWritten == 0xffffffff) *lpNumBytesWritten = 0; else retval = TRUE; } } __except (EXCEPTION_EXECUTE_HANDLER) { if (dodec) OpenDelRef(fsodev); SetLastError(ERROR_INVALID_PARAMETER); } return retval;}DWORD FS_DevSetFilePointer(fsopendev_t *fsodev, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { DWORD retval = 0xffffffff; DWORD dodec = 0; __try { if (!fsodev->lpDev) SetLastError(ERROR_GEN_FAILURE); else { OpenAddRef(fsodev); dodec = 1; ENTER_INSTRUM { retval = fsodev->lpDev->fnSeek(fsodev->dwOpenData,lDistanceToMove,dwMoveMethod); } EXIT_INSTRUM_SEEK; OpenDelRef(fsodev); dodec = 0; } } __except (EXCEPTION_EXECUTE_HANDLER) { if (dodec) OpenDelRef(fsodev); SetLastError(ERROR_INVALID_PARAMETER); } return retval;}BOOL FS_DevDeviceIoControl(fsopendev_t *fsodev, DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { BOOL retval = FALSE; DWORD dodec = 0; __try { if (!fsodev->lpDev) SetLastError(ERROR_GEN_FAILURE); else { if(dwIoControlCode == IOCTL_DEVICE_AUTODEREGISTER) { // NOTE: This IOCTL is here to avoid a deadlock between (a) a DllMain calling // DeregisterDevice (and hence trying to acquire the device CS *after* the // loader CS and (b) Various other paths in this file where we acquire the // device CS *before* the Loader CS (by calling LoadLib, FreeLib etc). // See WinCE#4165. Hence this code path must NOT acquire the device CS!! DEBUGMSG(ZONE_DYING, (L"FS_DevDeviceIoControl:IOCTL_DEVICE_AUTODEREGISTER. lpdev=%x\r\n", fsodev->lpDev)); fsodev->lpDev->wFlags |= DEVFLAGS_AUTO_DEREGISTER; retval = TRUE; // signal the main device (dying-devs-handler) thread SetEvent(g_hCleanEvt); } else { OpenAddRef(fsodev); dodec = 1; ENTER_INSTRUM { retval = fsodev->lpDev->fnControl(fsodev->dwOpenData,dwIoControlCode,lpInBuf,nInBufSize,lpOutBuf,nOutBufSize,lpBytesReturned); } EXIT_INSTRUM_IOCONTROL; OpenDelRef(fsodev); dodec = 0; } } } __except (EXCEPTION_EXECUTE_HANDLER) { if (dodec) OpenDelRef(fsodev); SetLastError(ERROR_INVALID_PARAMETER); } return retval;}DWORD FS_DevGetFileSize(fsopendev_t *fsodev, LPDWORD lpFileSizeHigh) { SetLastError(ERROR_INVALID_FUNCTION); return 0xffffffff;}BOOL FS_DevGetFileInformationByHandle(fsopendev_t *fsodev, LPBY_HANDLE_FILE_INFORMATION lpFileInfo) { SetLastError(ERROR_INVALID_FUNCTION); return FALSE;}BOOL FS_DevFlushFileBuffers(fsopendev_t *fsodev) { SetLastError(ERROR_INVALID_FUNCTION); return FALSE;}BOOL FS_DevGetFileTime(fsopendev_t *fsodev, LPFILETIME lpCreation, LPFILETIME lpLastAccess, LPFILETIME lpLastWrite) { SetLastError(ERROR_INVALID_FUNCTION); return FALSE;}BOOL FS_DevSetFileTime(fsopendev_t *fsodev, CONST FILETIME *lpCreation, CONST FILETIME *lpLastAccess, CONST FILETIME *lpLastWrite) { SetLastError(ERROR_INVALID_FUNCTION); return FALSE;}BOOL FS_DevSetEndOfFile(fsopendev_t *fsodev) { SetLastError(ERROR_INVALID_FUNCTION); return FALSE;}static void DevPSLNotify (DWORD flags, HPROCESS proc, HTHREAD thread) { fsopendev_t *fsodev; int icalls, i; HANDLE h[20]; HANDLE *ph; DEVICE_PSL_NOTIFY pslPacket; EnterCriticalSection(&g_devcs); fsodev = g_lpOpenDevs; icalls = 0; while (fsodev) { if (fsodev->hProc == proc) ++icalls; fsodev = fsodev->nextptr; } if (icalls < sizeof(h) / sizeof(h[0])) ph = h; else ph = (HANDLE *)LocalAlloc (LMEM_FIXED, icalls * sizeof(HANDLE)); i = 0; fsodev = g_lpOpenDevs; while (fsodev && i < icalls) { if (fsodev->hProc == proc) ph[i++] = fsodev->KHandle; fsodev = fsodev->nextptr; } LeaveCriticalSection (&g_devcs); pslPacket.dwSize = sizeof(pslPacket); pslPacket.dwFlags = flags; pslPacket.hProc = proc; pslPacket.hThread = thread; for (i = 0 ; i < icalls ; ++i) DeviceIoControl (ph[i], IOCTL_PSL_NOTIFY, (LPVOID)&pslPacket, sizeof(pslPacket), NULL, 0, NULL, NULL); if (ph != h) LocalFree (ph);}void FS_DevProcNotify(DWORD flags, HPROCESS proc, HTHREAD thread) { switch (flags) {#ifndef TARGET_NT case DLL_PROCESS_EXITING: DevPSLNotify (flags, proc, thread); break; case DLL_SYSTEM_STARTED: // // Eventually we'll want to signal all drivers that the system has // initialized. For now do what's necessary. // DevloadPostInit(); break;#endif // TARGET_NT } return;}void FS_CloseAllDeviceHandles(HPROCESS proc) {#if TARGET_NT ENTER_DEVICE_FUNCTION {#endif fsopendev_t *fsodev = g_lpOpenDevs; while (fsodev) { if (fsodev->hProc == proc) {#if TARGET_NT FS_DevCloseFileHandle(fsodev);#else CloseHandle(fsodev->KHandle);#endif fsodev = g_lpOpenDevs; } else fsodev = fsodev->nextptr; }#if TARGET_NT } EXIT_DEVICE_FUNCTION;#endif}#ifndef TARGET_NTvoid InitOOMSettings(){ SYSTEM_INFO SysInfo; GetSystemInfo (&SysInfo); // Calling this will set up the initial critical memory handlers and // enable memory scavenging in the kernel SetOOMEvent (NULL, 30, 15, 0x4000 / SysInfo.dwPageSize, (0x2000 / SysInfo.dwPageSize) > 2 ? (0x2000 / SysInfo.dwPageSize) : 2); }void ProcessDyingOpens(void){ fsopendev_t *fsodev; fsopendev_t *fsodevprev; DEBUGMSG(ZONE_DYING, (L"Device: About to walk dying opens list\r\n")); EnterCriticalSection(&g_devcs); fsodevprev = fsodev = g_lpDyingOpens; while (fsodev) { if (fsodev->dwOpenRefCnt == 0) { // Unlink and free unreferenced open if (fsodev == g_lpDyingOpens) { g_lpDyingOpens = fsodev->nextptr; LocalFree(fsodev); fsodev = fsodevprev = g_lpDyingOpens; } else { fsodevprev->nextptr = fsodev->nextptr; LocalFree(fsodev); fsodev = fsodevprev->nextptr; } } else { fsodevprev = fsodev; fsodev = fsodev->nextptr; } } LeaveCriticalSection(&g_devcs);}int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nCmShow){ fsdev_t* lpdev; BOOL bFreedOne; if (IsAPIReady(SH_DEVMGR_APIS)) return 0; InitOOMSettings(); InitializeListHead(&g_DevChain); InitializeListHead(&g_DyingDevs); g_hCleanEvt = CreateEvent(0,0,0,0); g_hCleanDoneEvt = CreateEvent(0, 1, 1, 0); //manual reset, init state signalled g_hDevApiHandle = CreateAPISet("WFLD", NUM_FDEV_APIS, FDevApiMethods, FDevApiSigs); RegisterAPISet(g_hDevApiHandle, SH_DEVMGR_APIS); g_hDevFileApiHandle = CreateAPISet("W32D", NUM_FAPIS, DevFileApiMethods, DevFileApiSigs); RegisterAPISet(g_hDevFileApiHandle, HT_FILE | REGISTER_APISET_TYPE); InitializeCriticalSection(&g_devcs); SetPowerOffHandler((FARPROC)FS_PowerAllDevices); DevloadInit(); SignalStarted(_wtol(lpCmdLine)); while (1) { WaitForSingleObject(g_hCleanEvt, INFINITE); // check for auto-deregister devs first as they may end up queuing // themselves on the dying devs list do { EnterCriticalSection(&g_devcs); bFreedOne = FALSE; // walking the chain of *active* devs, looking for ALL that want to deregister // don't care about refcount. That's handled by deregister & the dying-devs list DEBUGMSG(ZONE_DYING, (L"Device: About to walk main list\r\n")); for (lpdev = (fsdev_t *)g_DevChain.Flink; lpdev != (fsdev_t *)&g_DevChain; lpdev = (fsdev_t *)(lpdev->list.Flink)) { if (lpdev->wFlags & DEVFLAGS_AUTO_DEREGISTER) { LeaveCriticalSection(&g_devcs); // don't remove from list. DeregisterDevice will do that DEBUGMSG(ZONE_DYING, (L"Device: FOUND auto-deregister lpdev=%x\r\n", lpdev)); FS_DeregisterDevice((HANDLE)lpdev); bFreedOne = TRUE; break; // break out of inner loop, because after letting go of critsec & // freeing lpdev, our loop traversal is not valid anymore. So start over } } if (lpdev == (fsdev_t *)&g_DevChain) { LeaveCriticalSection(&g_devcs); break; } } while (bFreedOne); // keep looping as long as we have something to do DEBUGMSG(ZONE_DYING, (L"Device: About to walk dying list\r\n")); while (!IsListEmpty(&g_DyingDevs)) { EnterCriticalSection(&g_devcs); bFreedOne = FALSE; // walk the chain of dying devs (already deregistered. just waiting to be unloaded) for (lpdev = (fsdev_t *)g_DyingDevs.Flink; lpdev != (fsdev_t *)&g_DyingDevs; lpdev = (fsdev_t *)lpdev->list.Flink) { if (!lpdev->dwRefCnt) { RemoveEntryList((PLIST_ENTRY)lpdev); LeaveCriticalSection(&g_devcs); DEBUGMSG(ZONE_DYING, (L"Device: FOUND dying dev lpdev=%x\r\n", lpdev)); DoFreeDevice(lpdev); bFreedOne = TRUE; break; // break out of inner loop, because after letting go of critsec & // freeing lpdev, our loop traversal is not valid anymore. So start over } } if (bFreedOne == FALSE) { // Couldn't free anyone LeaveCriticalSection(&g_devcs); Sleep(5000); // snooze, and try again... } } ProcessDyingOpens(); DEBUGMSG(ZONE_DYING, (TEXT("DEVICE: Setting CleanDoneEvt in WinMain.\r\n"))); SetEvent(g_hCleanDoneEvt); } return 1; // should not ever be reached}#else BOOLWINAPISetPriorityClass( HANDLE hProcess, DWORD dwPriorityClass );int wmain(int argc, wchar_t *argv){ SetPriorityClass(GetCurrentProcess(), 0x80 /*HIGH_PRIORITY_CLASS*/); InitializeCriticalSection(&g_devcs); g_hDevFileApiHandle = (HANDLE) 0x80002000; if (!proxy_init(8, 4096)) return 0; DevloadInit(); DevloadPostInit(); wait_for_exit_event(); return 1;}#endif // TARGET_NT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -