std::string get_root_uuid() { using tchar_str = std::basic_string<TCHAR>; string uuid; TCHAR buf[max_drive_name]; // temporary buffer for volume name tchar_str drive = TEXT("c:\\"); // string "template" for drive specifier // walk through legal drive letters, skipping floppies for (TCHAR i = TEXT('c'); i < TEXT('z'); i++) { // Stamp the drive for the appropriate letter. drive[0] = i; if (GetVolumeNameForVolumeMountPoint(drive.c_str(), buf, max_drive_name)) { tchar_str drive_name = buf; auto first = drive_name.find(TEXT("Volume{")); if (first != std::string::npos) { first += 7; auto last = drive_name.find(TEXT("}"), first); if (last != std::string::npos && last > first) { mv(uuid, drive_name.substr(first, last - first)); // UUIDs are formatted as 8-4-4-4-12 hex digits groups auto cpy = uuid; replace_if(cpy.begin(), cpy.end(), ::isxdigit, 'F'); // discard invalid UUID if (cpy != uuid_format) uuid.clear(); else return uuid; // return first valid UUID we get } } } } return uuid; }
QString QStorageInfo_CustomPrivate::uriForDrive(const QString &drive) { WCHAR uri[50]; if (GetVolumeNameForVolumeMountPoint((WCHAR *)drive.utf16(), uri, 50)) return QString::fromUtf16(reinterpret_cast<const unsigned short *>(uri)); return QString(); }
QString getGUID(const QString &mountPoint) { const size_t maxGUIDPath = 50; wchar_t buffer[maxGUIDPath + 1]; qDebug()<<"GetGUIDof: "<<mountPoint; GetVolumeNameForVolumeMountPoint(mountPoint.toStdWString().c_str(), buffer, maxGUIDPath); qDebug()<<"GetGUIDof: "<<QString("").fromStdWString(buffer).toLatin1()<< " "<<GetLastError(); return QString(QString("").fromStdWString(buffer).toLatin1()).remove("\\\\?\\Volume").remove("\\"); }
void GetSystemDriveGUID(Row& r) { char buf[51] = {0}; auto sysRoot = getSystemRoot().root_name().string() + "\\"; if (GetVolumeNameForVolumeMountPoint( sysRoot.c_str(), static_cast<LPSTR>(buf), 50)) { r["device"] = SQL_TEXT(buf); } }
static int sync_win32 (void) { DWORD n1, n2; n1 = GetLogicalDriveStrings (0, NULL); if (n1 == 0) return -1; TCHAR buffer[n1+2]; /* sic */ n2 = GetLogicalDriveStrings (n1, buffer); if (n2 == 0) return -1; TCHAR *p = buffer; /* The MSDN example code itself assumes that there is always one * drive in the system. However we will be better than that and not * make the assumption ... */ while (*p) { HANDLE drive; DWORD drive_type; /* Ignore removable drives. */ drive_type = GetDriveType (p); if (drive_type == DRIVE_FIXED) { /* To open the volume you have to specify the volume name, not * the mount point. MSDN documents use of the constant 50 * below. */ TCHAR volname[50]; if (!GetVolumeNameForVolumeMountPoint (p, volname, 50)) return -1; drive = CreateFile (volname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (drive == INVALID_HANDLE_VALUE) return -1; BOOL r; /* This always fails in Wine: * http://bugs.winehq.org/show_bug.cgi?id=14915 */ r = FlushFileBuffers (drive); CloseHandle (drive); if (!r) return -1; } /* Skip to next \0 character. */ while (*p++); } return 0; }
BOOL GetNtfsNumberOfSectors(wchar_t * rootPath, uint64 * pNumberOfSectors, DWORD *pBytesPerSector) { HANDLE hDevice; BOOL bResult; DWORD nbytes, dwError; size_t len; NTFS_VOLUME_DATA_BUFFER ntfsvdb; wchar_t szVolumeGUID[128]; // get volume name if (!GetVolumeNameForVolumeMountPoint(rootPath,szVolumeGUID,ARRAYSIZE(szVolumeGUID))) { return FALSE; } // strip trailing backslash from volume GUID (otherwise it means root dir) len = wcslen(szVolumeGUID); if (len>0) --len; if (szVolumeGUID[len]==L'\\') szVolumeGUID[len]=0; hDevice = CreateFile(szVolumeGUID, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == INVALID_HANDLE_VALUE) return (FALSE); bResult = DeviceIoControl(hDevice, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsvdb, sizeof(ntfsvdb), &nbytes, (LPOVERLAPPED) NULL); if (bResult) { if (pNumberOfSectors) *pNumberOfSectors = ntfsvdb.NumberSectors.QuadPart; if (pBytesPerSector) *pBytesPerSector = ntfsvdb.BytesPerSector; } dwError = GetLastError (); CloseHandle(hDevice); SetLastError (dwError); return (bResult); }
BOOL _GetDiskFreeSpaceEx( LPCTSTR lpDirectoryName, // ディレクトリ名 PULARGE_INTEGER lpFreeBytesAvailable, // 呼び出し側が利用できるバイト数 PULARGE_INTEGER lpTotalNumberOfBytes, // ディスク全体のバイト数 PULARGE_INTEGER lpTotalNumberOfFreeBytes // ディスク全体の空きバイト数 ) { TCHAR szVolumePathName[MAX_PATH] = _T(""); if( GetVolumePathName( lpDirectoryName, szVolumePathName, MAX_PATH) == FALSE ){ return GetDiskFreeSpaceEx( lpDirectoryName, lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes ); } TCHAR szMount[MAX_PATH] = _T(""); if( GetVolumeNameForVolumeMountPoint(szVolumePathName, szMount, MAX_PATH) == FALSE ){ return GetDiskFreeSpaceEx( szVolumePathName, lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes ); } return GetDiskFreeSpaceEx( szMount, lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes ); }
bool mountFolder(const QString &srcDrive, const QString &tgtPath, QString &error) { QString drv = QDir::cleanPath(srcDrive)+"\\"; QString nat = QDir::toNativeSeparators(tgtPath); #ifdef _WIN32 LPCWSTR lpszVolumeMountPoint = (LPCWSTR)drv.utf16(); LPWSTR lpszVolumeName = '\0'; if (GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, lpszVolumeName, 100) == NO_ERROR) { lpszVolumeMountPoint = (LPCWSTR)nat.utf16(); if (SetVolumeMountPoint(lpszVolumeMountPoint, lpszVolumeName) == NO_ERROR) return true; } #endif error = getLastWinError(); return false; }
int ExtendFileSystem (HWND hwndDlg , wchar_t *lpszVolume, Password *pVolumePassword, int VolumePkcs5, int VolumePim, uint64 newDataAreaSize) { wchar_t szVolumeGUID[128]; int driveNo = -1; wchar_t rootPath[] = L"A:\\"; enum EV_FileSystem fs; DWORD dwError; int nStatus = ERR_SUCCESS; DWORD BytesPerSector; // mount and resize file system DebugAddProgressDlgStatus (hwndDlg, L"Mounting volume ...\r\n"); nStatus=MountVolTemp(hwndDlg, lpszVolume, &driveNo, pVolumePassword, VolumePkcs5, VolumePim); if (nStatus!=ERR_SUCCESS) { driveNo = -1; goto error; } rootPath[0] += driveNo; if ( !GetFileSystemType(rootPath,&fs) ) { dwError = GetLastError(); if (dwError == ERROR_UNRECOGNIZED_VOLUME) { // raw volume with unrecognized file system -> return with no error nStatus = ERR_SUCCESS; goto error; } nStatus = ERR_OS_ERROR; goto error; } if (fs != EV_FS_TYPE_RAW && fs != EV_FS_TYPE_NTFS ) { // FsctlExtendVolume only supports NTFS and RAW -> return with no error nStatus = ERR_SUCCESS; goto error; } // Get volume GUID if (!GetVolumeNameForVolumeMountPoint(rootPath,szVolumeGUID,ARRAYSIZE(szVolumeGUID))) { nStatus = ERR_OS_ERROR; goto error; } else { // strip trailing backslash from volume GUID (otherwise it means root dir) size_t len = wcslen(szVolumeGUID); if (len>0) --len; if (szVolumeGUID[len]==L'\\') szVolumeGUID[len]=0; } // Get Sector Size if ( !GetNtfsNumberOfSectors(rootPath, NULL, &BytesPerSector) ) { nStatus = ERR_OS_ERROR; goto error; } DebugAddProgressDlgStatus (hwndDlg, L"Extending file system ...\r\n"); // extend volume nStatus = FsctlExtendVolume(szVolumeGUID, newDataAreaSize/BytesPerSector ); error: dwError = GetLastError(); if (driveNo>=0) { DebugAddProgressDlgStatus (hwndDlg, L"Unmounting volume ...\r\n"); UnmountVolume (hwndDlg, driveNo, TRUE); } SetLastError (dwError); return nStatus; }
HRESULT pGetVolumeDeviceNameForMountPointW( __in LPCWSTR VolumeMountPoint, __out LPWSTR* VolumeDeviceName) { // The lpszVolumeMountPoint parameter may be a drive letter with // appended backslash (\), such as "D:\". Alternatively, it may be // a path to a volume mount point, again with appended backslash (\), // such as "c:\mnt\edrive\". // A reasonable size for the buffer to accommodate the largest possible // volume name is 50 characters --> wrong 100 HRESULT hr; XTLASSERT(NULL != VolumeDeviceName); if (NULL == VolumeDeviceName) { return E_POINTER; } *VolumeDeviceName = NULL; const DWORD MAX_VOLUMENAME_LEN = 50; DWORD volumeDeviceNameLength = MAX_VOLUMENAME_LEN; XTL::AutoProcessHeapPtr<TCHAR> volumeDeviceName = static_cast<TCHAR*>( HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, volumeDeviceNameLength * sizeof(TCHAR))); if (volumeDeviceName.IsInvalid()) { XTLTRACE2(NdasVolTrace, 0, "HeapAlloc for %d bytes failed.\n", volumeDeviceNameLength); return E_OUTOFMEMORY; } BOOL success = GetVolumeNameForVolumeMountPoint( VolumeMountPoint, volumeDeviceName, volumeDeviceNameLength); if (!success) { hr = HRESULT_FROM_WIN32(GetLastError()); XTLTRACE2(NdasVolTrace, 0, "GetVolumeNameForVolumeMountPoint(%ls) failed, hr=0x%X\n", VolumeMountPoint, hr); return hr; } // Volume Name is a format of \\?\Volume{XXXX}\ with trailing backslash // Volume device name is that of \\.\Volume{XXXX} without trailing backslash _ASSERTE(_T('\\') == volumeDeviceName[0]); _ASSERTE(_T('\\') == volumeDeviceName[1]); _ASSERTE(_T('?') == volumeDeviceName[2]); _ASSERTE(_T('\\') == volumeDeviceName[3]); if (_T('\\') == volumeDeviceName[0] && _T('\\') == volumeDeviceName[1] && _T('?') == volumeDeviceName[2] && _T('\\') == volumeDeviceName[3]) { // replace ? to . volumeDeviceName[2] = _T('.'); } // remove trailing backslash pRemoveTrailingBackslash(volumeDeviceName); XTLTRACE2(NdasVolTrace, 2, "VolumeMountPoint(%ls)=>Volume(%ls)\n", VolumeMountPoint, volumeDeviceName); *VolumeDeviceName = volumeDeviceName.Detach(); return S_OK; }
// This does the same as GetVolumePathNamesForVolumeNameW() on Windows XP and // later. It is built into 32 bit versions of this library to make sure that // the DLL can load correctly on Windows 2000 as well. BOOL WINAPI ImScsiLegacyGetVolumePathNamesForVolumeName( __in LPCWSTR lpszVolumeName, __out LPWSTR lpszVolumePathNames, __in DWORD cchBufferLength, __out PDWORD lpcchReturnLength) { *lpcchReturnLength = 0; DWORD dw; dw; LPWSTR cur_ptr = lpszVolumePathNames; LPWSTR end_ptr = lpszVolumePathNames + cchBufferLength; WCHAR vol_target[MAX_PATH]; wcsncpy(vol_target, lpszVolumeName + 4, 44); vol_target[44] = 0; if (!QueryDosDevice(vol_target, vol_target, _countof(vol_target))) { return FALSE; } WHeapMem<WCHAR> dosdevs(UNICODE_STRING_MAX_BYTES, HEAP_GENERATE_EXCEPTIONS); if (!QueryDosDevice(NULL, dosdevs, (DWORD)dosdevs.Count())) { return FALSE; } DWORD good = cchBufferLength >= 2; *lpcchReturnLength = 2; WCHAR dev_target[MAX_PATH]; SIZE_T length; for (LPCWSTR ptr = dosdevs; (length = wcslen(ptr)) != 0; ptr += length + 1) { if (good) { *cur_ptr = 0; } if ((length != 2) || (ptr[1] != L':') || (!QueryDosDevice(ptr, dev_target, _countof(dev_target))) || (_wcsicmp(dev_target, vol_target) != 0)) { continue; } *lpcchReturnLength += 4; if ((cur_ptr + 4) >= end_ptr) { good = FALSE; } if (good) { swprintf(cur_ptr, L"%ws\\", ptr); cur_ptr += 4; } } WCHAR vol_name[50]; HANDLE volume = FindFirstVolume(vol_name, _countof(vol_name)); if (volume == INVALID_HANDLE_VALUE) { return FALSE; } DWORD error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); do { HANDLE vol_mnt = FindFirstVolumeMountPoint(vol_name, dosdevs, (DWORD)dosdevs.Count()); if (vol_mnt == INVALID_HANDLE_VALUE) { continue; } do { WMem<WCHAR> mnt_path; mnt_path = ImDiskAllocPrintF(L"%1!ws!%2!ws!", vol_name, dosdevs); if (!mnt_path) { continue; } WCHAR mnt_vol_name[50]; if (!GetVolumeNameForVolumeMountPoint(mnt_path, mnt_vol_name, _countof(mnt_vol_name))) { continue; } if (_wcsicmp(mnt_vol_name, lpszVolumeName) == 0) { if (ImScsiLegacyGetVolumePathNamesForVolumeName(vol_name, vol_target, _countof(vol_target), &dw)) { mnt_path = ImDiskAllocPrintF(L"%1!ws!%2!ws!", vol_target, dosdevs); } size_t len = wcslen(mnt_path) + 1; *lpcchReturnLength += (DWORD)len; if ((cur_ptr + len) >= end_ptr) { good = FALSE; } if (good) { wcscpy(cur_ptr, mnt_path); cur_ptr += len; } } } while (FindNextVolumeMountPoint(vol_mnt, dosdevs, (DWORD)dosdevs.Count())); FindVolumeMountPointClose(vol_mnt); } while (FindNextVolume(volume, vol_name, _countof(vol_name))); FindVolumeClose(volume); SetErrorMode(error_mode); if (cur_ptr >= end_ptr) { good = FALSE; } if (good) { *cur_ptr = 0; ++*lpcchReturnLength; } else { SetLastError(ERROR_MORE_DATA); } return good; }
void g_scan_drives (DWORD mask) { //pfc::hires_timer timer; //timer.start(); //profiler(scandrives); #if 0 { TCHAR volume[128], mount[512]; memset(volume, 0, sizeof(volume)); HANDLE vol = FindFirstVolume(volume, tabsize(volume)-1); if (vol != INVALID_HANDLE_VALUE) { do { console::formatter() << "Volume: " << pfc::stringcvt::string_utf8_from_wide(volume, 128); memset(mount, 0, sizeof(mount)); HANDLE hmount = FindFirstVolumeMountPoint(volume, mount, tabsize(mount)-1); if (hmount != INVALID_HANDLE_VALUE) { do { console::formatter() << "mountpoint: " << pfc::stringcvt::string_utf8_from_wide(mount, tabsize(mount)); memset(mount, 0, sizeof(mount)); } while (FindNextVolumeMountPoint(hmount, mount, tabsize(mount)-1) || GetLastError() != ERROR_NO_MORE_FILES); FindVolumeMountPointClose(hmount); } memset(volume, 0, sizeof(volume)); } while (FindNextVolume(vol, volume, tabsize(volume)-1) || GetLastError() != ERROR_NO_MORE_FILES); FindVolumeClose(vol); } } #endif if (mask) { t_volumes volumes; build_volumes_v2(volumes); t_size i =0; for (i=0; i<32; i++) { if (mask & 1<<i) { pfc::string8 drive; drive.add_byte('A'+i); pfc::array_t<WCHAR> path, itunesdb_path; path.append_single('A'+i); path.append_fromptr(L":\\", 3); { WCHAR volumename[129]; memset(volumename, 0, sizeof(volumename)); if (GetDriveType(path.get_ptr()) == DRIVE_REMOVABLE && GetVolumeNameForVolumeMountPoint(path.get_ptr(), volumename, 128)) { t_size indexvol; //if (volumes.find(volumename, 128, indexvol)) { //FIXME WTF if (volumes.find(volumename, 128, indexvol) /*&& g_check_devid_is_ipod(volumes[indexvol].disk_device_id)*/) { ipod_device_ptr_t temp = new ipod_device_t('A' + i, volumes[indexvol].model, volumes[indexvol].shuffle, volumes[indexvol].disk_device_id.get_ptr(), volumes[indexvol].volume_name.get_ptr(), volumes[indexvol].driver_symbolic_path.get_ptr(), volumes[indexvol].instance, device_properties_t()); pfc::string8 pl; try { g_get_device_xml(temp, pl); #if 0//_DEBUG { file::ptr f; abort_callback_dummy noabort; filesystem::g_open_read(f, "i:\\nano6g.plist", noabort); pfc::array_staticsize_t<char> d(pfc::downcast_guarded<t_uint32>(f->get_size_ex(noabort))); f->read(d.get_ptr(), d.get_size(), noabort); pl.set_string(d.get_ptr(), d.get_size()); } #endif g_get_artwork_info(pl, temp->m_device_properties); } catch (const pfc::exception & ex) { console::formatter() << "iPod manager: Failed to get iPod checkpoint data - " << ex.what() << ". Artwork functionality will be unavailable."; temp->m_device_properties.m_artwork_formats.remove_all(); }; //console::formatter() << "New iPod detected. Drive: " << drive << " Device Instance ID: " << pfc::stringcvt::string_utf8_from_wide(volumes[indexvol].disk_device_id); if (m_abort) g_drive_manager.add_drive(temp, *m_abort); else g_drive_manager.add_drive(temp, abort_callback_dummy()); } //else // console::formatter() << "New drive detected. Drive: " << drive << " Device Instance ID: " << pfc::stringcvt::string_utf8_from_wide(volumes[indexvol].disk_device_id);// << " Volume ID: " << pfc::stringcvt::string_utf8_from_wide(volumes[indexvol].volume_name); } } //else // console::formatter() << "Drive is not expected type or GetVolumeNameForVolumeMountPoint failed. Drive: " << drive; } } } } //console::formatter() << "old:" << timer.query(); }
BOOL get_all_removable_disks(struct tagDrives *g_drives) { WCHAR caDrive[4]; WCHAR volume[BUFSIZE]; int nLoopIndex; DWORD dwDriveMask; unsigned int g_count=0; caDrive[0] = 'A'; caDrive[1] = ':'; caDrive[2] = '\\'; caDrive[3] = 0; // Get all drives in the system. dwDriveMask = GetLogicalDrives(); if(dwDriveMask == 0) { PyErr_SetString(DriveError, "GetLogicalDrives failed"); return FALSE; } // Loop for all drives (MAX_DRIVES = 26) for(nLoopIndex = 0; nLoopIndex < MAX_DRIVES; nLoopIndex++) { // if a drive is present (we cannot ignore the A and B drives as there // are people out there that think mapping devices to use those letters // is a good idea, sigh) if(dwDriveMask & 1) { caDrive[0] = 'A' + nLoopIndex; // If a drive is removable if(GetDriveType(caDrive) == DRIVE_REMOVABLE) { //Get its volume info and store it in the global variable. if(GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFSIZE)) { g_drives[g_count].letter = caDrive[0]; wcscpy_s(g_drives[g_count].volume, BUFSIZE, volume); g_count ++; } } } dwDriveMask >>= 1; } // success if atleast one removable drive is found. if(g_count == 0) { PyErr_SetString(DriveError, "No removable drives found"); return FALSE; } return TRUE; }
int __cdecl _tmain(int argc, TCHAR** argv) { TCHAR* lpPath; TCHAR mountPoint[MAX_PATH]; TCHAR volumeName[100]; LPTSTR lpVolumeDevicePath; HANDLE hVolume; if (argc > 1) { if (0 == lstrcmpi(_T("/trace"), argv[1]) || 0 == lstrcmpi(_T("-trace"), argv[1])) { NdasVolSetTrace(0x0000ffff, 0xffffffff, 5); --argc; ++argv; } } lpPath = (argc < 2) ? _T("C:") : argv[1]; lpVolumeDevicePath = lpPath; _tprintf(_T("Device Name: %s\n"), lpVolumeDevicePath); if (NdasIsNdasPath(lpVolumeDevicePath)) { _tprintf(_T("%s is on the NDAS device.\n"), lpVolumeDevicePath ); if (GetVolumePathName(lpVolumeDevicePath, mountPoint, RTL_NUMBER_OF(mountPoint))) { if (GetVolumeNameForVolumeMountPoint( mountPoint, volumeName, RTL_NUMBER_OF(volumeName))) { int len = lstrlen(volumeName); // _tprintf(_T("VolumeName=%s\n"), volumeName); // remove trailing backslash if (len > 0 && _T('\\') == volumeName[len-1]) { volumeName[len-1] = _T('\0'); } // replace \\?\Volume... to \\.\Volume... if (_T('\\') == volumeName[0] && _T('\\') == volumeName[1] && _T('?') == volumeName[2] && _T('\\') == volumeName[3]) { volumeName[2] = _T('.'); } // _tprintf(_T("VolumeName=%s\n"), volumeName); hVolume = CreateFile(volumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE != hVolume) { NDAS_SCSI_LOCATION loc; if (NdasGetNdasScsiLocationForVolume(hVolume,&loc)) { _tprintf(_T("NDAS_SCSI_LOCATION=(%d,%d,%d)"), loc.SlotNo, loc.TargetID, loc.LUN); } else { _tprintf(_T("NdasGetNdasScsiLocationForVolume failed.\n")); _tprintf(_T("Error %u(%X)\n"), GetLastError(), GetLastError()); } CloseHandle(hVolume); } else { _tprintf(_T("Opening the volume %s failed.\n"), volumeName); _tprintf(_T("Error %u(%X)\n"), GetLastError(), GetLastError()); } } else { _tprintf(_T("GetVolumeNameForVolumeMountPoint %s failed.\n"), mountPoint); _tprintf(_T("Error %u(%X)\n"), GetLastError(), GetLastError()); } } else { _tprintf(_T("GetVolumePathName %s failed.\n"), lpVolumeDevicePath); _tprintf(_T("Error %u(%X)\n"), GetLastError(), GetLastError()); } } else { _tprintf(_T("Error %u(%X)\n"), GetLastError(), GetLastError()); } return 0; }
static int adddrive (const TCHAR *drvpath, int bus, int pathid, int targetid, int lunid, int scanmode) { struct dev_info_spti *di; int cnt = total_devices, i; int freeit = 1; if (cnt >= MAX_TOTAL_SCSI_DEVICES) return 0; for (i = 0; i < total_devices; i++) { di = &dev_info[i]; if (!_tcscmp (drvpath, di->drvpath)) return 0; } write_log (L"SPTI: unit %d '%s' added\n", total_devices, drvpath); di = &dev_info[total_devices]; di->drvpath = my_strdup (drvpath); di->type = 0; di->bus = bus; di->path = pathid; di->target = targetid; di->lun = lunid; di->scanmode = scanmode; di->drvletter = 0; di->enabled = true; for (TCHAR drvletter = 'C'; drvletter <= 'Z'; drvletter++) { TCHAR drvname[10]; TCHAR volname[MAX_DPATH], volname2[MAX_DPATH]; _stprintf (drvname, L"%c:\\", drvletter); if (GetVolumeNameForVolumeMountPoint (drvname, volname, sizeof volname / sizeof (TCHAR))) { TCHAR drvpath2[MAX_DPATH]; _stprintf (drvpath2, L"%s\\", di->drvpath); if (GetVolumeNameForVolumeMountPoint (drvpath2, volname2, sizeof volname2 / sizeof (TCHAR))) { if (!_tcscmp (volname, volname2)) { di->drvletter = drvletter; _tcscpy (di->drvlettername, drvname); break; } } } } total_devices++; unittable[cnt] = cnt + 1; if (open_scsi_device2 (&dev_info[cnt], cnt)) { for (i = 0; i < cnt; i++) { if (!memcmp (di->inquirydata, dev_info[i].inquirydata, INQUIRY_SIZE) && di->scanmode != dev_info[i].scanmode) { write_log (L"duplicate device, skipped..\n"); break; } } if (i == cnt) { freeit = 0; close_scsi_device2 (&dev_info[cnt]); } } if (freeit) { free_scsi_device (&dev_info[cnt]); total_devices--; } unittable[cnt] = 0; return 1; }
int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams) { int nStatus; PCRYPTO_INFO cryptoInfo = NULL; HANDLE dev = INVALID_HANDLE_VALUE; DWORD dwError; char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; unsigned __int64 num_sectors, startSector; fatparams ft; FILETIME ftCreationTime; FILETIME ftLastWriteTime; FILETIME ftLastAccessTime; BOOL bTimeStampValid = FALSE; BOOL bInstantRetryOtherFilesys = FALSE; char dosDev[TC_MAX_PATH] = { 0 }; char devName[MAX_PATH] = { 0 }; int driveLetter = -1; WCHAR deviceName[MAX_PATH]; uint64 dataOffset, dataAreaSize; LARGE_INTEGER offset; BOOL bFailedRequiredDASD = FALSE; HWND hwndDlg = volParams->hwndDlg; FormatSectorSize = volParams->sectorSize; if (FormatSectorSize < TC_MIN_VOLUME_SECTOR_SIZE || FormatSectorSize > TC_MAX_VOLUME_SECTOR_SIZE || FormatSectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0) { Error ("SECTOR_SIZE_UNSUPPORTED", hwndDlg); return ERR_DONT_REPORT; } /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is less than the maximum FAT size, the user is asked within this function whether he wants to instantly retry FAT format instead (to avoid having to re-create the whole container again). If the user answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed and some destructive operations that were performed during the first attempt must be (and are) skipped. Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format', determine whether they (or their portions) need to be skipped during such a second attempt; if so, use the 'bInstantRetryOtherFilesys' flag to skip them. */ if (volParams->hiddenVol) { dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size; } else { if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE) return ERR_VOL_SIZE_WRONG; dataOffset = TC_VOLUME_DATA_OFFSET; } dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size); num_sectors = dataAreaSize / FormatSectorSize; if (volParams->bDevice) { StringCbCopyA ((char *)deviceName, sizeof(deviceName), volParams->volumePath); ToUNICODE ((char *)deviceName, sizeof(deviceName)); driveLetter = GetDiskDeviceDriveLetter (deviceName); } VirtualLock (header, sizeof (header)); nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE, header, volParams->ea, FIRST_MODE_OF_OPERATION_ID, volParams->password, volParams->pkcs5, volParams->pim, NULL, &cryptoInfo, dataAreaSize, volParams->hiddenVol ? dataAreaSize : 0, dataOffset, dataAreaSize, 0, volParams->headerFlags, FormatSectorSize, FALSE); if (nStatus != 0) { burn (header, sizeof (header)); VirtualUnlock (header, sizeof (header)); return nStatus; } begin_format: if (volParams->bDevice) { /* Device-hosted volume */ DWORD dwResult; int nPass; if (FakeDosNameForDevice (volParams->volumePath, dosDev, sizeof(dosDev), devName, sizeof(devName), FALSE) != 0) return ERR_OS_ERROR; if (IsDeviceMounted (devName)) { if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE) { Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg); nStatus = ERR_DONT_REPORT; goto error; } /* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver would otherwise prevent us from writing to hidden sectors). */ if (!DeviceIoControl (dev, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL)) { bFailedRequiredDASD = TRUE; } } else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1) { // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition // to which no drive letter has been assigned under the system. This problem can be worked // around by assigning a drive letter to the partition temporarily. char szDriveLetter[] = { 'A', ':', 0 }; char rootPath[] = { 'A', ':', '\\', 0 }; char uniqVolName[MAX_PATH+1] = { 0 }; int tmpDriveLetter = -1; BOOL bResult = FALSE; tmpDriveLetter = GetFirstAvailableDrive (); if (tmpDriveLetter != -1) { rootPath[0] += (char) tmpDriveLetter; szDriveLetter[0] += (char) tmpDriveLetter; if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath)) { bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH); DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE, szDriveLetter, volParams->volumePath); if (bResult && SetVolumeMountPoint (rootPath, uniqVolName)) { // The drive letter can be removed now DeleteVolumeMountPoint (rootPath); } } } } // For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be // redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed, // bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However, // for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly // send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result. DeviceIoControl (dev, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL); // If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open // so that the filesystem driver does not prevent us from formatting hidden sectors. for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++) { int retryCount; retryCount = 0; // Try exclusive access mode first // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries). while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES) { dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (retryCount > 1) Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY); } if (dev == INVALID_HANDLE_VALUE) { // Exclusive access denied -- retry in shared mode dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (dev != INVALID_HANDLE_VALUE) { if (!volParams->bForceOperation && (Silent || (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2)))) { nStatus = ERR_DONT_REPORT; goto error; } } else { handleWin32Error (volParams->hwndDlg, SRC_POS); Error ("CANT_ACCESS_VOL", hwndDlg); nStatus = ERR_DONT_REPORT; goto error; } } if (volParams->hiddenVol || bInstantRetryOtherFilesys) break; // The following "quick format" operation would damage the outer volume if (nPass == 0) { char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE]; DWORD bw; // Perform pseudo "quick format" so that the filesystem driver does not prevent us from // formatting hidden sectors memset (buf, 0, sizeof (buf)); if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL)) { nStatus = ERR_OS_ERROR; goto error; } FlushFileBuffers (dev); CloseHandle (dev); dev = INVALID_HANDLE_VALUE; } } if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL)) { Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg); nStatus = ERR_DONT_REPORT; goto error; } } else { /* File-hosted volume */ dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0, NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); if (dev == INVALID_HANDLE_VALUE) { nStatus = ERR_OS_ERROR; goto error; } DisableFileCompression (dev); if (!volParams->hiddenVol && !bInstantRetryOtherFilesys) { LARGE_INTEGER volumeSize; volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE; if (volParams->sparseFileSwitch && volParams->quickFormat) { // Create as sparse file container DWORD tmp; if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL)) { nStatus = ERR_OS_ERROR; goto error; } } // Preallocate the file if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN) || !SetEndOfFile (dev) || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0) { nStatus = ERR_OS_ERROR; goto error; } } } if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp) { if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) bTimeStampValid = FALSE; else bTimeStampValid = TRUE; } if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW); /* Volume header */ // Hidden volume setup if (volParams->hiddenVol) { LARGE_INTEGER headerOffset; // Check hidden volume size if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE) { nStatus = ERR_VOL_SIZE_WRONG; goto error; } // Seek to hidden volume header location headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET; if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN)) { nStatus = ERR_OS_ERROR; goto error; } } else if (bInstantRetryOtherFilesys) { // The previous file system format failed and the user wants to try again with a different file system. // The volume header had been written successfully so we need to seek to the byte after the header. LARGE_INTEGER offset; offset.QuadPart = TC_VOLUME_DATA_OFFSET; if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN)) { nStatus = ERR_OS_ERROR; goto error; } } if (!bInstantRetryOtherFilesys) { // Write the volume header if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header)) { nStatus = ERR_OS_ERROR; goto error; } // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data if (!volParams->bDevice && !volParams->hiddenVol) { byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE]; DWORD bytesWritten; ZeroMemory (buf, sizeof (buf)); if (!WriteFile (dev, buf, sizeof (buf), &bytesWritten, NULL)) { nStatus = ERR_OS_ERROR; goto error; } if (bytesWritten != sizeof (buf)) { nStatus = ERR_PARAMETER_INCORRECT; goto error; } } } if (volParams->hiddenVol) { // Calculate data area position of hidden volume cryptoInfo->hiddenVolumeOffset = dataOffset; // Validate the offset if (dataOffset % FormatSectorSize != 0) { nStatus = ERR_VOL_SIZE_WRONG; goto error; } volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant } /* Data area */ startSector = dataOffset / FormatSectorSize; // Format filesystem switch (volParams->fileSystem) { case FILESYS_NONE: case FILESYS_NTFS: if (volParams->bDevice && !StartFormatWriteThread()) { nStatus = ERR_OS_ERROR; goto error; } nStatus = FormatNoFs (hwndDlg, startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat); if (volParams->bDevice) StopFormatWriteThread(); break; case FILESYS_FAT: if (num_sectors > 0xFFFFffff) { nStatus = ERR_VOL_SIZE_WRONG; goto error; } // Calculate the fats, root dir etc ft.num_sectors = (unsigned int) (num_sectors); #if TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF #error TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF #endif ft.sector_size = (uint16) FormatSectorSize; ft.cluster_size = volParams->clusterSize; memcpy (ft.volume_name, "NO NAME ", 11); GetFatParams (&ft); *(volParams->realClusterSize) = ft.cluster_size * FormatSectorSize; if (volParams->bDevice && !StartFormatWriteThread()) { nStatus = ERR_OS_ERROR; goto error; } nStatus = FormatFat (hwndDlg, startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat); if (volParams->bDevice) StopFormatWriteThread(); break; default: nStatus = ERR_PARAMETER_INCORRECT; goto error; } if (nStatus != ERR_SUCCESS) goto error; // Write header backup offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE; if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN)) { nStatus = ERR_OS_ERROR; goto error; } nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE, header, volParams->ea, FIRST_MODE_OF_OPERATION_ID, volParams->password, volParams->pkcs5, volParams->pim, cryptoInfo->master_keydata, &cryptoInfo, dataAreaSize, volParams->hiddenVol ? dataAreaSize : 0, dataOffset, dataAreaSize, 0, volParams->headerFlags, FormatSectorSize, FALSE); if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header)) { nStatus = ERR_OS_ERROR; goto error; } // Fill reserved header sectors (including the backup header area) with random data if (!volParams->hiddenVol) { nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, dataAreaSize, FALSE, FALSE); if (nStatus != ERR_SUCCESS) goto error; } #ifndef DEBUG if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS) Sleep (500); // User-friendly GUI #endif error: dwError = GetLastError(); burn (header, sizeof (header)); VirtualUnlock (header, sizeof (header)); if (dev != INVALID_HANDLE_VALUE) { if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0) { // Remove preallocated part before closing file handle if format failed if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0) SetEndOfFile (dev); } FlushFileBuffers (dev); if (bTimeStampValid) SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime); CloseHandle (dev); dev = INVALID_HANDLE_VALUE; } if (nStatus != 0) { SetLastError(dwError); goto fv_end; } if (volParams->fileSystem == FILESYS_NTFS) { // Quick-format volume as NTFS int driveNo = GetLastAvailableDrive (); MountOptions mountOptions; int retCode; ZeroMemory (&mountOptions, sizeof (mountOptions)); if (driveNo == -1) { if (!Silent) { MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND); MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); } nStatus = ERR_NO_FREE_DRIVES; goto fv_end; } mountOptions.ReadOnly = FALSE; mountOptions.Removable = FALSE; mountOptions.ProtectHiddenVolume = FALSE; mountOptions.PreserveTimestamp = bPreserveTimestamp; mountOptions.PartitionInInactiveSysEncScope = FALSE; mountOptions.UseBackupHeader = FALSE; if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, volParams->pkcs5, volParams->pim, FALSE, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1) { if (!Silent) { MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND); MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND); } nStatus = ERR_VOL_MOUNT_FAILED; goto fv_end; } if (!Silent && !IsAdmin () && IsUacSupported ()) retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize); else retCode = FormatNtfs (driveNo, volParams->clusterSize); if (retCode != TRUE) { if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent) MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); if (dataAreaSize <= TC_MAX_FAT_SECTOR_COUNT * FormatSectorSize) { if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT", hwndDlg) == IDYES) { // NTFS format failed and the user wants to try FAT format immediately volParams->fileSystem = FILESYS_FAT; bInstantRetryOtherFilesys = TRUE; volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted volParams->clusterSize = 0; // Default cluster size goto begin_format; } } else Error ("FORMAT_NTFS_FAILED", hwndDlg); nStatus = ERR_DONT_REPORT; goto fv_end; } if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent) MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); } fv_end: dwError = GetLastError(); if (dosDev[0]) RemoveFakeDosName (volParams->volumePath, dosDev); crypto_close (cryptoInfo); SetLastError (dwError); return nStatus; }
void build_volumes_v2(t_volumes & volumes) { HDEVINFO di = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (di != INVALID_HANDLE_VALUE) { SP_DEVINFO_DATA did; memset(&did, 0, sizeof(did)); did.cbSize = sizeof(did); DWORD i; for (i=0; SetupDiEnumDeviceInfo(di, i, &did); i++) { if (did.ClassGuid == GUID_DEVCLASS_DISKDRIVE) { ULONG DevLen = 0, DevDiskLen=0; pfc::array_t<WCHAR> Dev, DevDisk, DevRoot; DEVINST pParent = NULL, ppParent = NULL; CM_Get_Parent_Ex(&pParent, did.DevInst, NULL, NULL); CM_Get_Parent_Ex(&ppParent, pParent, NULL, NULL); CM_Get_Device_ID_Size(&DevLen, pParent, NULL); CM_Get_Device_ID_Size(&DevDiskLen, did.DevInst, NULL); Dev.set_size(DevLen+1); Dev.fill_null(); DevDisk.set_size(DevDiskLen+1); DevDisk.fill_null(); CM_Get_Device_ID(pParent, Dev.get_ptr(), Dev.get_size(), NULL); CM_Get_Device_ID(did.DevInst, DevDisk.get_ptr(), DevDisk.get_size(), NULL); { ULONG len = 0; CM_Get_Device_ID_Size(&len, ppParent, NULL); DevRoot.set_size(len+1); DevRoot.fill_null(); CM_Get_Device_ID(ppParent, DevRoot.get_ptr(), len, NULL); } bool b_shuffle; t_ipod_model model; if (g_check_devid_is_ipod(Dev.get_ptr(), model, b_shuffle)) { pfc::array_t<WCHAR> DriverSymbolicPath; if (!wcsncmp(Dev.get_ptr(), DevRoot.get_ptr(), 7)) { ULONG len=0; CM_Get_Device_Interface_List_Size(&len, (LPGUID)&GUID_DEVINTERFACE_USBAPPL_DEVICE, DevRoot.get_ptr(), CM_GET_DEVICE_INTERFACE_LIST_PRESENT); DriverSymbolicPath.set_size(len+1); DriverSymbolicPath.fill_null(); CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_USBAPPL_DEVICE, DevRoot.get_ptr(), DriverSymbolicPath.get_ptr(), len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); //console::formatter() << pfc::stringcvt::string_utf8_from_os(buff.get_ptr()); } else { DriverSymbolicPath.set_size(1); DriverSymbolicPath.fill_null(); } { ULONG DevRemovalListSize = NULL, DevBusListSize = NULL; pfc::array_t<WCHAR> DevRemovalList, DevBusList; CM_Get_Device_ID_List_Size_Ex(&DevRemovalListSize, DevDisk.get_ptr(), CM_GETIDLIST_FILTER_REMOVALRELATIONS, NULL); CM_Get_Device_ID_List_Size_Ex(&DevBusListSize, DevDisk.get_ptr(), CM_GETIDLIST_FILTER_BUSRELATIONS, NULL); DevRemovalList.set_size(DevRemovalListSize); DevBusList.set_size(DevBusListSize); CM_Get_Device_ID_List_Ex(DevDisk.get_ptr(), DevRemovalList.get_ptr(), DevRemovalListSize, CM_GETIDLIST_FILTER_REMOVALRELATIONS, NULL); CM_Get_Device_ID_List_Ex(DevDisk.get_ptr(), DevBusList.get_ptr(), DevBusListSize, CM_GETIDLIST_FILTER_BUSRELATIONS, NULL); WCHAR * ptr = DevRemovalList.get_ptr(), *pvolume=NULL; { t_size ptrlen= NULL; while (ptr && (ptrlen = wcslen(ptr))) { if (!wcsicmp_partial(ptr, L"STORAGE\\")) { pvolume = ptr; break; } ptr+=ptrlen; ptr++; } } if (!pvolume) { ptr = DevBusList.get_ptr(); t_size ptrlen= NULL; while (ptr && (ptrlen = wcslen(ptr))) { if (!wcsicmp_partial(ptr, L"STORAGE\\")) { pvolume = ptr; break; } ptr+=ptrlen; ptr++; } } if (pvolume) { SP_DEVINFO_DATA pdid; memset(&pdid, 0, sizeof(pdid)); pdid.cbSize = sizeof(pdid); HDEVINFO pdi = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);; SetupDiOpenDeviceInfo(pdi, pvolume, NULL, NULL, &pdid); { { DWORD j; SP_DEVICE_INTERFACE_DATA dia; memset(&dia, 0, sizeof(dia)); dia.cbSize = sizeof(dia); for (j=0; SetupDiEnumDeviceInterfaces(pdi, &pdid, &GUID_DEVINTERFACE_VOLUME, j, &dia); j++) { DWORD required_size = 0; pfc::array_t<t_uint8> data; SetupDiGetDeviceInterfaceDetail(pdi, &dia, NULL, NULL, &required_size, &pdid); data.set_size(required_size); data.fill_null(); if (required_size >= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)) { SP_DEVICE_INTERFACE_DETAIL_DATA * didd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)data.get_ptr(); didd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if (SetupDiGetDeviceInterfaceDetail(pdi, &dia, didd, required_size, NULL, &pdid)) { pfc::array_t<WCHAR> path; t_size len = wcslen(didd->DevicePath); path.append_fromptr(didd->DevicePath, len); path.grow_size (len + sizeof(WCHAR)*2); path[len] = '\\'; path[len+1] = 0; WCHAR volumename[129]; memset(&volumename, 0, sizeof(volumename)); if (GetVolumeNameForVolumeMountPoint(path.get_ptr(), volumename, 128)) { volumes.add_item(t_volume(volumename, Dev.get_ptr(), model, b_shuffle, pParent, DriverSymbolicPath.get_ptr())); } } } } } } SetupDiDestroyDeviceInfoList(pdi); } } } } } SetupDiDestroyDeviceInfoList(di); } }