How to get serial number for Hard Drive - c++

How to get the unique number (serial number/ID) for Processor (CPU), SCSI, Display, and IDE using C++ program other than WMI and asm code?

Since you mention WMI, I assume you are working on Windows. Lookup GetVolumeInformation().

On Windows you can get CPU info from the environment variable *PROCESSOR_** , you can parse the volume serial number from vol, the MAC address from route print
If you want to make it cross-platform (and if this is for software licensing) then an open source platform like Linux raises the problem to a whole new level anyway and requires a different approach. However you can still get a lot of the info by parsing the output from standard tools.
You really should consider WMI. In the old days, the BIOS would have been helpful but its all been replaced by the HAL.
CodeProject is always worth searching in cases like this.
How To Get Hardware Information

The below is the code I use to retrieve the hard drive serial for a game, so that cheaters are permanently banned (and they can't get back in without getting a new drive!):
string GetMachineID()
{
// LPCTSTR szHD = "C:\\"; // ERROR
string ss;
ss = "Err_StringIsNull";
UCHAR szFileSys[255],
szVolNameBuff[255];
DWORD dwSerial;
DWORD dwMFL;
DWORD dwSysFlags;
int error = 0;
bool success = GetVolumeInformation(LPCTSTR("C:\\"), (LPTSTR)szVolNameBuff,
255, &dwSerial,
&dwMFL, &dwSysFlags,
(LPTSTR)szFileSys,
255);
if (!success) {
ss = "Err_Not_Elevated";
}
std::stringstream errorStream;
errorStream << dwSerial;
return string(errorStream.str().c_str());
}
Although there is a potential bug whereupon if Windows is installed onto a drive other than C:\, this is an easy fix.

Related

The equivelant code %SystemDrive% in batch translated into C++

To anyone that can help Please,
(My operating system is Windows XP)
I have looked on the this forum but have not found a similair answer that I could use or adapt to suite this particular situation. I will try to explain (I apologise in advance if my question seems confusing)
I am constructing a batch file that will call a C++ program (.exe) The C++ program is hard coded to the C: drive. By the way I did not write the C++ program as I am incapable of writing in C++ but would like to exchange the C: in C++ for what would be in batch %SystemDrive%. The line of code in C++ reads as follows:
SetSfcFileException(0, L"c:\\windows\\system32\\calc.exe",-1);
// Now we can modify the system file in a complete stealth.
}
The bit of code I would like to alter in the above code is C: or "C" to change it to %systemDrive% but in C++ code language, in effect change the hard coded part of the C++ program to read a System path variable within XP.
I have also looked elsewhere on the net but have not found a suitable answer as I do Not want to break the C++ code you see.
The C++ code was obtained from the folowing website written by Abdellatif_El_Khlifi:
https://www.codeproject.com/Articles/14933/A-simple-way-to-hack-Windows-File-Protection-WFP-u
Many Thanks for any help given,
David
The search term you should be looking for is Known Folders.
Specifically, calling SHGetKnownFolderPath() with the FOLDERID_System identifier, one of the many IDs found here.
That's for Vista or better. For earlier than that (such as XP), you have to use CSIDL values, CSIDL_SYSTEM (see here for list) passed into SHGetFolderPath().
You can still use the pre-Vista ones but I think they're just thin wrappers around the newer ones.
This is the simplest console application I could come up with that shows this in action (Visual Studio 2019):
#include <iostream>
#include <shlobj_core.h>
#include <comutil.h>
int main()
{
PWSTR path = NULL;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_System, 0, NULL, &path);
_bstr_t bstrPath(path);
std::string strPath((char*)bstrPath);
std::cout << "Path is '" << strPath << "'\n";
}
and the output on my system is:
Path is 'C:\WINDOWS\system32'
This is not really answering my own question, well it is but in a alternative manner, many ways to skin a cat so to speak!
Here is one encouraging bit of news though I have stumbled across the very thing I need called WFPReplacer, it is a commandline windows utility that pretty well does what I want & generally in the same manner. it disables WFP for both singular files & can be used for wholesale switching off of WFP if the right file is replaced. All I need to do is write a batch file as a front end to back up the system files I want to disable use WFPReplacer.exe. So if in the event of the proceedings the routine gets stuffed I can revert back to the backed up files. I think this program uses the same type of embedded coding but is written in Delphi/pascal, it is called Remko Weijnen's Blog (Remko's Blog) "replacing Wfp protected files".
I generally like to leave whatever I am doing on a positive note. So just in case someone else lands on this forum & is trying to accomplish a similair exercise here is the code that one can compile (This is not my code it belongs to Remko Weijnen's Blog (Remko's Blog)) Please be advised it is NOT C++ it is a commandline exe Delhi/Pascal found at this link, so all credits belong to him. The link is:
https://www.remkoweijnen.nl/blog/2012/12/05/replacing-wfp-protected-files/
DWORD __stdcall SfcFileException(RPC_BINDING_HANDLE hServer, LPCWSTR lpSrc, int Unknown)
{
RPC_BINDING_HANDLE hServerVar; // eax#2
int nts; // eax#6
__int32 dwResult; // eax#7
DWORD dwResultVar; // esi#9
int v8; // [sp+8h] [bp-8h]#1
int v9; // [sp+Ch] [bp-4h]#1
LOWORD(v8) = 0;
*(int *)((char *)&v8 + 2) = 0;
HIWORD(v9) = 0;
if ( !hServer )
{
hServerVar = _pRpcHandle;
if ( !_pRpcHandle )
{
hServerVar = SfcConnectToServer(0);
_pRpcHandle = hServerVar;
if ( !hServerVar )
return 0x6BA; // RPC_S_SERVER_UNAVAILABLE
}
hServer = hServerVar;
}
nts = SfcRedirectPath(lpSrc, (int)&v8);
if ( nts >= 0 )
dwResult = SfcCli_FileException((int)hServer, v9, Unknown).Simple;
else
dwResult = RtlNtStatusToDosError(nts);
dwResultVar = dwResult;
MemFree(v9);
return dwResultVar;
}
Also as one further warning (Unless you know what you are doing!!!) do not attempt to use this program, ALWAYS ALWAYS ALWAYS backup your system files before deletion or alteration.
What this program will do is disarm WFP for 60 seconds whilst you intercange or amend your files. Example usage for example is:
WfpReplacer.exe c:\windows\Notepad.exe (Errorlevel true or false will be produced on execution).
Best Regards
David

