📄 device.c
字号:
pfsd1 = pfsd1->next;
}
// we should never get here
}
}
}
void DoFreeDevice(fsdev_t *lpdev)
{
EnterCriticalSection(&g_devcs);
if (lpdev->pfsd)
DoFreeFSD(lpdev->pfsd);
LeaveCriticalSection(&g_devcs);
FreeLibrary(lpdev->hLib);
LocalFree(lpdev);
}
void WaitForFSDs()
{
fsdev_t *lpdev;
restart:
EnterCriticalSection(&g_devcs);
for (lpdev = (fsdev_t *)g_DevChain.Flink;
lpdev != (fsdev_t *)&g_DevChain;
lpdev = (fsdev_t *)lpdev->list.Flink) {
// If the FSD hasn't finished init'ing yet, we must wait...
if (lpdev->wFlags & DEVFLAGS_FSD_NEEDTOWAIT) {
DEBUGMSG(1/*ZONE_FSD*/,(TEXT("DEVICE!WaitForFSDs: waiting for FSD to finish init'ing device 0x%x first...\r\n"), lpdev));
LeaveCriticalSection(&g_devcs);
Sleep(2000);
goto restart;
}
}
LeaveCriticalSection(&g_devcs);
}
void NotifyFSDs()
{
int n;
pfsd_t pfsd = g_lpFSDChain;
pfsd_t pfsd1;
EnterCriticalSection(&g_devcs);
while (pfsd) {
if (pfsd->pfnFSDDeinit && (n = pfsd->pfnFSDDeinit(0)) ||
pfsd->pfnFSDDeinitEx && (n = pfsd->pfnFSDDeinitEx(0))) {
DEBUGMSG(ZONE_FSD,(TEXT("DEVICE!NotifyFSDs: FSD unmounted %d devices (out of %d)\n"), n, pfsd->cFSDDevices));
pfsd->cFSDDevices -= n;
DEBUGMSG(pfsd->cFSDDevices < 0,(TEXT("DEVICE!NotifyFSDs: device count underflow! (%d)\n"), pfsd->cFSDDevices));
pfsd1 = pfsd;
pfsd = pfsd->next;
DoFreeFSD(pfsd1);
} else {
pfsd = pfsd->next;
}
}
LeaveCriticalSection(&g_devcs);
}
//
// IsValidDevice - function to check if passed in device handle is actually a
// valid registered device.
//
// Return TRUE if it is a valid registered device, FALSE otherwise.
//
BOOL
IsValidDevice(
fsdev_t * lpdev
)
{
fsdev_t * lpTrav;
for (lpTrav = (fsdev_t *)g_DevChain.Flink;
lpTrav != (fsdev_t *)&g_DevChain;
lpTrav = (fsdev_t *)(lpTrav->list.Flink)) {
if (lpTrav == lpdev) {
return TRUE;
}
}
return FALSE;
}
//
// Function to wait for the file system driver associated with the specified
// device to finish initializing before deregistering the device.
// (For instance when FATFS has a dialog up and the corresponding PC card is
// removed, the PCMCIA callback thread would get blocked until the dialog
// got dismissed. Now we spin up a thread so PCMCIA messages are not blocked.)
//
DWORD
WaitForFSDInitThread(
HANDLE hDevice
)
{
fsdev_t *lpdev = (fsdev_t *)hDevice;
while (1) {
EnterCriticalSection(&g_devcs);
if (!(lpdev->wFlags & DEVFLAGS_FSD_NEEDTOWAIT)) {
break;
}
LeaveCriticalSection(&g_devcs);
DEBUGMSG(1/*ZONE_FSD*/,
(TEXT("DEVICE!WaitForFSDInitThread: waiting for FSD to finish init'ing device 0x%x first...\n"), lpdev));
Sleep(2000);
}
LeaveCriticalSection(&g_devcs);
FS_DeregisterDevice(hDevice);
return 0;
}
// @func BOOL | DeregisterDevice | Deregister a registered device
// @parm HANDLE | hDevice | handle to registered device, from RegisterDevice
// @rdesc Returns TRUE for success, FALSE for failure
// @comm DeregisterDevice can be used if a device is removed from the system or
// is being shut down. An example would be:<nl>
// <tab>DeregisterDevice(h1);<nl>
// where h1 was returned from a call to RegisterDevice.
// @xref <f RegisterDevice> <l Overview.WinCE Device Drivers>
BOOL FS_DeregisterDevice(HANDLE hDevice)
{
fsdev_t *lpdev;
fsopendev_t *lpopen;
BOOL retval = FALSE;
HANDLE hThd;
restart:
ENTER_DEVICE_FUNCTION {
lpdev = (fsdev_t *)hDevice;
if (!IsValidDevice(lpdev)) {
goto errret;
}
// If an FSD hasn't finished init'ing yet, we should wait,
// because if it does eventually successfully init, then it
// will need to be de-init'ed as well.
if (lpdev->wFlags & DEVFLAGS_FSD_NEEDTOWAIT) {
DEBUGMSG(1/*ZONE_FSD*/,(TEXT("DEVICE!FS_DeregisterDevice: waiting for FSD to finish init'ing device 0x%x first...\n"), lpdev));
hThd = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)&WaitForFSDInitThread,
(LPVOID) hDevice, 0, NULL);
if (hThd != NULL) {
CloseHandle(hThd);
retval = TRUE;
goto errret;
} else {
//
// If we can't start a thread, then revert to polling.
//
LeaveCriticalSection(&g_devcs);
Sleep(2000);
goto restart;
}
}
lpopen = g_lpOpenDevs;
while (lpopen) {
if (lpopen->lpDev == lpdev)
lpopen->lpDev = 0;
lpopen = lpopen->nextptr;
}
RemoveEntryList((PLIST_ENTRY)lpdev);
if (lpdev->dwFSDData && lpdev->pfsd) {
pfsd_t pfsd = lpdev->pfsd;
if (pfsd->pfnFSDDeinit &&
pfsd->pfnFSDDeinit(lpdev->dwFSDData) ||
pfsd->pfnFSDDeinitEx &&
pfsd->pfnFSDDeinitEx(lpdev->dwFSDData) ||
pfsd->pfnFSDDeinit == NULL && pfsd->pfnFSDDeinitEx == NULL) {
pfsd->cFSDDevices--;
}
}
LeaveCriticalSection(&g_devcs);
ENTER_INSTRUM {
lpdev->fnDeinit(lpdev->dwData);
} EXIT_INSTRUM_DEINIT;
if ((!lpdev->dwRefCnt) && (!lpdev->pfsd)) {
DoFreeDevice(lpdev);
EnterCriticalSection(&g_devcs);
} else {
EnterCriticalSection(&g_devcs);
InsertTailList(&g_DyingDevs, (PLIST_ENTRY)lpdev);
DEBUGMSG(ZONE_DYING, (TEXT("DEVICE: About to Reset CleanDoneEvt.\r\n")));
ResetEvent(g_hCleanDoneEvt);
SetEvent(g_hCleanEvt);
}
retval = TRUE;
errret:
;
} EXIT_DEVICE_FUNCTION;
return retval;
}
//
// @func HANDLE | ActivateDevice | Register a device and add it to the active list under HKEY_LOCAL_MACHINE\Drivers\Active.
// @parm LPCWSTR | lpszDevKey | The driver's device key under HKEY_LOCAL_MACHINE\Drivers (for example "Drivers\PCMCIA\Modem")
// @parm DWORD | dwClientInfo | Instance information to be stored in the device's active key.
// @rdesc Returns a handle to a device, or 0 for failure. This handle should
// only be passed to DeactivateDevice
// @comm ActivateDevice will RegisterDevice the specified device and
// create an active key in HKEY_LOCAL_MACHINE\Drivers\Active for the new device.
// Also the device's creation is announced to the system via a
// WM_DEVICECHANGE message and through the application notification system.
//
// An example would be:<nl>
// <tab>hnd = ActivateDevice(lpszDevKey, dwClientInfo);<nl>
// where hnd is a HANDLE that can be used for DeactivateDevice<nl>
// lpszDevKey is the registry path in HKEY_LOCAL_MACHINE to the device
// driver's device key which has values that specify the driver name and
// device prefix.<nl>
// dwClientInfo is a DWORD value that will be stored in the device's active
// key.<nl>
// @xref <f DeactivateDevice> <f RegisterDevice> <f DeregisterDevice> <l Overview.WinCE Device Drivers>
//
HANDLE FS_ActivateDevice(
LPCWSTR lpszDevKey,
DWORD dwClientInfo
)
{
CARD_SOCKET_HANDLE hSock;
DEBUGMSG(1, (TEXT("DEVICE!ActivateDevice(%s, %d) entered\r\n"),
lpszDevKey, dwClientInfo));
hSock.uSocket = 0xff; // Not a PCMCIA device.
return StartOneDriver(
(LPWSTR)lpszDevKey,
NULL, // PnpID
MAX_LOAD_ORDER,
dwClientInfo,
hSock);
}
//
// Function to search through HLM\Drivers\Active for a matching device handle.
// Return TRUE if the device is found. The device's active registry path will be
// copied to the ActivePath parameter.
//
BOOL
FindActiveByHandle(
HANDLE hDevice,
LPTSTR ActivePath
)
{
DWORD Handle;
DWORD RegEnum;
DWORD status;
DWORD ValLen;
DWORD ValType;
LPTSTR RegPathPtr;
HKEY DevKey;
HKEY ActiveKey;
TCHAR DevNum[DEVNAME_LEN];
_tcscpy(ActivePath, s_ActiveKey);
status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
ActivePath,
0,
0,
&ActiveKey);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ACTIVE|ZONE_ERROR,
(TEXT("DEVICE!FindActiveByHandle: RegOpenKeyEx(%s) returned %d\r\n"),
ActivePath, status));
return FALSE;
}
RegEnum = 0;
while (1) {
ValLen = sizeof(DevNum)/sizeof(TCHAR);
status = RegEnumKeyEx(
ActiveKey,
RegEnum,
DevNum,
&ValLen,
NULL,
NULL,
NULL,
NULL);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ACTIVE|ZONE_ERROR,
(TEXT("DEVICE!FindActiveByHandle: RegEnumKeyEx() returned %d\r\n"),
status));
RegCloseKey(ActiveKey);
return FALSE;
}
status = RegOpenKeyEx(
ActiveKey,
DevNum,
0,
0,
&DevKey);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ACTIVE|ZONE_ERROR,
(TEXT("DEVICE!FindActiveByHandle: RegOpenKeyEx(%s) returned %d\r\n"),
DevNum, status));
goto fad_next;
}
//
// See if the handle value matches
//
ValLen = sizeof(Handle);
status = RegQueryValueEx(
DevKey,
DEVLOAD_HANDLE_VALNAME,
NULL,
&ValType,
(PUCHAR)&Handle,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ACTIVE|ZONE_ERROR,
(TEXT("DEVICE!FindActiveByHandle: RegQueryValueEx(%s\\Handle) returned %d\r\n"),
DevNum, status));
//
// We found an active device key with no handle value.
//
Handle = 0;
goto fad_next;
}
if (Handle == (DWORD)hDevice) {
//
// Format the registry path
//
RegPathPtr = ActivePath + _tcslen(ActivePath);
RegPathPtr[0] = (TCHAR)'\\';
RegPathPtr++;
_tcscpy(RegPathPtr, DevNum);
RegCloseKey(ActiveKey);
RegCloseKey(DevKey);
return TRUE;
}
fad_next:
RegCloseKey(DevKey);
RegEnum++;
} // while
} // FindActiveByHandle
//
// @func BOOL | DeactivateDevice | Deregister a registered device and remove
// it from the active list.
// @parm HANDLE | hDevice | handle to registered device, from ActivateDevice
// @rdesc Returns TRUE for success, FALSE for failure
// @comm DeactivateDevice will DeregisterDevice the specified device and
// delete the device's active key from HKEY_LOCAL_MACHINE\Drivers\Active.
// Also the device's removal is announced to the system via a
// WM_DEVICECHANGE message and through the application notification system.
// An example would be:<nl>
// <tab>DeactivateDevice(h1);<nl>
// where h1 was returned from a call to ActivateDevice.
// @xref <f ActivateDevice> <f RegisterDevice> <f DeregisterDevice> <l Overview.WinCE Device Drivers>
//
BOOL FS_DeactivateDevice(HANDLE hDevice)
{
TCHAR ActivePath[REG_PATH_LEN];
if (FindActiveByHandle(hDevice, ActivePath)) {
return I_DeactivateDevice(hDevice, ActivePath);
}
return FALSE;
}
//
// Find a currently loaded FSD or load it
//
pfsd_t GetFSD(LPCWSTR lpFSDName, BOOL fInitEx)
{
pfsd_t pfsd;
HMODULE hFSDLib;
hFSDLib = LoadDriver(lpFSDName);
if (hFSDLib == NULL) {
DEBUGMSG(ZONE_FSD,(TEXT("DEVICE!GetFSD: LoadDriver(%s) failed %d\n"), lpFSDName, GetLastError()));
return NULL;
}
//
// If this FSD sports the new "FSD_MountDisk" interface,
// then we want to load FSDMGR.DLL instead, and give FSDMGR.DLL
// our handle to the FSD.
//
if (!fInitEx && GetProcAddress(hFSDLib, L"FSD_MountDisk")) {
pfsd = GetFSD(L"FSDMGR.DLL", TRUE); if (pfsd) {
pfsd->pfnFSDInitEx =
(pInitExFn)GetProcAddress(pfsd->hFSDLib, L"FSDMGR_InitEx");
pfsd->pfnFSDDeinitEx =
(pDeinitFn)GetProcAddress(pfsd->hFSDLib, L"FSDMGR_DeinitEx");
if (pfsd->pfnFSDInitEx && pfsd->pfnFSDDeinitEx)
pfsd->hFSDLibEx = hFSDLib;
else
FreeLibrary(hFSDLib);
return pfsd;
}
// If GetFSD(FSDMGR.DLL) failed for some reason, then the code below
// will simply try to treat hFSDLib as an old-model FSD. Probably won't
// work, unless someone really did write an FSD that supports both models.
}
//
// If this file system driver is already loaded, then return a pointer to
// its fsd struct.
//
pfsd = g_lpFSDChain;
while (pfsd) {
if (pfsd->hFSDLib == hFSDLib) {
FreeLibrary(hFSDLib); // only keep one instance
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -