📄 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_NT
void 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
BOOL
WINAPI
SetPriorityClass(
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 + -