|
Hi,
i'm a beginner in c++, i have already did some little projects but there is many years and i don't remember the most of things. I'm on c#, since many years (+a sickness that ruins my life, not good for the memory).
After several days of research, testing wmi, registry, c# c++/cli etc to measure performance, there was something i would find, how to remote since a drive letter (or path here) to know interface type. I finally found another articles of Raymond Chen, 90% of this code was already written by him i just made the link between and add what was missing. I understood the most of this, but i forgot a lot of syntaxes, memory management and few other things, because most of them are managed by c#. Then i would submit this code to know if there wase some things i could optimize, and most important if i correctly did things to not have an hardware problem beside.
Raymond Chen's blog
Futhermore i hope it will help others.
LPCWSTR filePath = L"H:";
HANDLE volumeHandle = NULL;
HANDLE driveHandle = NULL;
TCHAR volumePath[MAX_PATH]; bool res = GetVolumePathName(filePath, volumePath, ARRAYSIZE(volumePath));
wprintf(L"%s \n", volumePath);
TCHAR volumeName[MAX_PATH]; GetVolumeNameForVolumeMountPoint(volumePath, volumeName, ARRAYSIZE(volumeName));
wprintf(L"%s \n", volumeName);
CString test = volumeName;
test.TrimRight('\\');
LPCWSTR volumeNameWithoutTrailingBackslash = test;
volumeHandle = CreateFile(volumeNameWithoutTrailingBackslash,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
VOLUME_DISK_EXTENTS* extents = nullptr;
VOLUME_DISK_EXTENTS singleExtent;
std::unique_ptr<BYTE[]> lifetime;
DWORD bytesWritten;
if (DeviceIoControl(volumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0,
&singleExtent, sizeof(singleExtent),
&bytesWritten,
nullptr))
{
extents = &singleExtent;
}
else
{
VOLUME_DISK_EXTENTS* lastQuery = &singleExtent;
while (GetLastError() == ERROR_MORE_DATA)
{
assert(RTL_CONTAINS_FIELD(lastQuery, bytesWritten, NumberOfDiskExtents));
DWORD extentCount = lastQuery->NumberOfDiskExtents;
DWORD allocatedSize = FIELD_OFFSET(VOLUME_DISK_EXTENTS, Extents[extentCount]);
lifetime.reset(new BYTE[allocatedSize]);
lastQuery = (VOLUME_DISK_EXTENTS*)lifetime.get();
if (DeviceIoControl(volumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0,
lastQuery, allocatedSize,
&bytesWritten,
nullptr)) {
extents = lastQuery;
break;
}
}
}
if (extents)
{
int physicalDriveNumber = extents->Extents->DiskNumber;
wchar_t physicalDrivePath[80];
swprintf_s(physicalDrivePath, L"\\\\.\\PhysicalDrive%d", physicalDriveNumber);
driveHandle = CreateFile(physicalDrivePath,
0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, 0, nullptr);
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageAdapterProperty;
query.QueryType = PropertyStandardQuery;
DWORD bytesWritten;
STORAGE_ADAPTER_DESCRIPTOR result{};
if (DeviceIoControl(driveHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(query),
&result, sizeof(result),
&bytesWritten, nullptr))
{
printf("Interface type: %d", result.BusType);
}
}
CloseHandle(volumeHandle);
CloseHandle(driveHandle);
At the end, the number give the port used, check Here
|
|
|
|
|
If this is supposed to be an alternative to Raymond Chen's article, then you should post it there.
|
|
|
|
|
Hi, it's not an alternative i just filled the element missing to perform what i need, 90% of the code came from Raymond Chen's blog. I've seen many people would know as me, how to find if a logical drive was usb, etc... I'm not enough good to c++ to make an article with it. I just want to verify with the community if there is no problem with the way i close handle, if there is things i didn't see. Et cetera. c++ code i made by the past was not about windows api, was just simple ui then i gone to java then c# (worst is i have a sickess doing i lost a big part of what i learnt).
About the code, I saw many people using WMI but WMI could reach until 8s as i measured yesterday to retrieve information (i've hard 7 hard drive, 4 in usb 3) what is for a local application is a non-sense. Some others think DriveType is an hard disk is usb, what is false. An hard disk is considerate as "fixed" (Worse is for c# developper as me, there is no all possibilities we have with c++ except by c++/cli and it's not really a good idea to check logical drive by logical drive with c++/cli, it's slow in compareason. We need DriveInfo in c# it's slow.
This is why step by step i search with c++/windows api how to do and have something quick and each time i find an algorithm doing the job (by combining, searching etc...) i post for others. Things evoluted since 2003, and i found hard to sort what it's deprecated, most of answers i found, people use workarounds. And c# get logical drives give me not at all what i need, i'm frustrated .
Sorry for this long post.
|
|
|
|
|
Duc Axenn wrote: I just want to verify with the community if there is no problem The code is technically wrong. But don't worry... it's probably correct 99.99% of the time.
Did you write this code? The top half seems to be written by someone who knows that the file can span across multiple physical disks. The bottom half is incorrectly returning the STORAGE_BUS_TYPE of only the last disk extent.
Microsoft Windows supports spanned volumes[^] which means that in very rare cases a single file might be located on multiple physical disks. Those physical drives could be a mixture of SCSI, SATA, USB, ATAPI, NVME, etcetera...
To make your code more correct you would need to loop through all of those disk extents and return all of the storage bus types[^].
Best Wishes,
-David Delaune
edit: fixed typo
modified 24-May-21 9:06am.
|
|
|
|
|
|
Seriously... i hate myself,
I was so sure that it will be something weird that i 've make a quick refresh of my knowledges on c++, as i said there was years i touch it. I took some notes for the future this time, i'm pretty sure i have already dit it but i don't remember where are this notes... Thanks to that damn sickness.
I can't verify for a spanned volume, if somebody can it will great, last time i tried JODB it was on a netgear NAS that doesn't want anything else except it or raid 1 for the two bay it has. I tried JODB then one of the drives failed i understood how life could be fun...
For the code... if you could give me your feedback, because i recognize it's a bit special to understand how DeviceIOControl works with IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, but finally.. basically by running in debug mode i explored content of extents and realized there were an array... *ù*ù$^% of me. What could say QBert ? "@!#@?!" or something like these. I was so sure to found something weird, another handle with a special iteration behind... No.
Then i modified the part at the end, i let the if conditionnal to avoid problems in case of i retrieve nothing. I don't know if c++ allow to use something like extents?.Extents.Any(). Is there something near that in c++ ?
if (extents)
{
vector<BYTE> interfaces;
for (DWORD i = 0; i < extents->NumberOfDiskExtents; i++)
{
int physicalDriveNumber = extents->Extents->DiskNumber;
wchar_t physicalDrivePath[80];
swprintf_s(physicalDrivePath, L"\\\\.\\PhysicalDrive%d", physicalDriveNumber);
driveHandle = CreateFile(physicalDrivePath,
0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, 0, nullptr);
interfaces.push_back( GetInterfaceType(driveHandle));
}
return interfaces;
}
In the example i stay with int values that could be used as i want, i'm pretty sure i will stay on c#, i want to enhance an existing explorer system i made for my other applications and i don't know for the while how to call a windows written with something else than winform. I don't even know if it's possible.
Do you think it's ok now ? I'm very dumb to didn't see it at the beginning.
Edit --- (Thanks to Randor)
BYTE& Drives::GetInterfaceType(HANDLE& driveHandle)
{
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageAdapterProperty;
query.QueryType = PropertyStandardQuery;
DWORD bytesWritten;
STORAGE_ADAPTER_DESCRIPTOR result{};
if (DeviceIoControl(driveHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(query),
&result, sizeof(result),
&bytesWritten, nullptr))
{
printf("Interface type: %d", result.BusType);
return result.BusType;
}
}
Header
static vector<BYTE> GetPhysicalDrive(wstring path);
static BYTE GetInterfaceType(HANDLE &driveHandle);
modified 25-May-21 6:05am.
|
|
|
|
|
Hi,
The only problem I see this new code snippet is that NumberOfDiskExtents is DWORD (unsigned long) and your for-loop conditional is signed. It's not a big deal but code reviewers might reject it. You didn't show us the definition of your GetInterfaceType() function but I have guessed it just does the STORAGE_PROPERTY_QUERY and returns the STORAGE_BUS_TYPE.
I did see some other issues in your original top post but I refrained mentioning them. You should avoid mixing TCHAR with both CString and LPCWSTR but rather choose Unicode or MBCS and use the same character set throughout your entire project when possible.
Text and Strings in Visual C++[^]
Duc Axenn wrote: Do you think it's ok now? Yes, it works. I compiled it and it found my SATA and NVMe volumes.
Duc Axenn wrote: I'm very dumb to didn't see it at the beginning. You seem like a fast learner, reading code that Raymond Chen wrote; understanding what it does and then extended it. That's fantastic for a beginner. Congratulations and keep up the good work.
Best Wishes,
-David Delaune
|
|
|
|
|
Thanks i will read all of that, it's not as simply as c# ^^.(i must remember DWORD is unsigned, it's more simple with c#, with int or uint,...). I just saw it's a byte value furthermore.
It's true for the function. I think to myself it was implicitly said, but it's true that for the one that never seen it before i should think to put the function.
I was working about how use handle and reference, it's more easy in c# about that.
modified 25-May-21 3:13am.
|
|
|
|
|
Duc Axenn wrote: Thanks You are welcome.
Not sure if you know this... but the username you are using on codeproject perfectly translates to 'Master/Leader of asking questions' in Middle English. Even the alveolarized double nn is period and would indicate that the vowel e is pronounced as a monophthong.
It's probably just a coincidence. But I thought I would mention it.
Best Wishes,
-David Delaune
|
|
|
|
|
lol , i didn't know it, it's cool to learn something new. I took this username on google with reference to The big Lebowski's movie, i'm pretty sure it's a wrong translation. Perhaps it's dude in english but in french he wants to be called The Duc, what is a total paradox with all of he is. It's true that it could interpreted as something pretentious, i'm happy you understood it was not at all for this reason. It's interesting to discover a particularity of another language.
Thanks for all, sinceraly.
- Alexandre CODOUL.
|
|
|
|
|
Hi,
I have a successful Laundrette and Dry Cleaner application written in CPP, and MFC. It is more than 20 years old now.I want to start afresh again, this time using cloud storage. I have the 20 year experience of how such application should work in real time. I now want to move to "The Cloud" for data storage and licensing to get paid. Any suggestions on how to get this started.
Bram.
Bram van Kampen
|
|
|
|
|
What kind of data are you going to store in the "cloud"?
|
|
|
|
|
Hi,
Well Ideally, sets of binary data of my own design, but, essentially a set of databases relating to a number of different customers, who will hold their archives and trading records there, There will also be a number of PDF's and jpeg's, facsimiles of identification documents to comply with local money laundering legislation.
Regards,
Bram.
Bram van Kampen
|
|
|
|
|
What happens if the internet connection goes down ... business stops? Nobody gets their clothes back? I'd use "the cloud" for backup, not as a primary.
Same application ... just sync to the cloud periodically.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Gerry Schmitz wrote: What happens if the internet connection goes down ... business stops? Nobody gets their clothes back? I'd use "the cloud" for backup, not as a primary.
Well, the same ass what happens currently when the electricity goes down, or a disk fails. These things have happened. We close the shop, and indeed on those rare occasions, people get their clothes back via a manual system, but, payment is not asked for. Actually Handing in far processing is far more challenging. We would require an automatic sync at least 10 times per hour.
Bram van Kampen
|
|
|
|
|
You need to find which cloud storage you want to use (google, amazon...)
Then look at the API/SDK they offer.
CI/CD = Continuous Impediment/Continuous Despair
|
|
|
|
|
Well, is there a list of smaller providers? or Intermediaries?
Bram.
Bram van Kampen
|
|
|
|
|
Is there any way I can configure Visual Studio 2019 so that when I build the solution, it automatically builds a 32 bit and a 64 bit version of the same native project at once?
It's a pain to have to keep two different projects in sync to build two different executables.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Only if you share resources with Richard Andrew x32
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
|
You could always have VS build the x86 version and create a PostBuild event bat file and run the MSBuild command line to build the x64 version.
|
|
|
|
|
|
Thank you Victor!
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I spend most of my development time using 64 bit Debug, but have to build both 32/64 and Debug/Release and test before I check in. I call MSBuild from a batch file to build everything. My dev environment is highly customized, and have a post build deployment script that runs and updates all 4 installations automagically to 4 different VMs that I have our products running on. At the end of each build, it triggers automated testing on each of those VMs.
|
|
|
|
|
#include<iostream>
using namespace std;
class calculate
{
private:
int x,y;
public:
void input (int p, int q);
{
x=p;
y=q;
}
void output()
{
cout<<"In sum=" <<(x+y);
cout<<"In product" <<(x*y);
}
};
main()
{
calculate m;
m.input(60,40);
m.output();
}
|
|
|
|
|