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

📄 disk.c

📁 Windows CE 5.0下的U盘驱动源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
    )
{
    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 + -