Close shared files programmatically

The company I'm working with has a program written in ye olde vb6, which is updated pretty frequently, and most clients run the executable from a mapped network drive. This actually has surprisingly few issues, the biggest of which is automatic updates. Currently the updater program (written in c++) renames the existing exe, then downloads and places the new version into the old version's place. This generally works fine, but in some environments it simply fails.
The solution is running this command from microsoft:
for /f "skip=4 tokens=1" %a in ('net files') do net files %a /close
This command closes all network files that are shared (well... most) and then the updater can replace the exe.
In C++ I can use the System(""); function to run that command, or I could redirect the output of net files, and iterate through the results looking for the particular file in question and run net file /close command to close them. But it would be much much nicer if there were winapi functions that have similar capabilities for better reliability and future safety.
Is there any way for me to programmatically find all network shared files and close relevant ones?
You can programmatically do what net file /close does. Just include lmshare.h and link to Netapi32.dll. You have two functions to use: NetFileEnum to enumerate all open network files (on a given computer) and NetFileClose to close them.
Quick (it assumes program is running on same server and there are not too many open connections, see last paragraph) and dirty (no error checking) example:
FILE_INFO_2* pFiles = NULL;
DWORD nRead = 0, nTotal = 0;
NetFileEnum(
NULL, // servername, NULL means localhost
"c:\\directory\\path", // basepath, directory where VB6 program is
NULL, // username, searches for all users
2, // level, we just need resource ID
(LPBYTE*)&pFiles, // bufptr, need to use a double pointer to get the buffer
MAX_PREFERRED_LENGTH, // prefmaxlen, collect as much as possible
&nRead, // entriesread, number of entries stored in pFiles
&nTotal, // totalentries, ignore this
NULL //resume_handle, ignore this
);
for (int i=0; i < nRead; ++i)
NetFileClose(NULL, pFiles[i].fi2_id);
NetApiBufferFree(pFiles);
Refer to MSDN for details about NetFileEnum and NetFileClose. Note that NetFileEnum may return ERROR_MORE_DATA if more data is available.

