StorPortGetDeviceInformation yields error and thus cannot use it - windows

I am trying to get my harddisk serial ID by using StorPortGetDeviceInformation, but it gives me an error: identifier StorPortGetDeviceInformation is undefined. I am also seeing an error such as "Error (active) E0020 identifier "PRTL_RUN_ONCE_INIT_FN" is undefined mutante C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\km\ntddk.h 2225 "
I would be happy if someone could take a look at see why this does not work. Below is the code I am using (from an empty Driver Project created in Visual Studio 2022):
#include <Windows.h>
#include <storport.h>
#include <stdio.h>
#include <ntddk.h>
int main()
{
// Enumerate the physical drives on the system
for (int i = 0; i < 256; i++)
{
// Open a handle to the storage device
WCHAR deviceName[32];
swprintf_s(deviceName, L"\\\\.\\PhysicalDrive%d", i);
HANDLE hDevice = CreateFile(deviceName,
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
continue;
}
// Allocate a buffer to hold the serial ID
ULONG serialIdSize = sizeof(STORAGE_DEVICE_ID_DESCRIPTOR);
PSTORAGE_DEVICE_ID_DESCRIPTOR pSerialId =
(PSTORAGE_DEVICE_ID_DESCRIPTOR)malloc(serialIdSize);
if (pSerialId == NULL)
{
printf("Failed to allocate buffer.\n");
CloseHandle(hDevice);
return 1;
}
// Retrieve the serial ID
ULONG bytesReturned;
if (!StorPortGetDeviceInformation(hDevice,
StorageDeviceIdDescriptor, pSerialId, serialIdSize, &bytesReturned))
{
printf("Failed to get device information.\n");
free(pSerialId);
CloseHandle(hDevice);
return 1;
}
// Print the serial ID
printf("Serial ID of disk %d: %S\n", i, pSerialId->Identifiers[0].Identifier);
// Clean up
free(pSerialId);
CloseHandle(hDevice);
}
return 0;
}
What I done so far:
Created an empty driver project
Installed WDK and can be found in C:\Program Files (x86)\Windows Kits\10
Tried to link against the storport.lib library at C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\km\x64\storport.lib
What I expected:
I can call StorPortGetDeviceInformation from my driver.

Related

GetThreadSelectorEntry throwing ERROR_NOT_SUPPORTED for x64 App

I trying to write a very simple app to debug a Win32 64-bit app. My end goal is to get the TIB and PEB of the remote thread, but for some reason the way I did this on 32-bit app is not working for 64-bit ones (Aside from looking at Esp vs Rsp and checking SegFs vs SegGs). The code I'm trying to use is here:
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
int main(int argc, char *argv[]){
LDT_ENTRY entry;
DWORD pid;
HANDLE hThread;
HANDLE hSnapshot;
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;
if(argc < 2){
printf("Usage: %s PID\n", argv[0]);
exit(1);
}
pid = atoi(argv[1]);
THREADENTRY32 te32;
te32.dwSize = sizeof(te32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
while(Thread32Next(hSnapshot, &te32)){
if(pid == te32.th32OwnerProcessID){
hThread = OpenThread(THREAD_ALL_ACCESS, 0, te32.th32ThreadID);
if(!hThread)
exit(1);
if(SuspendThread(hThread) == (DWORD) -1)
exit(1);
if(!GetThreadContext(hThread, &context))
exit(1);
printf("Rsp = 0x%x\n", context.Rsp);
if(!GetThreadSelectorEntry(hThread, context.SegGs, &entry)){
LPSTR buff = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buff, 0, NULL);
printf("Error: %s\n", buff); //ERROR_NOT_SUPPORTED 50 0x32 The request is not supported.
LocalFree(buff);
exit(1);
}
}
}
CloseHandle(hSnapshot);
return 0;
}
but it's always throwing an error at "GetThreadSelectorEntry". The error code that's thrown is ERROR_NOT_SUPPORTED: The request is not supported.
I am not able to understand why it's not supported. Does anyone know why?
[EDIT]
Okay GetThreadSelectorEntry is not available to x86_64 processes, does anyone know how I can get the TIB/PEB addresses of a remote process?

Solution to avoid the error: "Entry point not found " even though I'm checking the OS version before callingGetTcpTable2 api on windows XPindows XP?

