📄 disk.c
字号:
)
{
BOOL bRc = TRUE;
DWORD dwWait = 0;
DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6>DiskDetach:%p\n"), pDevice));
if ( !VALID_CONTEXT( pDevice ) ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Context!\n")));
return FALSE;
}
//
// set Remove Pending state
//
EnterCriticalSection( &pDevice->Lock );
pDevice->Flags.DeviceRemoved = TRUE;
LeaveCriticalSection( &pDevice->Lock );
//
// wait for the polling thread to terminate
//
if (pDevice->hMediaChangedEvent && pDevice->hMediaPollThread) {
SetEvent(pDevice->hMediaChangedEvent);
WaitForSingleObject(pDevice->hMediaPollThread, INFINITE);
} else if ( pDevice->hStreamDevice ) {
//
// The device has no polling thread, so dismount the disk
//
DismountUpperDriver(pDevice);
} else {
TEST_TRAP();
}
//
// wait for the remove lock
//
DEBUGMSG(ZONE_INIT, (TEXT("ReleaseRemoveLockAndWait...\n")));
ReleaseRemoveLockAndWait( &pDevice->RemoveLock, NULL );
DEBUGMSG(ZONE_INIT, (TEXT("...ReleaseRemoveLockAndWait\n")));
//
// remove this device instance
//
RemoveDeviceContext( pDevice );
DEBUGMSG(ZONE_INIT, (TEXT("USBDISK6<DiskDetach:%d\n"), bRc));
return bRc;
}
//
// Mount the File System Driver named in the registry on top of our Device.
//
DWORD
MountUpperDriver(
IN PSCSI_DEVICE pDevice,
IN PPOST_INIT_BUF pInBuf
)
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR sFsd[MAX_DLL_LEN] = DEFAULT_FSD_SZ;
REG_VALUE_DESCR RegVal[] = {
FSD_SZ, REG_SZ, MAX_DLL_LEN, (PUCHAR)(sFsd),
NULL, 0, 0, NULL
};
HANDLE h;
DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6>MountUpperDriver\n")));
if ( !VALID_CONTEXT( pDevice ) ) {
DEBUGMSG( ZONE_ERR, (TEXT("MountUpperDriver: Invalid Context!\n")));
return ERROR_INVALID_PARAMETER;
}
EnterCriticalSection(&pDevice->Lock);
do {
if (!pInBuf)
h = pDevice->hStreamDevice;
else
h = pInBuf->p_hDevice;
if ( !pDevice->ActivePath || !h ) {
dwErr = ERROR_INVALID_PARAMETER;
DEBUGMSG(ZONE_ERR, (TEXT("MountUpperDriver: ERROR_INVALID_PARAMETER\n")));
break;
}
if ( !GetSetKeyValues(pDevice->ActivePath,
RegVal,
GET,
FALSE ) ) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("GetSetKeyValues ERRROR:%d\n"), dwErr));
TEST_TRAP();
break;
}
//
// Special case: CD-ROM must load UDFS
//
if (pDevice->DeviceType == SCSI_DEVICE_CDROM &&
wcscmp(sFsd, TEXT("UDFS.DLL")) != 0 )
{
DEBUGMSG(ZONE_WARN, (TEXT("LoadFSD:%s OVERRIDE to:%s\n"), sFsd, TEXT("UDFS.DLL")));
memset(sFsd, 0, MAX_DLL_LEN);
wcscpy(sFsd, TEXT("UDFS.DLL"));
}
//
// This will cause the named FSD to open our device, query via Ioctl,
// then close our device. We can not assume that the FSD is loaded until
// we successfully complete the IOCTL_DISK_GETINFO Ioctl.
//
__try {
if ( !LoadFSDEx(h, sFsd, LOADFSD_SYNCH) ) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("LoadFSD error:%d\n"), dwErr ));
TEST_TRAP();
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErr = GetExceptionCode();
DEBUGMSG(ZONE_ERR,(TEXT("USBDISK6::MountUpperDriver:EXCEPTION:0x%x\n"), dwErr));
}
// pDevice->Flags.FSDMounted = TRUE; // Set in IOCTL_DISK_GETINFO
} while(0);
LeaveCriticalSection(&pDevice->Lock);
DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6<MountUpperDriver:%d\n"), dwErr));
return dwErr;
}
/* ++
This function forces the FSD to dismount by unloading the streams interface.
This invokes our DSK_Deinit.
This deletes the active key in the registry, sends a WM_DEVICECHANGE
message, and triggers a NOTIFICATION_EVENT_DEVICE_CHANGE.
-- */
DWORD
DismountUpperDriver(
IN PSCSI_DEVICE pDevice
)
{
DWORD dwErr = ERROR_SUCCESS;
DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6>DismountUpperDriver\n")));
if ( !pDevice || !pDevice->hStreamDevice ) {
dwErr = ERROR_INVALID_PARAMETER;
} else {
EnterCriticalSection(&pDevice->Lock);
if ( DeactivateDevice( pDevice->hStreamDevice ) ) {
pDevice->hStreamDevice = NULL;
pDevice->Flags.FSDMounted = FALSE;
} else {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("DeactivateDevice error: %d\n")));
TEST_TRAP();
}
LeaveCriticalSection(&pDevice->Lock);
}
DEBUGMSG(ZONE_TRACE, (TEXT("USBDISK6<DismountUpperDriver:%d\n"), dwErr));
return dwErr;
}
DWORD
GetDeviceInfo(
IN PSCSI_DEVICE pDevice,
IN OUT STORAGEDEVICEINFO *psdi
)
{
REG_VALUE_DESCR RegValHD[] = {
L"USBHDProfile", REG_SZ, MAX_DLL_LEN, (PUCHAR)(psdi->szProfile),
NULL, 0, 0, NULL
};
REG_VALUE_DESCR RegValCD[] = {
L"USBCDProfile", REG_SZ, MAX_DLL_LEN, (PUCHAR)(psdi->szProfile),
NULL, 0, 0, NULL
};
REG_VALUE_DESCR RegValFD[] = {
L"USBFDProfile", REG_SZ, MAX_DLL_LEN, (PUCHAR)(psdi->szProfile),
NULL, 0, 0, NULL
};
psdi->dwDeviceType = STORAGE_DEVICE_TYPE_REMOVABLE_MEDIA | \
STORAGE_DEVICE_TYPE_REMOVABLE_DRIVE | \
STORAGE_DEVICE_TYPE_USB;
psdi->dwDeviceFlags = STORAGE_DEVICE_FLAG_MEDIASENSE;
wcscpy( psdi->szProfile, L"Default");
if (pDevice->DeviceType == SCSI_DEVICE_CDROM) {
psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_MULTIMEDIA;
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READONLY;
if ( !GetSetKeyValues(pDevice->ActivePath,
RegValCD,
GET,
FALSE ) ) {
wcscpy( psdi->szProfile, L"USBCDProfile");
}
}
else
if (pDevice->DeviceType== SCSI_DEVICE_DIRECT_ACCESS && pDevice->DiskSubClass == USBMSC_SUBCLASS_UFI) { // USB FLOPPY
psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_BLOCK;
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READWRITE;
if ( !GetSetKeyValues(pDevice->ActivePath,
RegValFD,
GET,
FALSE ) ) {
wcscpy( psdi->szProfile, L"USBFDProfile");
}
}
else
{
psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_BLOCK;
psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READWRITE;
if ( !GetSetKeyValues(pDevice->ActivePath,
RegValHD,
GET,
FALSE ) ) {
wcscpy( psdi->szProfile, L"USBHDProfile");
}
}
return ERROR_SUCCESS;
}
//
// Media Change Polling Thread
//
DWORD WINAPI
MediaChangeThread(
LPVOID Context
)
{
PSCSI_DEVICE pDevice = (PSCSI_DEVICE)Context;
DWORD dwErr, dwReason;
BOOL bReturn;
ULONG ulMediumPresent,ulMediumChanged;
DEBUGMSG(ZONE_THREAD,(TEXT("USBDISK6>MediaChangeThread\n")));
if ( !VALID_CONTEXT( pDevice ) ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Context!\n")));
ExitThread(ERROR_INVALID_PARAMETER);
return ERROR_SUCCESS;
}
dwErr = AcquireRemoveLock(&pDevice->RemoveLock, NULL) ;
if ( ERROR_SUCCESS != dwErr) {
ExitThread(dwErr);
return ERROR_SUCCESS;
}
pDevice->Flags.prevMediumStatus=pDevice->Flags.MediumPresent;
while (pDevice && !pDevice->Flags.DeviceRemoved && !pDevice->Flags.PoweredDown)
{
DWORD ScsiPureTestUnitReady(PSCSI_DEVICE pDevice, UCHAR Lun);
EnterCriticalSection(&pDevice->Lock);
//
// See if the medium changed by polling the device.
// Some devices hard code the information returned in Inquiry,
// so use TestUnitReady.
//
dwErr = ScsiTestUnitReady(pDevice, pDevice->Lun);
if (dwErr==ERROR_SUCCESS) { // Media is available.
pDevice->Flags.MediumPresent=TRUE;
}
else {
pDevice->Flags.MediumPresent=FALSE;
}
ulMediumPresent = pDevice->Flags.MediumPresent;
ulMediumChanged = pDevice->Flags.prevMediumStatus ^ ulMediumPresent;
// RETAILMSG(1, (L"LUN=%d err=%d present=%d changed=%d\n", pDevice->Lun, dwErr,ulMediumPresent, ulMediumChanged));
pDevice->Flags.prevMediumStatus = ulMediumPresent;
#ifdef YE_DATA
//
// Y-E DATA floppy: TestUnitReady will (incorrectly) not return scsi check condition
// if the media is removed. ReadCapacity or ModeSense10 keeps the floppy drive motor constantly
// running, but seems to be the best thing available.
//
// TBD: is this true of all UFI devices, or just Y-E Data? May need a dword reg flag
// set by usbmsc.dll since the scsi driver has no knowledge if VID/PIDs.
if (USBMSC_SUBCLASS_UFI == pDevice->DiskSubClass)
{
DISK_INFO di = { 0 };
// YE-DATA data toggle problem?
ScsiReadCapacity(pDevice, &di, pDevice->Lun);
}
#endif
if (ulMediumChanged)
pDevice->Flags.MediumChanged = TRUE;
if (ulMediumChanged && pDevice->Flags.MediumPresent) {
// Try to update the medium info
dwErr = GetMediumInfo(pDevice, pDevice->Lun);
}
//
// If the Medium has changed then resync the FS, which forces the FS to Dismount, then Remount
//
if (ulMediumChanged && pDevice->hStreamDevice) {
DEBUGMSG(ZONE_THREAD, (TEXT("*** MediaChangeThread::CeResyncFilesys\n")));
LeaveCriticalSection(&pDevice->Lock);
bReturn=CeResyncFilesys(pDevice->hStreamDevice);
EnterCriticalSection(&pDevice->Lock);
if ( !bReturn ) {
DEBUGMSG(ZONE_ERR, (TEXT("*** CeResyncFilesys ERROR:%d\n"), GetLastError() ));
if ( !pDevice->Flags.FSDMounted ) {
//
// The FSD never loaded. This happens when the user
// plugged in the device with no media.
//
dwErr = MountUpperDriver(pDevice, NULL);
}
}
}
LeaveCriticalSection(&pDevice->Lock);
//
// sleep
//
DEBUGMSG(ZONE_EVENTS, (TEXT("*** MediaChangeThread:WaitForSingleObject...\n")));
dwReason = WaitForSingleObject(pDevice->hMediaChangedEvent, pDevice->Timeouts.MediaPollInterval );
DEBUGMSG(ZONE_EVENTS, (TEXT("*** ...MediaChangeThread:WaitForSingleObject:%d\n"), dwReason));
}
//
// The device has been removed, Deactivate the Streams Interface & dismount the FSD
//
if ( pDevice && pDevice->hStreamDevice ) {
DEBUGMSG( ZONE_THREAD, (TEXT("*** MediaChangeThread:DismountUpperDriver\n")));
DismountUpperDriver(pDevice);
}
ReleaseRemoveLock(&pDevice->RemoveLock, NULL);
DEBUGMSG(ZONE_THREAD,(TEXT("USBDISK6<MediaChangeThread\n")));
ExitThread(ERROR_SUCCESS);
return ERROR_SUCCESS;
}
VOID
RemoveDeviceContext(
PSCSI_DEVICE pDevice
)
{
DEBUGMSG(ZONE_INIT,(TEXT("USBDISK6>RemoveDeviceContext(%p)\n"), pDevice));
if ( VALID_CONTEXT( pDevice ) ) {
ASSERT(!pDevice->hStreamDevice);
ASSERT(!pDevice->Flags.FSDMounted);
ASSERT(pDevice->Flags.DeviceRemoved);
// If Flags.Open is set here then we were suprise removed
// so the FSD never called DSK_Close.
//
//ASSERT(!pDevice->Flags.Open);
//ASSERT(0 == pDevice->OpenCount);
if (pDevice->hMediaChangedEvent) {
CloseHandle(pDevice->hMediaChangedEvent);
}
if (pDevice->hMediaPollThread) {
CloseHandle(pDevice->hMediaPollThread);
pDevice->hMediaPollThread = NULL;
}
if (&pDevice->Lock) {
DeleteCriticalSection( &pDevice->Lock );
}
if (pDevice->ActivePath) {
LocalFree(pDevice->ActivePath);
pDevice->ActivePath = NULL;
}
//pDevice->hUsbTransport = NULL;
LocalFree(pDevice);
} else {
DEBUGMSG(ZONE_ERR,(TEXT("Invalid Parameter\n")));
}
DEBUGMSG(ZONE_INIT,(TEXT("USBDISK6<RemoveDeviceContext\n")));
return;
}
// EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -