|
Just a last note. You are passing 'USB' as class. But the MSDN[^] mentions 'USBDevice'. You may also try using the GUID for USB devices:
const GUID GUID_DEVINTERFACE_USB =
{ 0x88BAE032, 0x5A81, 0x49f0, { 0xBC, 0x3D, 0xA4, 0xFF, 0x13, 0x82, 0x16, 0xD6 }};
|
|
|
|
|
Thanks,
I'll try that.
Even when it fails in one way or another - it generally "returns" GUID ( I am not that far in my coding effords to identify the GUID ) when I ask for all devices.
I also folowed your advice ( and MS) to use
// Pass hRes to FormatMessage() to retrieve the error message
HRESULT hRes = HRESULT_FROM_SETUPAPI(::GetLastError());
and it did not change the error formated message.
Thanks for your help, it is much appreciated.
|
|
|
|
|
Recheck if you are compiling Unicode or not. The in/out size parameter is in bytes, not TCHARs, so you should LocalAlloc (AFAIK) with the returned size and cast to LPTSTR.
Nuclear launch detected
|
|
|
|
|
<pre lang="text">
Thanks Cristian,
I have actually given up on figuring it out, but here is the latest ( with lots of development comments) and it does work as advertized.
NULL, // (PBYTE)buf, // get size with NULL (PBYTE)buffer, // _Out_opt_ PBYTE PropertyBuffer,
0, // sizeof(buf),
With these two parameters set this way , the function fails and returns / sets the &nSize.
I am not checking the errors anymore and just run the same function again with results and it returns true.
The rest of it is just an execise to see the “properties” . And it works.
I am going to check my original code , it is possible that I did forget the cast (PBYTE) buffer, but it is such a mess I am really not looking forward to do that. I was just hoping to delete all the commented out attempts a be done with it. I'll check for unicode too.
Thanks
</pre>
bool C_HWDetect::C_Enumerate()
{
TRACE("\nbool C_HWDetect::C_Enumerate()");
WPARAM wParam; // event wiht parameters !!
CString szClass = "";
/* this monitors changes
DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ?
DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT);
*/
DWORD dwFlag = DIGCF_ALLCLASSES | DIGCF_PRESENT;
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL,"USB", /* szClass,*/ NULL,dwFlag);
if( INVALID_HANDLE_VALUE == hDevInfo ) {
/*
AfxMessageBox(CString("SetupDiGetClassDevs(): ")
+ _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
*/
return false;
}
CString szDevId;
SP_DEVINFO_DATA spDevInfoData;
if ( C_FindDevice(hDevInfo, szDevId, spDevInfoData) ) {
DWORD DataT ;
TCHAR buf[MAX_PATH];
DWORD nSize = 0;
bool bResult = SetupDiGetDeviceRegistryProperty(
hDevInfo, // _In_ HDEVINFO DeviceInfoSet,
&spDevInfoData, // _In_ PSP_DEVINFO_DATA DeviceInfoData
SPDRP_DEVICEDESC, // _In_ DWORD Property,
&DataT, // _Out_opt_ PDWORD PropertyRegDataType,
NULL, // (PBYTE)buf, // get size with NULL (PBYTE)buffer, // _Out_opt_ PBYTE PropertyBuffer,
0, // sizeof(buf), // get size with 0 buffersize,
&nSize); // fills buffer size
bResult = SetupDiGetDeviceRegistryProperty(
hDevInfo, // _In_ HDEVINFO DeviceInfoSet,
&spDevInfoData, // _In_ PSP_DEVINFO_DATA DeviceInfoData
SPDRP_DEVICEDESC, // _In_ DWORD Property,
&DataT, // _Out_opt_ PDWORD PropertyRegDataType,
(PBYTE)buf, // get size with NULL (PBYTE)buffer, // _Out_opt_ PBYTE PropertyBuffer,
sizeof(buf), // get size with 0 buffersize,
&nSize); // fills buffer size
for (int iProperty = 0; iProperty != SPDRP_MAXIMUM_PROPERTY; iProperty++)
{
bResult = SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData,
iProperty /* SPDRP_DEVICEDESC*/ , &DataT, (PBYTE)buf, sizeof(buf), &nSize);
TRACE("\nBuffer Property %i %s ",iProperty, buf);
}
// get Friendly Name or Device Description
if ( SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize) ) {
TRACE("\nBuffer SPDRP_DEVICEDESC %s ",buf);
} else if ( SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize) ) {
TRACE("\nBuffer SPDRP_FRIENDLYNAME %s ",buf);
} else {
lstrcpy(buf, _T("Unknown"));
}
There is one unanswered question - this function <b>SetupDiGetDeviceRegistryProperty</b>either returns description or friendly name. How am I suppose to know which one is really valid to ask for???
SetupDiGetDeviceRegistryProperty
|
|
|
|
|
Let me clean the dust from some old source folder to see if I can get a sample. (If you see I don't reply today, please ping me with another message, thanks).
Nuclear launch detected
|
|
|
|
|
Ok, I found a piece of code inside of one of my projects (I wrote it some 2 years ago, and worked at that time).
class devenum {
private:
devenum();
~devenum();
devenum(const devenum&);
devenum& operator=(const devenum&);
public:
static bool get(vector_t< pair_t< string_t<wchar_t>, string_t<wchar_t> > > & info) {
HDEVINFO hdevinfo = ::SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if(hdevinfo == INVALID_HANDLE_VALUE) {
return false;
}
SP_DEVINFO_DATA did = {0};
did.cbSize = sizeof(did);
for(DWORD i = 0; ::SetupDiEnumDeviceInfo(hdevinfo, i, &did); i++) {
string_t<wchar_t> desc;
if(getDescription(hdevinfo, &did, desc)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L"description", desc);
}
string_t<wchar_t> hwid;
if(getHardwareID(hdevinfo, &did, hwid)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" hardware-id", hwid);
}
string_t<wchar_t> clas;
if(getClass(hdevinfo, &did, clas)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" class", clas);
}
string_t<wchar_t> classGuid;
if(getClassGuid(hdevinfo, &did, classGuid)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" class-guid", classGuid);
}
string_t<wchar_t> address;
if(getAddress(hdevinfo, &did, address)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" address", address);
}
string_t<wchar_t> busnumber;
if(getBusNumber(hdevinfo, &did, busnumber)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" bus-number", busnumber);
}
string_t<wchar_t> bustypeguid;
if(getBusTypeGuid(hdevinfo, &did, bustypeguid)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" bus-type-guid", bustypeguid);
}
}
::SetupDiDestroyDeviceInfoList(hdevinfo);
return true;
}
static bool getDescription(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_DEVICEDESC, str);
}
static bool getHardwareID(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_HARDWAREID, str);
}
static bool getClass(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_CLASS, str);
}
static bool getClassGuid(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_CLASSGUID, str);
}
static bool getAddress(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getDWORD(hdevinfo, pdid, SPDRP_ADDRESS, str);
}
static bool getBusNumber(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getDWORD(hdevinfo, pdid, SPDRP_BUSNUMBER, str);
}
static bool getBusTypeGuid(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getByte(hdevinfo, pdid, SPDRP_BUSTYPEGUID, str);
}
static bool getString(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, DWORD propid, string_t<wchar_t>& str) {
DWORD type = 0;
DWORD bufsiz = 0;
LPWSTR pw = NULL;
bool ok = true;
do {
if(::SetupDiGetDeviceRegistryPropertyW(hdevinfo, pdid, propid,
&type, (PBYTE)pw, bufsiz, &bufsiz)) {
ok = true;
break;
}
if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
ok = true;
if(pw != NULL) {
::LocalFree(pw);
}
pw = (LPWSTR)LocalAlloc(LPTR, bufsiz * 2 + 1);
if(pw == NULL) {
break;
}
}
else {
ok = false;
break;
}
#pragma warning(disable: 4127)
} while(true);
#pragma warning(default: 4127)
if(ok) {
if(pw != NULL) {
str = pw;
}
}
else {
ok = true;
str = L"";
}
if(pw != NULL) {
::LocalFree(pw);
}
return ok;
}
static bool getDWORD(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, DWORD propid, string_t<wchar_t>& str) {
DWORD type = 0;
DWORD bufsiz = 0;
DWORD v = 0;
if(!::SetupDiGetDeviceRegistryPropertyW(hdevinfo, pdid, propid,
&type, (PBYTE)&v, sizeof(DWORD), &bufsiz)) {
str = L"";
return true;
}
WCHAR sz[40] = L"";
swprintf_s(sz, _countof(sz), L"0x%8.8x", v);
str = sz;
return true;
}
static bool getByte(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, DWORD propid, string_t<wchar_t>& str) {
DWORD type = 0;
DWORD bufsiz = 0;
LPBYTE pb = NULL;
bool ok = true;
do {
if(::SetupDiGetDeviceRegistryPropertyW(hdevinfo, pdid, propid,
&type, (PBYTE)pb, bufsiz, &bufsiz)) {
ok = true;
break;
}
if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
ok = true;
if(pb != NULL) {
::LocalFree(pb);
}
pb = (LPBYTE)LocalAlloc(LPTR, bufsiz * 2);
if(pb == NULL) {
break;
}
}
else {
ok = false;
break;
}
#pragma warning(disable: 4127)
} while(true);
#pragma warning(default: 4127)
if(ok) {
if(bufsiz == sizeof(GUID)) {
GUID* guid = (GUID *)pb;
WCHAR sz[40] = L"";
memset(&sz[0], 0, _countof(sz) * sizeof(WCHAR));
int rez = ::StringFromGUID2(*guid, sz, _countof(sz) - 1);
if(rez != 0) {
str = sz;
ok = true;
}
}
}
else {
ok = true;
str = L"";
}
if(pb != NULL) {
::LocalFree(pb);
}
return ok;
}
};
The string_t is a string class, but you can replace it with std::wstring (or a LPWSTR* output variable as well). Same for vector_t, pair_t - you can replace them with STL counterparts std::vector, std::pair with minimal or no changes.
The getDescription is what you are looking for, which in turn calls getString - this is the core of business.
The usage - in my project - is:
vector_t< pair_t< string_t<wchar_t>, string_t<wchar_t> > > info;
devenum::get(info);
I can post somewhere the entire project but the message form does not support attachments. Maybe I will post the entire project here as an article soon.
Regards,
Cristian
Nuclear launch detected
|
|
|
|
|
Cristian,
thanks for the code.
I may "borrow" it if you do not mind.
Am I correct that the property (string) may not be defined , hence one has to check for all possible property or just check for one of interest?
I still do not get the reason for letting the SetupDiGetDeviceRegistryProperty function get the buffer size and still return false. Seems illogical- the function did perform correctly.
|
|
|
|
|
You can use the code, sure - that's why I posted it.
A property string may or may not be defined, although I suppose to do not have description sounds odd from a vendor. SetupDiGetDeviceRegistryProperty can return FALSE, as the documentation says: SetupDiGetDeviceRegistryProperty returns the ERROR_INVALID_DATA error code if the requested property does not exist for a device or if the property data is not valid.
Nuclear launch detected
|
|
|
|
|
Hi,
I shred a file with the implementation of Peter Gutmann's algorithm in C++
but I can't shred a folder yet.
please instuct.
|
|
|
|
|
MehdiHazrati wrote: but I can't shred a folder yet. Why not? Is the code giving an error?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
The code is resposing well, but it is usefull for file shreding, it uses WriteFile() to overwrite on the file.
For shredding a folder I must search the space of the folder & iterate this procedure for all files, and about the subfolder we need a recursive code to traverse them.
Is there any better solution to wipe a folder of shred a whole drive?
Thanks.
|
|
|
|
|
You cannot 'shred' folders in this way, as they are not writable in the same way that files are.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
I thinked that the files of the folder could be deleted in this way and finally the empty folder that is not important can be deleted from the system instructions.
This idea is feasible, but the only concern is about the complexity for the huge folders with various subfolders; it is time consuming.
|
|
|
|
|
MehdiHazrati wrote: it is time consuming. That's why we write programs.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Is there alternative solution to do this?
Specially for wiping a drive
|
|
|
|
|
MehdiHazrati wrote: Specially for wiping a drive Format it, perhaps?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
You can access a volume or physical disk through the CreateFile() [^] function. This would allow you to overwrite all information including the file system tables.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
MehdiHazrati wrote: This idea is feasible, but the only concern is about the complexity for the huge folders with various subfolders; it is time consuming. Have you considered SHFileOperation() or IFileOperation() ? They can recursively delete subfolders.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
From the other responses presumably the following is what you want to do.
1. You want to shred files.
2. You want to shred file information in the directory itself.
For 1 you iterate over files in the directory and recurse through each sub directory and shred each file. You MUST do this. There is no magic solution that would allow you to do it in some other way.
For 2 it is more complex and depends on what you want you think a 'shred' would do. At a minor level you can just rename each file before shredding it. That overwrites the name. For a real shred you would need to
1. Create an API to access the file system at a raw level
2. Parse the file block
3. Shred the relevant file info that was found by step 1. In this case 'shred' includes the same basic methodology employed to shred a file but on a very small scale. You would need to write the shred code yourself.
Note that if you choose to implement the solution above then you MUST back up your hard drive because when you mess up the code you will need to reformat the hard drive. You must also extensively test this feature as well for the same reason. Also account for different file system types (like ssd and usb.)
|
|
|
|
|
thank you for your instructions
but I want to know if there is any way to rewrite the folder area outright and do not delete its files one by one
Regards.
|
|
|
|
|
MehdiHazrati wrote: but I want to know if there is any way to rewrite the folder area outright and
do not delete its files one by one
No.
File systems do not work like that.
|
|
|
|
|
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char again;
do{
printf("insert y or Y to repeat");
fflush(stdout);
scanf("%c",&again);
}while(again=='y'||again=='Y');
}
i wrote this code to create a loop that when insert y or Y do the job again but did not work.when i enter first y the loop be end.
|
|
|
|
|
As mentioned in the QA section: Please don't cross post. I decided to answer you here.
Did you take a look at "again" in the debugger? You will recognize that in the second round thru the loop it will have the value 0x0a == \r it's the carriage return from your input.
You can try something like this to catch the CR:
char cr;
char again;
do
{
printf("insert y or Y to repeat");
fflush(stdout);
again = getchar();
cr = getchar();
}while(again=='y'||again=='Y');
|
|
|
|
|
thank you very much Andy411.its work good.
what do you use
cr = getchar();
what do this code
|
|
|
|
|
How do you learn C? Don't you have a book or a tutoroial with an index?
That's what google answered me:
http://www.cplusplus.com/reference/cstdio/getchar/[^]
PS: Sorry if my answer sounds a bit rude, but I am realy confused about the question what getchar does. If I were you, my first step would be asking google, bing are whatever searchmachine you want. Or taking a look inside a book. If I don't understand the description/answer there, I would ask in a forum again.
|
|
|
|
|