📄 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.
//
DWORD
LoadFSDThread(
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 + -