Using RegQueryInfoKey() to enumerate COM ports - winapi

Trying to get the number of available comports.
Used the following code:
HKEY hKey;
if (RegOpenKey(HKEY_LOCAL_MACHINE,TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"),&hKey)==ERROR_SUCCESS)
{
DWORD NumKeys;
RegQueryInfoKey(hKey,NULL,NULL,NULL,&NumKeys,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}
For some reason NumKeys returns to be 0, while there are serial ports showing in the registry. It does enters the if (meaning no error with RegOpenKey).
Any ideas?
Thanks,

The port names listed there are values, not keys. Use the lpcValues argument instead.

Related

check if read operation is for spesific file in filter driver

Hello im new at filter driver programming, i took windows swapBuffer example and i try to modify it to pritn me the file name for each read/write operation
and print the data tryed to read/ write.
i tried to do it like this:
FLT_PREOP_CALLBACK_STATUS SwapPreWriteBuffers(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext)
{
/* here we do some logic that check that we want to write more the
0 bytes and get volume context and allocate aligned nonPaged memory
for the "swapping memory" , build a MDL and then if all succeed i try this:
*/
WCHAR filename[300] = {0};
wfprintf(filename, "%wZ\0", Data->Iopb->TargetFileObject->FileName);
if (NULL != wcstr(filename, L"try_me.txt"))
{
DbgPrint("Fname %S try to write %S\n", filename, Data->Iopb->Parameters.Write.WriteBuffe);
}
}
my main problem (i think) Data->Iopb->TargetFileObject->FileName is unicode and i dont know how to make the compae betwine this and a string of the file name
my outher problem is how do i print the buffer curretly to the dbg string without risking at getting blue screen? (i got alot from them laytly...) sometimes i get to this function without writing a string , how do i recognize the different and printing it saftely?
last question , are there any way to nake try except in drivers or all the faults are continue directly to blue screen?
thank you
p.s.
here is the link to the entire code (Without the additions I wrote (which I listed in this post above))
https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/miniFilter/swapBuffers/swapBuffers.c
File name are the concepts at IRP_MJ_CREATE. you can't rely on the name at irp_mj_write or read. so better to do it in create. also try to get the name from FltObject->FileObject->FileName it may give you the desired name of your file aling with other names too.
For printing the written data you need to check for Irp flag in minifilter it is from Data->Iopb->IrpFlags, IRP_PAGING_IO if its true then print the buffer using
KdPrint((".... "));
Yes, you can use try, except in driver too.
Hope this may help.
:)

Find DeviceInterface (SP_DEVICE_INTERFACE_DATA) for DeviceInfo (SP_DEVINFO_DATA)

I am trying to communicate with a USB printer using c-function CreateFile and therefore i need the device path. I know that i can get the device path by SetupDiEnumDeviceInterfaces and SetupDiGetDeviceInterfaceDetail, but for SetupDiEnumDeviceInterfaces i need to give an InterfaceClassGuid as third parameter which I don't know.
My current approach is:
OpenPrinter with the "user friendly" name of the Printer
GetPrinterDataEx with "PnpData" and "DeviceInstanceId" as parameters 2 and 3 which gives me the DeviceInstanceId
ClosePrinter
SetupDiCreateDeviceInfoList (with NULL-parameters)
SetupDiOpenDeviceInfo with the DeviceInstanceId obtained in step 2. Now I have the DeviceInfo of the printer
CM_Get_Parent with the DevInst of the printer (obtained in step 5).
CM_Get_Device_ID of the parent (obtained in step 6)
SetupDiOpenDeviceInfo with the device id obtained in step 7. Now I have the DeviceInfo of the USB-Interface (but not the interface itself) and am almost at the end.
The only missing thing is to get the device interface (SP_DEVICE_INTERFACE_DATA) when I have the SP_DEVINFO_DATA. The other way would be easy: Having the SP_DEVICE_INTERFACE_DATA, I could call SetupDiGetDeviceInterfaceDetail, so basically I am looking for the opposite function of SetupDiGetDeviceInterfaceDetail.
If it would be possible to enumerate ALL interfaces without having to know the InterfaceClassGuid, I could iterate through the list of interfaces and look for the one that is pointing to my device, but unfortunately, this is not possible.
The following articles were very helpful on my way:
Figuring which printer name corresponds to which device ID AND
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/51449be7-a4fa-476b-8cd2-b8933bfa3294/enumerate-multifunction-printer-in-vc?forum=wdk
Am I missing something?
It's been awhile, so I imagine you already found the answer. I'll answer it anyway for someone who may find this question later. I believe the answer is to call SetupDiEnumDeviceInterfaces passing in your SP_DEVINFO_DATA as the second parameter. From the documentation:
A pointer to an SP_DEVINFO_DATA
structure that specifies a device information element in
DeviceInfoSet.
This parameter is optional and can be NULL. If this parameter is
specified, SetupDiEnumDeviceInterfaces constrains the enumeration to
the interfaces that are supported by the specified device. If this
parameter is NULL, repeated calls to SetupDiEnumDeviceInterfaces
return information about the interfaces that are associated with all
the device information elements in DeviceInfoSet. This pointer is
typically returned by SetupDiEnumDeviceInfo.

Is there an issue with using backslashes in registry key names?

I'm writing a small program with QT creator under windows 7 (32 bit). My goal is to create a windows key.
I'm using
QSettings settings("HKEY_CURRENT_USER\\Software\\Company", QSettings::NativeFormat);
settings.setValue("C:\\path\\prog.exe", "Value");
but in the windows registry the generated key has the value C:/path/prog.exe
I've tryed to convert it with
qDebug() << QDir::toNativeSeparators("C:\\path\\prog.exe");
the output of qDebug() is right c:\path\prog.exe
but doing
settings.setValue(QDir::toNativeSeparators("C:\\path\\prog.exe"), "Value");
results again in a path with a wrong slash.
do there is a way to write correctly the path in the windows registry without using the windows API?
Thanks
Francesco
You can't do it even with WinAPI. Because you are specifying an invalid key. You should understand that QSettings class use platform-specific backend, so it is useful to read documentation, if something does not work as expected. Start here.
QSettings class performs custom transformation to keys and values, so you may store any QVariant values there. Even arrays. Invalid values for each platform will be escaped. You may look at exact transformation rules in Qt sources.
Note: values transformation depends on type of settings storage. For example^ for .ini files.
ok, I managed to achieve my goal by using
RegSetValueEx(hkey, TEXT("C:\\path\\prog.exe"), 0, REG_SZ, (LPBYTE)TEXT("WIN98"), 6 * sizeof(WCHAR));
for a constant string.
in case the program path is strored in a char * (like in my case), it works with
char* exe_name = /*something*/
wchar_t* wString=new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, exe_name, -1, wString, 4096);
RegCreateKeyEx( .......... )
RegSetValueEx(hkey, (LPCWSTR) wString, 0, REG_SZ, (LPBYTE)TEXT("WIN98"), 6 * sizeof(WCHAR));
Francesco

Pseudo variable

Can someone please explain me what is a Pseudo Variable and what exactly is the first parameter to the function WinMain below??
GetStartupInfo(&StartupInfo);
int nMainRetVal = WinMain((HINSTANCE)&__ImageBase, NULL, pszCommandLineAnsi,
(StartupInfo.dwFlags & STARTF_USESHOWWINDOW)
? StartupInfo.wShowWindow : SW_SHOWDEFAULT);
Also what does the following statement do??
extern "C" const IMAGE_DOS_HEADER __ImageBase;
The first parameter of WinMain is a so-called "application instance handle". This thing originated from the ancient Windows 3.x times, where it denoted the handle to the running instance of the application. But starting from Win32 (Windows 9x/NT) this parameter is the base address of the executable module mapping in the process virtual address space.
So, what you see is the image base address __ImageBase, which is cast to HINSTANCE to meet the WinMain signature.
Now, __ImageBase - I guess it's a build-time-generated structure that resides exactly at the image starting address.
And, I'm not certain what is a "Pseudo Variable". But perhaps this is exactly __ImageBase.
__ImageBase is the "current module's HINSTANCE from a static library". This is a so called pseudovariable which the linker provides. This pseudovariable is the address where the module has been loaded in memory. Using this pseudovariable you can directly access the mapped image from memory and address its content.

Hiding an entry (or a "fin the registry

I'm trying to hide some values in the registry (such as serial numbers) with C++/windows
so I've been looking at this article http://www.codeproject.com/KB/system/NtRegistry.aspx
which says:
How is this possible? The answer is
that a name which is a counted as a
Unicode string can explicitly include
NULL characters (0) as part of the
name. For example, "Key\0". To include
the NULL at the end, the length of the
Unicode string is specified as 4.
There is absolutely no way to specify
this name using the Win32 API since if
"Key\0" is passed as a name, the API
will determine that the name is "Key"
(3 characters in length) because the
"\0" indicates the end of the name.
When a key (or any other object with a
name such as a named Event, Semaphore,
or Mutex) is created with such a name,
any application using the Win32 API
will be unable to open the name, even
though they might seem to see it.
so I tried doing something similar:
HKEY keyHandle;
PHKEY key;
unsigned long status = 0;
wchar_t *wKeyName = new wchar_t[m_keyLength];
MultiByteToWideChar(CP_ACP, 0, m_keyName, m_keyLength, wKeyName, m_keyLength);
wKeyName[18] = '\0';
long result = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
wKeyName,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&keyHandle,
&status);
where m_keyName is the ASCII text and wKeyName is the wide char text, but in regedit I see that it is treated the same and the key is just cut where I put the '\0'.
what is wrong with it?
The problem is that you are using the Win32 API and not the NT Native API. There is a table about 1/2 way through the article that you referenced that contains the list of Native APIs. For example, you would use NtCreateKey or ZwCreateKey instead of RegCreateKeyExW. The Win32 API assumes that alls strings are terminated by a NUL character whereas the Native API counterparts use a UNICODE_STRING structure for the name.
I'll take a stab in the dark, as I have never tried to do this.
It appears that you are using the wrong function to create your registry key. You should be using the NtCreateKey method because RegCreateKeyEx[AW] will notice your '\0' and chop off past it.
Why not use the class provided in the example? It provides a method called CreateHiddenKey. To use it, simply call SetKey before it. It would be much cleaner.

Resources