I'm aware that the GetTcpTable2 api is supported only on windows vista and above versions, hence the code checks for the OS version and only then enters the loop that calls the api. I'm compiling the code on windows 7, visual studio 2008 and the executable runs fine on windows 7 and other OS except Windows XP, the error thrown is :
The code snippet is:`
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
// Need to link with Iphlpapi.lib and Ws2_32.lib
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
/* Note: could also use malloc() and free() */
int main()
{
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO *)&osvi);
if(osvi.dwMajorVersion>=6)
{
// Declare and initialize variables
PMIB_TCPTABLE2 pTcpTable;
ULONG ulSize = 0;
DWORD dwRetVal = 0;
char szLocalAddr[128];
char szRemoteAddr[128];
struct in_addr IpAddr;
int i;
pTcpTable = (MIB_TCPTABLE2 *) MALLOC(sizeof (MIB_TCPTABLE2));
if (pTcpTable == NULL)
{
printf("Error allocating memory\n");
return 1;
}
ulSize = sizeof (MIB_TCPTABLE);
// Make an initial call to GetTcpTable2 to
// get the necessary size into the ulSize variable
if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) ==
ERROR_INSUFFICIENT_BUFFER)
{
FREE(pTcpTable);
pTcpTable = (MIB_TCPTABLE2 *) MALLOC(ulSize);
if (pTcpTable == NULL)
{
printf("Error allocating memory\n");
return 1;
}
}
}
else
{
printf("Unsupported OS");
}
return 0;
}
`How do I get the executable to work on Windows XP without crashing/throwing the error shown in attached image?

wininet.InternetOpenUrlA ERROR_SXS_ACTIVATION_CONTEXT_DISABLED

I have this program:
#include <string>
#include <iostream>
#include <fstream>
#include <windows.h>
#include <wininet.h>
#include <winsock.h>
#include <stdio.h>
#include <stdarg.h>
using namespace std;
int main()
{
HINTERNET hOpen, hURL;
LPCTSTR NameProgram = "UA"; // LPCWSTR == Long Pointer to Const Wide String
LPCTSTR Website;
char file[101];
unsigned long read;
//Always need to establish the internet connection with this funcion.
if ( !(hOpen = InternetOpen(NameProgram, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 )))
{
cerr << "Error in opening internet" << endl;
return 0;
}
Website = "www.c-jump.com";
hURL = InternetOpenUrl( hOpen, Website, NULL, 0, 0, 0 ); //Need to open the URL
InternetReadFile(hURL, file, 100, &read);
while (read == 100)
{
InternetReadFile(hURL, file, 100, &read);
file[read] = '\0';
cout << file;
}
cout << endl;
InternetCloseHandle(hURL);
return 0;
}
which I've compiled like this:
C:\Users\user\Desktop>cl.exe new.cpp /link "wininet.lib"
Microsoft (R) C/C++ Optimizing Compiler Version 19.10.25019 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
new.cpp
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.10.25017\include\xlocale(314): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.10.25017\include\exception(366): warning C4577: 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
Microsoft (R) Incremental Linker Version 14.10.25019.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:new.exe
wininet.lib
new.obj
I run the exe and get no output, I'm expecting the HTML response from the URL to be printed to stdout. I run the code in a debugger and get the following error returned when the InternetOpenUrlA function returns:
ERROR_SXS_ACTIVATION_CONTEXT_DISABLED (00002EE6)
I'm running Windows on Windows 10.
Could anyone shed any light on what this means and how one could resolve the issue? I had the same code working earlier yesterday and then suddenly it stopped working, with some Windows updates getting installed in between.
Many many thanks
Charlie
The error is probably ERROR_INTERNET_UNRECOGNIZED_SCHEME because your URL does not have a scheme/protocol. Just fix the URL: Website = "http://www.c-jump.com"; Your read loop also has issues, you throw away the first 100 bytes! There is also no guarantee that it can read 100 bytes each time.
You can also attempt to fix the URL:
DWORD DumpResponse(const char *URL)
{
LPCSTR agent = "Stackoverflow Example";
DWORD error, read;
HINTERNET hInet, hConn;
char data[101], urlbuf[INTERNET_MAX_URL_LENGTH];
const char *defscheme = "http";
URL_COMPONENTSA uc;
ZeroMemory(&uc, sizeof(uc));
uc.dwStructSize = sizeof(uc);
BOOL crack = InternetCrackUrlA(URL, 0, 0, &uc);
error = GetLastError();
printf("DBG: InternetCrackUrlA error %d\n", crack ? 0 : error);
if (!crack && error == ERROR_INTERNET_UNRECOGNIZED_SCHEME && strlen(defscheme) + 3 + strlen(URL) < INTERNET_MAX_URL_LENGTH)
{
// Prepend a protocol
sprintf(urlbuf, "%s://%s", defscheme, URL);
URL = urlbuf;
}
else if (!crack)
{
return error;
}
hInet = InternetOpenA(agent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInet) return GetLastError();
hConn = InternetOpenUrlA(hInet, URL, NULL, 0, 0, 0);
error = GetLastError();
if (!hConn)
{
InternetCloseHandle(hInet);
printf("DBG: InternetOpenUrl failed with error %d\n", error);
return error;
}
error = 0;
for (;;)
{
if (!InternetReadFile(hConn, data, sizeof(data) - 1, &read))
{
error = GetLastError();
break;
}
if (0 == read) break; // Done
data[read] = '\0';
printf("%s", data);
}
InternetCloseHandle(hInet);
InternetCloseHandle(hConn);
return error;
}
int main()
{
printf("----\nDumpResponse returned %d\n", DumpResponse("www.c-jump.com"));
}

