void ProcessManager::InitDriveMappings() { wchar_t volumeName[100]; wchar_t deviceName[150]; wchar_t pathNames[100]; HANDLE fileHandle = FindFirstVolumeW(volumeName, sizeof(volumeName)); if (fileHandle == INVALID_HANDLE_VALUE) return; do { auto index = wcslen(volumeName) - 1; volumeName[index] = L'\0'; auto charCount = QueryDosDeviceW(&volumeName[4], deviceName, sizeof(deviceName)); volumeName[index] = L'\\'; DWORD returned; if (GetVolumePathNamesForVolumeNameW(volumeName, pathNames, sizeof(pathNames), &returned)) { DriveMappings[wxString(deviceName)] = wxString(pathNames); } } while (FindNextVolumeW(fileHandle, volumeName, sizeof(volumeName))); FindClose(fileHandle); }
/* real hardware */ static GList * get_connected_drives (GVolumeMonitor *volume_monitor) { GList *list = NULL; #if 0 HANDLE find_handle; BOOL found; wchar_t wc_name[MAX_PATH+1]; find_handle = FindFirstVolumeW (wc_name, MAX_PATH); found = (find_handle != INVALID_HANDLE_VALUE); while (found) { /* I don't know what this code is supposed to do; clearly it now * does nothing, the returned GList is always NULL. But what was * this code supposed to be a start of? The volume names that * the FindFirstVolume/FindNextVolume loop iterates over returns * device names like * * \Device\HarddiskVolume1 * \Device\HarddiskVolume2 * \Device\CdRom0 * * No DOS devices there, so I don't see the point with the * QueryDosDevice call below. Probably this code is confusing volumes * with something else that does contain the mapping from DOS devices * to volumes. */ wchar_t wc_dev_name[MAX_PATH+1]; guint trailing = wcslen (wc_name) - 1; /* remove trailing backslash and leading \\?\\ */ wc_name[trailing] = L'\0'; if (QueryDosDeviceW (&wc_name[4], wc_dev_name, MAX_PATH)) { gchar *name = g_utf16_to_utf8 (wc_dev_name, -1, NULL, NULL, NULL); g_print ("%s\n", name); g_free (name); } found = FindNextVolumeW (find_handle, wc_name, MAX_PATH); } if (find_handle != INVALID_HANDLE_VALUE) FindVolumeClose (find_handle); #endif return list; }
/* * @implemented (Wine 13 sep 2008) */ HANDLE WINAPI FindFirstVolumeW(IN LPWSTR volume, IN DWORD len) { DWORD size = 1024; HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE ); if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; for (;;) { MOUNTMGR_MOUNT_POINT input; MOUNTMGR_MOUNT_POINTS *output; if (!(output = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); break; } memset( &input, 0, sizeof(input) ); if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, &input, sizeof(input), output, size, NULL, NULL )) { if (GetLastError() != ERROR_MORE_DATA) break; size = output->Size; RtlFreeHeap( RtlGetProcessHeap(), 0, output ); continue; } CloseHandle( mgr ); /* abuse the Size field to store the current index */ output->Size = 0; if (!FindNextVolumeW( output, volume, len )) { RtlFreeHeap( RtlGetProcessHeap(), 0, output ); return INVALID_HANDLE_VALUE; } return (HANDLE)output; } CloseHandle( mgr ); return INVALID_HANDLE_VALUE; }
bool next( ) { if ( h_enum == INVALID_HANDLE_VALUE ) { h_enum = FindFirstVolumeW( volume_path.get( ), c_buf_size ); if ( h_enum == INVALID_HANDLE_VALUE ) { if ( GetLastError( ) == ERROR_NO_MORE_FILES ) { return false; } CHECK_SYS( false ); } } else { BOOL res = FindNextVolumeW( h_enum, volume_path.get( ), c_buf_size ); if ( !res ) { if ( GetLastError( ) == ERROR_NO_MORE_FILES ) { return false; } CHECK_SYS( false ); } } return true; }
/* * @implemented */ BOOL WINAPI FindNextVolumeA(IN HANDLE handle, IN LPSTR volume, IN DWORD len) { WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR)); BOOL ret; if (!buffer) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } if ((ret = FindNextVolumeW( handle, buffer, len ))) { if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE; } RtlFreeHeap(RtlGetProcessHeap(), 0, buffer); return ret; }
void requester_freeze(int *num_vols, void *mountpoints, ErrorSet *errset) { COMPointer<IVssAsync> pAsync; HANDLE volume; HRESULT hr; LONG ctx; GUID guidSnapshotSet = GUID_NULL; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; WCHAR short_volume_name[64], *display_name = short_volume_name; DWORD wait_status; int num_fixed_drives = 0, i; int num_mount_points = 0; if (vss_ctx.pVssbc) { /* already frozen */ *num_vols = 0; return; } CoInitialize(NULL); /* Allow unrestricted access to events */ InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE; vss_ctx.hEventFrozen = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_FROZEN); if (!vss_ctx.hEventFrozen) { err_set(errset, GetLastError(), "failed to create event %s", EVENT_NAME_FROZEN); goto out; } vss_ctx.hEventThaw = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_THAW); if (!vss_ctx.hEventThaw) { err_set(errset, GetLastError(), "failed to create event %s", EVENT_NAME_THAW); goto out; } vss_ctx.hEventTimeout = CreateEvent(&sa, TRUE, FALSE, EVENT_NAME_TIMEOUT); if (!vss_ctx.hEventTimeout) { err_set(errset, GetLastError(), "failed to create event %s", EVENT_NAME_TIMEOUT); goto out; } assert(pCreateVssBackupComponents != NULL); hr = pCreateVssBackupComponents(&vss_ctx.pVssbc); if (FAILED(hr)) { err_set(errset, hr, "failed to create VSS backup components"); goto out; } hr = vss_ctx.pVssbc->InitializeForBackup(); if (FAILED(hr)) { err_set(errset, hr, "failed to initialize for backup"); goto out; } hr = vss_ctx.pVssbc->SetBackupState(true, true, VSS_BT_FULL, false); if (FAILED(hr)) { err_set(errset, hr, "failed to set backup state"); goto out; } /* * Currently writable snapshots are not supported. * To prevent the final commit (which requires to write to snapshots), * ATTR_NO_AUTORECOVERY and ATTR_TRANSPORTABLE are specified here. */ ctx = VSS_CTX_APP_ROLLBACK | VSS_VOLSNAP_ATTR_TRANSPORTABLE | VSS_VOLSNAP_ATTR_NO_AUTORECOVERY | VSS_VOLSNAP_ATTR_TXF_RECOVERY; hr = vss_ctx.pVssbc->SetContext(ctx); if (hr == (HRESULT)VSS_E_UNSUPPORTED_CONTEXT) { /* Non-server version of Windows doesn't support ATTR_TRANSPORTABLE */ ctx &= ~VSS_VOLSNAP_ATTR_TRANSPORTABLE; hr = vss_ctx.pVssbc->SetContext(ctx); } if (FAILED(hr)) { err_set(errset, hr, "failed to set backup context"); goto out; } hr = vss_ctx.pVssbc->GatherWriterMetadata(pAsync.replace()); if (SUCCEEDED(hr)) { hr = WaitForAsync(pAsync); } if (FAILED(hr)) { err_set(errset, hr, "failed to gather writer metadata"); goto out; } AddComponents(errset); if (err_is_set(errset)) { goto out; } hr = vss_ctx.pVssbc->StartSnapshotSet(&guidSnapshotSet); if (FAILED(hr)) { err_set(errset, hr, "failed to start snapshot set"); goto out; } if (mountpoints) { PWCHAR volume_name_wchar; for (volList *list = (volList *)mountpoints; list; list = list->next) { size_t len = strlen(list->value) + 1; size_t converted = 0; VSS_ID pid; volume_name_wchar = new wchar_t[len]; mbstowcs_s(&converted, volume_name_wchar, len, list->value, _TRUNCATE); hr = vss_ctx.pVssbc->AddToSnapshotSet(volume_name_wchar, g_gProviderId, &pid); if (FAILED(hr)) { err_set(errset, hr, "failed to add %S to snapshot set", volume_name_wchar); delete volume_name_wchar; goto out; } num_mount_points++; delete volume_name_wchar; } if (num_mount_points == 0) { /* If there is no valid mount points, just exit. */ goto out; } } if (!mountpoints) { volume = FindFirstVolumeW(short_volume_name, sizeof(short_volume_name)); if (volume == INVALID_HANDLE_VALUE) { err_set(errset, hr, "failed to find first volume"); goto out; } for (;;) { if (GetDriveTypeW(short_volume_name) == DRIVE_FIXED) { VSS_ID pid; hr = vss_ctx.pVssbc->AddToSnapshotSet(short_volume_name, g_gProviderId, &pid); if (FAILED(hr)) { WCHAR volume_path_name[PATH_MAX]; if (GetVolumePathNamesForVolumeNameW( short_volume_name, volume_path_name, sizeof(volume_path_name), NULL) && *volume_path_name) { display_name = volume_path_name; } err_set(errset, hr, "failed to add %S to snapshot set", display_name); FindVolumeClose(volume); goto out; } num_fixed_drives++; } if (!FindNextVolumeW(volume, short_volume_name, sizeof(short_volume_name))) { FindVolumeClose(volume); break; } } if (num_fixed_drives == 0) { goto out; /* If there is no fixed drive, just exit. */ } } hr = vss_ctx.pVssbc->PrepareForBackup(pAsync.replace()); if (SUCCEEDED(hr)) { hr = WaitForAsync(pAsync); } if (FAILED(hr)) { err_set(errset, hr, "failed to prepare for backup"); goto out; } hr = vss_ctx.pVssbc->GatherWriterStatus(pAsync.replace()); if (SUCCEEDED(hr)) { hr = WaitForAsync(pAsync); } if (FAILED(hr)) { err_set(errset, hr, "failed to gather writer status"); goto out; } /* * Start VSS quiescing operations. * CQGAVssProvider::CommitSnapshots will kick vss_ctx.hEventFrozen * after the applications and filesystems are frozen. */ hr = vss_ctx.pVssbc->DoSnapshotSet(&vss_ctx.pAsyncSnapshot); if (FAILED(hr)) { err_set(errset, hr, "failed to do snapshot set"); goto out; } /* Need to call QueryStatus several times to make VSS provider progress */ for (i = 0; i < VSS_TIMEOUT_FREEZE_MSEC/VSS_TIMEOUT_EVENT_MSEC; i++) { HRESULT hr2 = vss_ctx.pAsyncSnapshot->QueryStatus(&hr, NULL); if (FAILED(hr2)) { err_set(errset, hr, "failed to do snapshot set"); goto out; } if (hr != VSS_S_ASYNC_PENDING) { err_set(errset, E_FAIL, "DoSnapshotSet exited without Frozen event"); goto out; } wait_status = WaitForSingleObject(vss_ctx.hEventFrozen, VSS_TIMEOUT_EVENT_MSEC); if (wait_status != WAIT_TIMEOUT) { break; } } if (wait_status == WAIT_TIMEOUT) { err_set(errset, E_FAIL, "timeout when try to receive Frozen event from VSS provider"); /* If we are here, VSS had timeout. * Don't call AbortBackup, just return directly. */ goto out1; } if (wait_status != WAIT_OBJECT_0) { err_set(errset, E_FAIL, "couldn't receive Frozen event from VSS provider"); goto out; } if (mountpoints) { *num_vols = vss_ctx.cFrozenVols = num_mount_points; } else { *num_vols = vss_ctx.cFrozenVols = num_fixed_drives; } return; out: if (vss_ctx.pVssbc) { vss_ctx.pVssbc->AbortBackup(); } out1: requester_cleanup(); CoUninitialize(); }
/* * File system functions */ JNIEXPORT void JNICALL Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) { wchar_t* volumeName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1)); jclass info_class = env->GetObjectClass(info); jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V"); HANDLE handle = FindFirstVolumeW(volumeName, MAX_PATH+1); if (handle == INVALID_HANDLE_VALUE) { free(volumeName); mark_failed_with_errno(env, "could not find first volume", result); return; } wchar_t* deviceName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1)); wchar_t* pathNames = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1)); wchar_t* fsName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1)); while(true) { // Chop off the trailing '\' size_t len = wcslen(volumeName); if (len < 5) { mark_failed_with_message(env, "volume name is too short", result); break; } volumeName[len-1] = L'\0'; if (QueryDosDeviceW(&volumeName[4], deviceName, MAX_PATH+1) == 0) { mark_failed_with_errno(env, "could not query dos device", result); break; } volumeName[len-1] = L'\\'; DWORD used; if (GetVolumePathNamesForVolumeNameW(volumeName, pathNames, MAX_PATH+1, &used) == 0) { // TODO - try again if the buffer is too small mark_failed_with_errno(env, "could not query volume paths", result); break; } wchar_t* cur = pathNames; if (cur[0] != L'\0') { if(GetVolumeInformationW(cur, NULL, 0, NULL, NULL, NULL, fsName, MAX_PATH+1) == 0) { if (GetLastError() != ERROR_NOT_READY) { mark_failed_with_errno(env, "could not query volume information", result); break; } wcscpy(fsName, L"unknown"); } for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) { env->CallVoidMethod(info, method, env->NewString((jchar*)deviceName, wcslen(deviceName)), env->NewString((jchar*)fsName, wcslen(fsName)), env->NewString((jchar*)cur, wcslen(cur)), JNI_FALSE); } } if (FindNextVolumeW(handle, volumeName, MAX_PATH) == 0) { if (GetLastError() != ERROR_NO_MORE_FILES) { mark_failed_with_errno(env, "could find next volume", result); } break; } } free(volumeName); free(deviceName); free(pathNames); free(fsName); FindVolumeClose(handle); }
void WmdmLister::GuessDriveLetter(DeviceInfo* info) { qLog(Debug) << "Guessing drive letter for" << info->name_; // Windows XP puts the drive letter in brackets at the end of the name QRegExp drive_letter("\\(([A-Z]:)\\)$"); if (drive_letter.indexIn(info->name_) != -1) { qLog(Debug) << "Looks like an XP drive" << drive_letter.cap(1); CheckDriveLetter(info, drive_letter.cap(1)); return; } // Windows 7 sometimes has the drive letter as the whole name drive_letter = QRegExp("^([A-Z]:)\\\\$"); if (drive_letter.indexIn(info->name_) != -1) { qLog(Debug) << "Looks like a win7 drive" << drive_letter.cap(1); CheckDriveLetter(info, drive_letter.cap(1)); return; } // Otherwise Windows 7 uses the drive's DOS label as its whole name. // Let's enumerate all the volumes on the system and find one with that // label, then get its drive letter. Yay! wchar_t volume_name[MAX_PATH + 1]; HANDLE handle = FindFirstVolumeW(volume_name, MAX_PATH); forever { // QueryDosDeviceW doesn't allow a trailing backslash, so remove it. int length = wcslen(volume_name); volume_name[length - 1] = L'\0'; wchar_t device_name[MAX_PATH + 1]; QueryDosDeviceW(&volume_name[4], device_name, MAX_PATH); volume_name[length - 1] = L'\\'; // Don't do cd-roms or floppies if (QString::fromWCharArray(device_name).contains("HarddiskVolume")) { wchar_t volume_path[MAX_PATH + 1]; DWORD volume_path_length = MAX_PATH; GetVolumePathNamesForVolumeNameW( volume_name, volume_path, volume_path_length, &volume_path_length); if (wcslen(volume_path) == 3) { ScopedWCharArray name(QString(MAX_PATH + 1, '\0')); ScopedWCharArray type(QString(MAX_PATH + 1, '\0')); DWORD serial = 0; if (!GetVolumeInformationW(volume_path, name, MAX_PATH, &serial, NULL, NULL, type, MAX_PATH)) { qLog(Warning) << "Error getting volume information for" << QString::fromWCharArray(volume_path); } else { if (name.ToString() == info->name_ && name.characters() != 0) { // We found it! qLog(Debug) << "Looks like a win7 drive name" << QString::fromWCharArray(volume_path); if (CheckDriveLetter(info, QString::fromWCharArray(volume_path))) { info->device_name_ = QString::fromWCharArray(device_name); info->volume_name_ = QString::fromWCharArray(volume_name); } break; } } } } if (!FindNextVolumeW(handle, volume_name, MAX_PATH)) break; } FindVolumeClose(handle); }