serial port works in debug but not release c++ code blocks windows

I have an application which performs properly under the CodeBlocks debugger or on the release version if under the bin sub-directory of the project. If the release gets copied to anywhere else it cannot identify or open a serial port on the system. It seems like I must be missing something simple or its not linking to a .lib file.
I use a function to check for existing ports on the system from com1 to com20 when the program starts. Under the project directory it can be connected to a micro-controller device and communication works fine. I use this function to check each port number for existence.
//determine if a serial port does or does not exist
bool getComPortList(std::string portName)
{
bool test;
char* portNumber = new char[portName.length() + 1];
for (unsigned int n = 0; n < portName.length(); n++)
{
portNumber[n] = portName[n];
}
HANDLE testSerial;
testSerial = CreateFile(portNumber, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, NULL, NULL);
if (testSerial == INVALID_HANDLE_VALUE)
{
test = false;
}
else
{
test = true;
}
CloseHandle(testSerial);
delete[] portNumber;
return test;
}
CreateFile is called with an unterminated string. I suggest using portName.c_str() instead of the roll-your-own string portNumber.
Why?
The loop generating portNumber copies the characters in the string, but leaves out the terminating NULL. Odds are pretty good that debug mode politely zeroes portNumber when newed so portNumber comes pre-terminated. Release mode will be compiling for speed and won't perform that which isn't explicitly requested, so no zeroing and no freebie NULL.
Why this works in one folder and not another could just be dumb unluck (Not lucky because an outright crash would be a lot easier to detect) or it could be something more sinister. Regardless, the unterminated string needs fixing.
It sounds like a deployment issue - i.e. running this in the build-environment seems ok, but when you move it "outside" of the environment it does not work "stand-alone".
You can use a free tool like: dependencywalker. Run this on your executable and it will tell you what dlls/libraries you need to copy along with the program to make it run stand-alone.
It might be a bit crude, but without seeing the whole of your project environment its hard to tell what the issue is.
In some build environments (like MS visual studio) you can tell it to include all the dependencies in the executable (makes it quite big).

How to set and read pins on the parallel port from C++?

