Добрый вечер!
Прошу помочь, срочно надо доделать часть программы:
нужно просто получить соответствие каждого логического диска реальному, физическому диску.
Т.е. что то вроде: std::string getPhysicalDrive(logicalDisk);
Нагуглил несколько вариантов того, как это можно сделать:
1) получить список дисков и использовать
DeviceIOControl(), которая вернет принадлежность диска конкретному накопителю. Пытаюсь запустить код в Visual Studio 2015:
// ConsoleApplication1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#define _WIN32_WINNT 0x501
#include <windows.h>
#include <shlwapi.h>
#include <stdio.h>
int GetDevicePhysicalDiskNumber(LPCTSTR lpszDevice, LPSTR lpszResult, DWORD cchResultMax) // by Napalm
{
HANDLE hDevice;
STORAGE_DEVICE_NUMBER sdNumber;
DWORD dwBytesReturned;
int nResult = 0;
hDevice = CreateFile(lpszDevice, GENERIC_READ, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0,
&sdNumber, sizeof(sdNumber), &dwBytesReturned, NULL))
{
wnsprintf(lpszResult, cchResultMax, "\\\\.\\PhysicalDrive%d", sdNumber.DeviceNumber);
nResult = 1;
}
CloseHandle(hDevice);
}
return nResult;
}
int main(int argc, char *argv[])
{
TCHAR szDrive[MAX_PATH], szPath[MAX_PATH];
// Method one.. not exactly what you want.
StrCpy(szDrive, "C:");
if (QueryDosDevice(szDrive, szPath, MAX_PATH) > 0) {
printf("%s to %s\n", szDrive, szPath);
}
// Method two.. exactly what you want
StrCpy(szDrive, "\\\\.\\C:"); // really "\\.\C:"
if (GetDevicePhysicalDiskNumber(szDrive, szPath, MAX_PATH)) {
printf("%s to %s\n", szDrive, szPath);
}
return 0;
}
Ошибки:
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка C2664 "int wnsprintfW(PWSTR,int,PCWSTR,...)": невозможно преобразовать аргумент 1 из "LPSTR" в "PWSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 25
Ошибка C2664 "PWSTR StrCpyW(PWSTR,PCWSTR)": невозможно преобразовать аргумент 2 из "const char [3]" в "PCWSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 40
Ошибка C2664 "PWSTR StrCpyW(PWSTR,PCWSTR)": невозможно преобразовать аргумент 2 из "const char [7]" в "PCWSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 46
Ошибка C2664 "int GetDevicePhysicalDiskNumber(LPCTSTR,LPSTR,DWORD)": невозможно преобразовать аргумент 2 из "TCHAR [260]" в "LPSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 47
Попробовал поменять LPSTR на LPWSTR PWSTR и прочее ... разные строковые типы как я понимаю (с winapi знаком плохо), но времени вникать в это нет (программу делаю на Qt, нужен лишь небольшой кусок специфичного для Windows кода).
2) Использовать
QueryDosDevice() (см. выше) или
GetVolumeInformation. Эти способы, насколько я понял, хуже в том плане, что на выходе мы получаем не конкретно какой то жесткий диск, а Volume, которому соответствует логический диск. \\Device\Harddisk1\Partition1 ...
Код:
// ConsoleApplication1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iomanip>
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
char szDIR[] = "?:";
char szVolumeName[MAX_PATH] = { 0 };
char szFileSystem[MAX_PATH] = { 0 };
DWORD nVolumeSerialNumber = 0;
DWORD nMaxComponentLength = 0;
DWORD nFileSystemFlags = 0;
while (true)
{
cout << "Enter volume label : "; cin >> szDIR[0];
if
(
!GetVolumeInformation
(
szDIR,
szVolumeName,
MAX_PATH,
&nVolumeSerialNumber,
&nMaxComponentLength,
&nFileSystemFlags,
szFileSystem,
MAX_PATH
)
)
cout << "GetVolumeInformation ERROR : " << strerror(GetLastError()) << endl;
else
if (!CharToOem(szVolumeName, szVolumeName))
cout << "CharToOem ERROR : " << strerror(GetLastError()) << endl;
else
if (!CharToOem(szFileSystem, szFileSystem))
cout << "CharToOem ERROR : " << strerror(GetLastError()) << endl;
else
{
cout << "szVolumeName : " << szVolumeName << endl;
cout << "nVolumeSerialNumber : 0x" << hex << nVolumeSerialNumber << endl;
cout << "nMaxComponentLength : " << nMaxComponentLength << endl;
cout << "nFileSystemFlags : 0x" << hex << nFileSystemFlags << endl;
}
}
return 0;
}
// char* to System::String^
System::String^ CharToSysString(char* ch)
{
char * chr=new char[]=ch;
System::String^ str;
for(int i=0;chr[i]!='\0';i++)
{
str+=wchar_t(ch[i]);
}
return str;
}
Ошибки:
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) аргумент типа "char *" несовместим с параметром типа "LPWSTR" ConsoleApplication1 e:\test\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp 27
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка C2664 "BOOL GetVolumeInformationW(LPCWSTR,LPWSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPWSTR,DWORD)": невозможно преобразовать аргумент 1 из "char [3]" в "LPCWSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 34
Ошибка C2664 "BOOL CharToOemW(LPCWSTR,LPSTR)": невозможно преобразовать аргумент 1 из "char [260]" в "LPCWSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 38
Ошибка C2664 "BOOL CharToOemW(LPCWSTR,LPSTR)": невозможно преобразовать аргумент 1 из "char [260]" в "LPCWSTR" ConsoleApplication1 e:\test\consoleapplication1\consoleapplication1\consoleapplication1.cpp 41
опять что то со строковыми типами и преобразованиями ... вроде бы можно делать преобразования через
WideCharToMultiByte(), но почему тогда эти версии программ работали без преобразований? может мне нужно еще какие то заголовочные файлы подключить? И как тогда пользоваться этой функций - у нее 100500 параметров, как и у остальных API )))
3) Использование
WMI - я сразу отсеял, т.к. пишут что тормозная (все операции проходят на серваке).
Вроде примеры должны работать - долго искал и, кажется, нашел то что нужно, но с ошибками разобраться не могу.
Вообще мне нужно, чтобы программа компилировалась с помощью Qt5 (MinGW) ... собственно на API уже сделано получение списка дисков, файловой системы и т.д. Осталось получение физического диска по имени логического.
Знающие люди, пожалуйста,помогите!)
зы: может есть готовые функции какие то на этот счет?
или есть пример с похожей задачей?
или есть варианты проще? (только не парсить вывод сторонних утилит)
если не жалко, поделитесь)
если это имеет значение: ОС Windows 10, пакет DDK не устанавливал.
UPD:
// ConsoleApplication1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iomanip>
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <Winioctl.h>
#include <cstring>
#include "atlstr.h"
using namespace std;
VOID LogicalToPhysical(TCHAR *szDrive)
{
CString szPhysical;
HANDLE h = CreateFile(szDrive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE != h)
{
STORAGE_DEVICE_NUMBER sd;
DWORD dwRet;
if (DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sd, sizeof(STORAGE_DEVICE_NUMBER), &dwRet, NULL))
{
szPhysical.Format(_T("\\\\.\\PhysicalDrive%d"), sd.DeviceNumber);
cout << szPhysical << " is " << sd.DeviceNumber;
}
CloseHandle(h);
}
}
int main()
{
LogicalToPhysical(_T("\\\\.\\\\C:"));
system("pause");
return 0;
}
удалось скомпилировать это, но программа ничего не выводит. А должна, если я правильно понимаю, вывести номер физического диска? что не так?