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

📄 device.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                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 + -