I am helping a friend to finish a final year project in which he has this circuit that we want to switch on and off using a C++ program.
I initially thought it would be easy, but I have failed to implement this program.
The main problem is that
Windows XP and above don't allow direct access to hardware so some websites are suggesting that I need to write a driver or find a driver.
I have also looked at some projects online but they seem to work for Windows XP but fail to work for Windows 7.
Also, most projects were written in VB or C# which I am not familiar with.
Question:
Is there a suitable driver that works for Windows XP and Windows 7, and if yes how can I use it in my code? (code snippets would be appreciated)
Is there a cross platform way of dealing communicating with parallel ports?
Have a look at codeproject: here, here and here. You'll find treasures.
The 1st link works for Windows 7 - both 32 bit and 64 bit.
You shouldn't need to write a driver or anything -- you just call CreateFile with a filename like "LPT1" to open up a handle to the parallel port, and then you can use WriteFile to write data to it. For example:
HANDLE parallelPort = CreateFile("LPT1", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(parallelPort == INVALID_HANDLE_VALUE)
{
// handle error
}
...
// Write the string "foobar" (and its null terminator) to the parallel port.
// Error checking omitted for expository purposes.
const char *data = "foobar";
WriteFile(parallelPort, data, strlen(data)+1, NULL, NULL);
...
CloseHandle(parallelPort);

Some CPU Information

Well, i we're working on a CPU Controller, which shows all CPU Data. I've managed to get Windows Version, Windows Service Pack, Processor Name, Processor Speed, Processor Identifier(Though Registry Vals).
But now i don't have any idea of how to get the processor Instructions, Caches, Video Card Information (Video Card Name, Available Memory, Total Memory), Southbridge Information (Ethernet Information)
Well, i've been loking on WinAPI but i get it very hard to work. I've looked over google 3 hours but nothing. :/ Any idea? :(
Have you looked at WMI ? This appears to suggest you can get SouthBridge info through WMI.
Gonna expand cppanda's answer a bit:
Concerning video cards, there's sometimes more than one in the system. The best way to get oodles n oodles of information on them is to use DirectX.
If it's meant to be compatible with Vista and up, you can use DXGI, which is cleaner and easier to use in my opinion.
First things first, you'll need to create a DXGI factory...
IDXGIFactory* DXGIFactoryPtr = 0;
HRESULT RetVal = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&DXGIFactoryPtr);
if (FAILED(RetVal)) {/*Error Checking*/;}
then use it to loop through each adapter...
unsigned short I = 0;
IDXGIAdapter* AdapterPtr = 0;
std::vector<IDXGIAdapter*> Adapters;
while (DXGIFactoryPtr->EnumAdapters(I, &AdapterPtr) != DXGI_ERROR_NOT_FOUND)
{
Adapters.push_back(AdapterPtr);
++I;
}
From here, you can see if Direct3D 10 is supported:
if (Adapters[I]->CheckInterfaceSupport(__uuidof(ID3D10Device), 0) == S_OK)
{ /*D3D10 is supported for this device*/; }
Enumerate attached outputs [I.E. Moniters], which could be useful for checking which resolutions are supported and such:
unsigned short J = 0;
IDXGIOutput* OutputPtr = 0;
std::vector<IDXGIOutput*> Outputs;
while (Adapter[I]->EnumOutputs(J, &OutputPtr) != DXGI_ERROR_NOT_FOUND)
{
Outputs.push_back(OutputPtr);
++J;
}
and get a description:
DXGI_ADAPTER_DESC AdapterDescription;
Adapter[I]->GetDesc(&AdapterDescription);
AdapterDescription has the fields Description, VenderId, DeviceId, SubSysId, Revision, DedicatedVideoMemory, DedicatedSystemMemory, SharedSystemMemory, and AdapterLuid.
AdapterLuid is a system specific unique identifier for the card, but all the others should be very obvious given the names.
Beyond that, it becomes vendor specific I think.
For DirectX 9, which is available for Windows 2000 up, it's a bit different. First, you have to create the core Direct3D9 object:
IDirect3D9* D3D9 = Direct3DCreate9(D3D_SDK_VERSION);
if (D3D9 == 0)
{ /* Error checking*/; }
Then get the adapter count:
unsigned short AdapterCount = (unsigned short)D3D9->GetAdapterCount();
Then loop through them, getting their identifiers:
D3DADAPTER_IDENTIFIER9* Identifiers = new D3DADAPTER_IDENTIFIER9[AdapterCount];
HRESULT RetVal = 0;
for (unsigned short I = 0; I < AdapterCount; ++I)
{
RetVal = D3D9->GetAdapterIdentifier(I, 0, &Identifiers[I]);
if (FAILED(RetVal))
{ /* Error checking*/; }
}
Again, most of the fields should be self explanitory. WHQLLevel is information on if and when Microsoft tested that driver's compatability with Windows, and for the most part can be safely ignored. Using close to the same method above, you can also acquire a device's capabilities using GetDeviceCaps, which would give you more information.
As cppanda said, you can use IDirect3DDevice9::GetAvailableTextureMem(), but that requires you to create the device before querying it. Anything the above two don't indicate require creating the device before retrieving it.
Hope that helps~
[Side note, a lot of this was pulled out of the DirectX SDK so code's theirs, not mine.]
Take a look at:
MEMORYSTATUSEX status;
GlobalMemoryStatusEx(&status);
For RAM and Virtual RAM
For video memory
vista:
CreateDXGIFactory API via GetProcAddress()
Below vista, d3d9 API
GetAvailableTextureMemory()
Well, the CPUID instruction gives a bit of info. Not all that you need, but it's a start.