I searched a bunch and am either not using the right key words or have a unique problem as I haven't found anything specific to what I'm seeing.
I've inherited a project at work, written in C++ and using WindowsAPI, that is supposed to identify USB drives that are currently connected to the machine, display those drives with manufacturer, model and serial number. This is all stored in the registry. Currently the program accesses the desired registry by:
RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"), 0, KEY_READ, &hKey)
Then using a combination of calls to RegQueryInfoKey and RegEnumKeyEx evaluates the key
/#/Control/Linked for each entry, if Linked equals 1 the drive is connected.
This works just fine in Windows 7, the problem I'm having is porting the program to Windows 8.1 It simply doesn't return any USB drives even when they're visible in File Explorer.
Running regedit and comparing Windows 7 and 8.1 what I'm noticing is that in win8.1 when I expand the registries nowhere do I see the Control key when I expand registries, all I get is the # with no value set.
So the question is, am I missing something or did Microsoft make some changes in this regard when moving to Win8.1. If it turns out I can no longer use this registry for this purpose does anyone have a suggestion as to how I may go about doing it?
Thanks is advance for the help.
I doubt reading from that registry key has ever been officially supported and so the fact that it's changed isn't that surprising.
One way you can do this is to use GetLogicalDriveStrings to get a list of drives in your system, and then test if each device is a USB drive using DeviceIoControl with the IOCTL_STORAGE_QUERY_PROPERTY command. This will fill out a STORAGE_DEVICE_DESCRIPTOR structure and the BusType member will be BusTypeUsb for USB devices.
Related
I'm writing a C++ application that is run as Windows Service (Win XP, Vista, 7, 8, servers).
My apllication uses third-patry library that maps local folder to the drive and this drive should be available in user mode (for all users). The problem occurs when user has some network share mapped to the local drive and third-party library doesn't recognize that specified drive letter as already in use.
The question is how to determine (from service application) if required drive letter is definitely available?
I'm using
GetLogicalDrives
QueryDosDevice
to determine logical devices. I've tried
WNetGetConnection
WNetGetUniversalName
to retrieve information about network share, but those functions doesn't return anything for required drive letter despite the fact that there were shares mapped to the specified drive letters.
My guess is that problem is in priveledges. Since my application run as service it can't get information about shares mapped in user mode (which seems very strange to me).
So the final question is - how to detect if specified drive letter is not used for mapping network share by any user?
The problem is in fact that there may be a difference with shares that a user can hold and shares that an admin can hold.
There is a flag in the registry that controls this:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
EnableLinkedConnections = 1 (DWord)
Here is also a MSDN-KB article that explains this. Using EnableLinkedConnections set to 1 should fix this. Usually it is set to 1.
Background: When the UAC was invented this change was one side effect.
Is there any way to programmatically alter the 'BM Options Latency Timer' of a USB<->Serial adapter? Needs to work on embedded windows xp. Can be a .net 2.0 or native windows solution...
I think you are using an FTDI USB serial converter. Then you can use libftdi
And check out the Application Notes (especially AN232B-04) because they contain lots of useful information.
This is driver specific. Your best bet is to do what romkyns says and try to figure out where the driver stores this setting. You will probably need to close and reopen the serial port after changing the setting assuming you are able to find out how it is stored and are able to change it.
As of 2016, the advice in AN232B-04 may be outdated due to changes in the Windows driver infrastructure. Nowadays, there's a requirement to sign all files in a driver package, which means that editing values in a inf/cat file while otherwise using the stock FTDI driver is not possible without re-signing the driver.
If you're using libftdi, you can configure this value at runtime, as per rve's answer. If you prefer to use FTDI's own driver and Windows' standard COM port API, and you need to configure this value, you can still change it permanently and programmatically by editing the registry.
If you go this route, you need to change the DWORD value LatencyTimer under the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_0403+PID_6001+KBxxxxxxx\0000\Device Parameters. KBxxxxxxx in this example needs to be replaced by the serial number of your device. You would need higher privileges to change this value, eg by raising a UAC prompt. The device driver may need to be restarted at that point for the changes to take effect, for example by unplugging and replugging the device.
I have two sound cards on my Win XP SP3 computer, and I've written a C++ app, with which I change the default playback device by editing the following Registry entry:
regKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Multimedia\Sound Mapper", true);
My app changes the "Playback" key value for the purposes of using the first or second sound card as the default playback device.
The problem is when I change the default device, the application still uses the old one (which was set as the default when the program starts). If after change, I launch the application again, everything works fine and I can use the "new" default playback device.
How can I "tell" for my application that I have changed the default device? By what way does the application read and store the variable on starting up which sound device is default in Windows? Is there any solution for my problem?
The Registry is essentially a database that stores the default settings. Modifying the values in the registry does not cause any application, nor Windows itself, to re-initialize its settings with the new, updated values. Raymond Chen discusses this very thing with reference to user interface settings.
Also consider that things like this are very likely to change in later versions of Windows. If you ever decide to update to Windows Vista or 7, you'll be back here again asking more questions because your sound-switcher application won't work anymore. The later versions handle audio devices very differently than they were handled in XP; for starters, they're now based around the Core Audio APIs.
Therefore, for reasons that should be obvious, modifying registry values is not the preferred way to modify your computer's configuration.
But if you're just trying to make a particular application notice that you've changed the value in the registry, the simple solution is the RegNotifyChangeKeyValue function. This essentially subscribes the application to receive notifications each time the value of a particular registry key changes.
The correct solution for Windows Vista and later is available here.
For a requirement to generate per-PC license keys, I need some code which will return a stable and (near) unique key on any PC. It doesn't have to be guaranteed unique, but close. It does need to be reasonably stable though, so that a given PC always generates the same result unless the hardware is substantially changed.
This is for a Windows application, using wxWidgets but a Win32 or other option is fine.
I was thinking about MAC address but what about laptops which can routinely disable the network card in power-saving mode? I came across GetCurrentHwProfile but it doesn't quite look like what I want?
One idea I had a while back for this is to use CryptProtectData as a way to identify a machine. Behind-the-scenes in that API, Microsoft has done what you're looking for. I never tested it though and I'm curious if it's actually viable.
Basically you would encode a constant magic value with CryptProtectData with CRYPTPROTECT_LOCAL_MACHINE, and the result is your machine ID.
I would just go with the MAC address method; when the wireless / LAN cards are turned off they still show up in Network Connections. You should therefore still be able to get the MAC.
Consider this: Any time you'd be able to contact your webserver or whatever you're cataloging these IDs with, the user is going to have to have some form of network card available.
Oh, and you might be able to use CPU serial number of the customer's computer supports it.
I think there no really easy and unique method so far discovered here.
GetVolumeInformation retrieves not even close to unique ID.....
To use any hardware serial is problematic because manufactures are not committed to supported it always and especially to keep it globally unique
GetCurrentHwProfile retrieves GUID but it's value affected by minor! hardware changes...
Using Product Key ... will bring U to deal with the stolen software - there lot of pirate installations over the globe.
Creation of own GUID and preserving it under registry (in any place) will not prevent duplication by cloning of image ....
etc...
From my perspective of view the best way is combine:
Volume ID + MAC's list + Machine SID + Machine Name. And obviously manage license policy on the server side ;0)
Regards
Mickel.
If you want something a bit harder to spoof than whatever the machine itself can tell you, you'll probably need to provide a USB dongle dedicated for this purpose (not just a flash drive).
For a pretty brain dead test I am using the ProductID code of the OS and the computer name - both extracted from the registry. Not really secure, but its all pretend security anyway.
edit
To answer John's question about what keys I am reading:
SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductID
SYSTEM\CurrentControlset\Control\ComputerName\ComputerName\ComputerName
How about using the serial number of the harddisk where windows is installed?
The function GetVolumeInformation() will give you such serial number.
To access the ID assigned by the harddisk vendor instead of the ID assigned by Windows, you can use the Win32_PhysicalMedia Class.
To determine the drive where windows is installed, you could expand the variable %windir" by using the function ExpandEnvironmentStrings()
Another option, if your architecture allows, is to use UuidCreate() to generate a random GUID at installation time and save it permanently in the registry. This GUID can then be used as the ID as long as the registry remains. A new registry database is generally considered as a new installation.
A third option is to have a well-known server assigning the IDs. Upon starting up, the software could look up for the ID in the registry and if not found, would contact the server and supply it with its MAC address, hostname, harddisk serial number, Machine SID and any number of indentifyable information (keys).
The server then determines if the client is already registered or not based on the information given. The server could have a relaxed policy and for example only require most of the keys for a match, so that the mechanism would work even in the event of a complete wipe out of the registry and if part (but not all) of the hardware was replaced.
How about using the serial number of a CPU. I remember Microsoft used to provide an api for this that would run the necessary assembler code and give you back all sorts of info about the CPU including serial number. Not sure if it'd work with AMD chips or not, I think it was intel specific.
Surely CPU Id is secure and static enough!!
I'm playing around with retrieving the MAC address from the NIC - there are a variety of ways to get it, this article covers the most common:
http://www.codeguru.com/Cpp/I-N/network/networkinformation/article.php/c5451
I'm currently using the GetAdaptersInfo method, which seems the most bulletproof, but if the MAC address has been set via the registry:
http://www.mydigitallife.info/2008/06/30/how-to-change-or-spoof-mac-address-in-windows-xp-vista-server-20032008-mac-os-x-unix-and-linux/
Then it reports the MAC address that it has been changed to. The only way I've found to actually get the true MAC is to remove the registry entry, restart the NIC, get the MAC via GetAdaptersInfo, then replace the registry entry, and restart the NIC. While it gets the job done, it's hardly transparent to the user.
Is there any other methods that anyone is familiar with, that will return the hardware MAC regardless of what the registry is set to? Ideally I'd like a solution that works on XP on up.
Thanks in advance!
My guess is that in the linked CodeGuru article, the Miniport solution is likely to overcome the problem you describe, albeit painful to implement. The reason I think this is that I have used the GetAdaptersInfo solution myself in the past, and noticed that the MAC address will change without reboot when an adapter is added, e.g. a Bluetooth adapter providing PAN services.
Perhaps rather than rebooting after changing the registry setting, you could try stopping and restarting the relevent network services. You could easily check this manually prior to looking for a programmatic solution.
(n.b. the above is all guess work. If you try it and it works, perhaps add a post for those trying to do the same in future).
Parse the output of ipconfig /all
You can use WMI to enumerate the Win32_NetworkAdapter instances and look at the MACAddress property. The main issue with this technique is finding the appropriate adapter instance if you have multiple active adapters installed, e.g. on a laptop which also has a wireless connection.