Format of the serial number of a physical harddrive retrieved using DeviceIoControl()

I retrieve the serial number of the physical hard-drive using the function DeviceIoControl following the suggestions from Blacktempel in this post. Getting the number works fine in principle, but I (still) have trouble with the format of the serial number as it keeps changing from computer to computer and with time. Also I experienced a format change on some computers between running the program as normal user or as admin.
For example, I retrieved a number with the following format:
WD-WCAZAF632086
when I tested the program first and after a few weeks it looks like:
2020202057202d4443575a414641333630323638
This is still the same number, only the characters have been replaced by their hex codes and swapped pair-wise. I've encountered different formats like a normal string with the characters exchanged pair-wise. Among other values, I need to check this number to verify if a software license is valid for a certain computer. Having an instable and unknown format is annoying and if the format changes to something I'm not yet aware of, I risk that the software license check fails although the license is still valid.
Does anyone know how to get the serial number in a stable format, or how to predict the format so it can be adapted for comparison?
Here is minimal C++ example of code that I used to retrieve the serial number of the first physical disc. I build it using Visual Studio 2015:
#include "stdafx.h"
#include "Windows.h"
#include <string>
#include <vector>
#include <iostream>
bool GetDeviceString(std::string &serialnumber)
{
HANDLE deviceHandle = CreateFileW(L"//./PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); // Get Handle to device
if (deviceHandle == INVALID_HANDLE_VALUE) // Check if Handle is valid
return false;
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
DWORD dwBytesReturned;
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
{
}
// Alloc the output buffer
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
std::vector<BYTE> pOutBuffer(dwOutBufferSize,0);
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
pOutBuffer.data(), dwOutBufferSize,
&dwBytesReturned, NULL))
{
// handle error, do cleanup and return
}
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer.data();
const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
if (dwSerialNumberOffset != 0)
{
// Finally, get the serial number
serialnumber = (char*)(pOutBuffer.data() + dwSerialNumberOffset);
}
}
int main()
{
std::string serialnumber;
if (GetDeviceString(serialnumber))
{
std::cout << "serial number of first disc: " << serialnumber << std::endl;
}
else
{
std::cout << "Failed!" << std::endl;
}
std::cin.ignore();
return 0;
}

How to access specific address of a USB drive

I need to access the partition table of a USB stick and change the first byte of partition 0 to make it bootable. And I also want to copy a bin file to a specific address of that USB drive. So can any one tell me how to perform these kind of tasks?
I badly in need of some examples... If you could provide any links of such kinds of works it would be great. I am working in C.
I am in the beginning stage. Here is my code:
// DeviceIoControl.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
BOOL GetMBR(PARTITION_INFORMATION *pdg)
{
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results
hDevice = CreateFile(TEXT("\\\\.\\H:"), // drive to open
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL // do not copy file attributes
);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile() failed!\n");
return (FALSE);
}
bResult = DeviceIoControl(
hDevice, // device to be queried
IOCTL_DISK_GET_PARTITION_INFO, // operation to perform
NULL, 0, // no input buffer
pdg, sizeof(*pdg), // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL // synchronous I/O
);
CloseHandle(hDevice);
return (bResult);
}
int _tmain(int argc, _TCHAR* argv[])
{
PARTITION_INFORMATION pdg; // disk drive geometry structure
BOOL bResult; // generic results flag
ULONGLONG DiskSize; // size of the drive, in bytes
bResult = GetMBR(&pdg);
if (bResult)
{
printf ("BootIndicator %lld\n", pdg.BootIndicator);
printf ("HiddenSectors %lld\n", pdg.HiddenSectors);
printf ("PartitionLength %u\n", pdg.PartitionLength);
printf ("PartitionNumber %u\n", pdg.PartitionNumber);
printf ("PartitionType %x\n", pdg.PartitionType);
printf ("RecognizedPartition %s\n", pdg.RecognizedPartition);
printf ("RewritePartition %ld.\n", pdg.RewritePartition);
printf ("StartingOffset %lld\n", pdg.StartingOffset);
}
else
{
printf ("PARTITION INFORMATION failed. Error %ld.\n", GetLastError ());
}
getchar();
return ((int)bResult);
}
Do you have to do it in code? You can use the built-in diskpart tool to make a USB drive bootable by following this tutorial.

Resources