First of all, I want to access all icons (16x16...256x256 and larger) in a ".exe" file.
As a result of my research, I found such code:
#ifndef __ICON_LIST_H__
#define __ICON_LIST_H__
#include <windows.h>
#include <vector>
class IconFile: public std::vector<HICON>{
public:
IconFile(){};
IconFile(std::string i_filename){
addIconsFromFile(i_filename);
};
int addIconsFromFile(std::string i_fileName){
int iCount=0;
HANDLE file = CreateFile( i_fileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if(file!=INVALID_HANDLE_VALUE){
int size = GetFileSize(file,NULL);
DWORD actRead;
BYTE* buffer = new BYTE[size];
ReadFile(file, buffer, size, &actRead, NULL);
CloseHandle(file);
int ind = -1;
for(int p = 0; p< size-4; ++p){
if(buffer[p]==40 && buffer[p+1]==0 && buffer[p+2]==0 && buffer[p+3]==0){
HICON icon = CreateIconFromResourceEx(&buffer[p], size-p, true, 0x00030000,0,0,0);
if(icon){
++iCount;
this->push_back(icon);
}
}
}
delete[] buffer;
}
return iCount;
};
};
#endif //__ICON_LIST_H__
This code works fine but doesn't show 256x256 or larger icon, Code output:
std::vector(0x8ef2013, 0x64ce1867, 0x24681219)
Currently, this is the icon list of the file:
How can I get the 256x256 icon?
Use LoadLibraryEx to load the file, EnumResourceNames to enumerate icons, and CreateIconFromResourceEx to lead each icon.
Note that driving a class from std::vector and other C++ Standard Library containers is not recommended.
The example below uses LR_SHARED, you might want to change that.
#include <windows.h>
#include <vector>
BOOL CALLBACK EnumIcons(HMODULE hmodule, LPCTSTR type, LPTSTR lpszName,
LONG_PTR ptr)
{
if (!ptr)
return FALSE;
auto pvec = (std::vector<HICON>*)ptr;
auto hRes = FindResource(hmodule, lpszName, type);
if (!hRes)
return TRUE;
auto size = SizeofResource(hmodule, hRes);
auto hg = LoadResource(hmodule, hRes);
if (!hg)
return TRUE;
auto bytes = (BYTE*)LockResource(hg);
auto hicon = CreateIconFromResourceEx(bytes, size, TRUE, 0x00030000,
0, 0, LR_SHARED);
if (hicon)
pvec->push_back(hicon);
return TRUE;
}
int main()
{
std::vector<HICON> vec;
const char* modulepath = "file.exe";
HMODULE hmodule = LoadLibraryEx(modulepath, NULL,
LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (!hmodule)
return 0;
EnumResourceNames(hmodule, RT_ICON,(ENUMRESNAMEPROC)EnumIcons,(LONG_PTR)&vec);
for (auto e : vec)
{
ICONINFOEX ii = { sizeof(ii) };
if (!GetIconInfoEx(e, &ii) || !ii.hbmColor)
continue;
BITMAP bm;
GetObject(ii.hbmColor, sizeof(bm), &bm);
printf("%d %d %d\n", bm.bmWidth, bm.bmHeight, bm.bmBitsPixel);
}
//free icons...
return 0;
}
Related
In my code I have a call to the GetRawInputDeviceInfo function, passing in the RIDI_DEVICENAME command. It is supposed to fill the 3rd parameter with a string containing the name of the buffer, and return the length of the string.
However, when the function returns, that parameter points to invalid memory (inside the debugger it says 0x234449485c3f5c5c, and can't view the contents of it).
This is the complete code:
#include <windows.h>
#include <stdint.h>
#define assert(x) do{if(!(x))__debugbreak();}while(0)
typedef size_t usize;
typedef uint8_t u8;
typedef unsigned int uint;
struct Raw_Input_Memory {
usize size;
usize used;
u8 *data;
};
#define raw_input_memory_push_array(memory, type, count) (type *)raw_input_memory_push_size(memory, sizeof(type) * count)
#define raw_input_memory_push_struct(memory, type) (type *)raw_input_memory_push_size(memory, sizeof(type))
void *raw_input_memory_push_size(Raw_Input_Memory *memory, usize size) {
assert(memory->used + size <= memory->size);
void *result = memory->data + memory->used;
memory->used += size;
return result;
}
int main() {
HINSTANCE module_instance = GetModuleHandle(NULL);
WNDCLASSA window_class = {};
window_class.lpfnWndProc = DefWindowProc;
window_class.hInstance = module_instance;
window_class.hCursor = LoadCursorA(NULL, IDC_ARROW);
window_class.lpszClassName = "Toplevel";
ATOM window_class_atom = RegisterClassA(&window_class);
if (window_class_atom) {
HWND window = CreateWindowA(window_class.lpszClassName, "Raw Input",
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, module_instance, NULL);
if (window) {
Raw_Input_Memory raw_input_memory = {};
raw_input_memory.size = 1024 * 1024;
raw_input_memory.used = 0;
raw_input_memory.data = (u8 *)VirtualAlloc(NULL, raw_input_memory.size,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
RAWINPUTDEVICE raw_input_device;
raw_input_device.usUsagePage = 0x01;
raw_input_device.usUsage = 0x05;
raw_input_device.dwFlags = 0;
raw_input_device.hwndTarget = 0;
if (RegisterRawInputDevices(&raw_input_device, 1,
sizeof(RAWINPUTDEVICE))) {
MSG window_message = {};
while (GetMessageA(&window_message, NULL, 0, 0) > 0) {
UINT message_kind = window_message.message;
WPARAM wparam = window_message.wParam;
LPARAM lparam = window_message.lParam;
switch (message_kind) {
case WM_QUIT: {
break;
} break;
case WM_INPUT: {
if (raw_input_memory.data) {
raw_input_memory.used = 0;
UINT input_size;
if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &input_size,
sizeof(RAWINPUTHEADER)) != -1) {
RAWINPUT *input = (RAWINPUT *)raw_input_memory_push_size(&raw_input_memory,
input_size);
if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, input,
&input_size, sizeof(RAWINPUTHEADER)) == input_size) {
assert(input->header.dwType == RIM_TYPEHID);
uint device_name_length = 128;
char *device_name = NULL;
device_name = raw_input_memory_push_array(&raw_input_memory, char,
device_name_length);
assert(device_name);
INT got_device_name = GetRawInputDeviceInfoA(input->header.hDevice,
RIDI_DEVICENAME,
&device_name,
&device_name_length);
if (got_device_name) {
/* ... */
}
}
}
}
} break;
default: {
TranslateMessage(&window_message);
DispatchMessageA(&window_message);
}
}
}
}
}
}
return 0;
}
Note that the call doesn't explicitly fail: it doesn't return -1 nor 0, but 83; and GetLastError returns 0.
I've tried both allocating the memory myself (as you can see in the code I posted) and passing in a NULL pointer, and both have the same result. I tried the wide version too, and I still get an 83 as a return value and a pointer to 0x005c003f005c005c, which is still invalid.
What am I doing wrong? Why does the function pass me invalid memory and how do I stop it from doing so? I've seen this answer, and this other answer, and read the docs. I don't know what else to do.
By the way, I'm trying it with a PS4 controller.
https://learn.microsoft.com/ko-kr/windows/win32/api/virtdisk/nf-virtdisk-querychangesvirtualdisk?redirectedfrom=MSDN
DWORD QueryChangesVirtualDisk(
HANDLE VirtualDiskHandle,
PCWSTR ChangeTrackingId,
ULONG64 ByteOffset,
ULONG64 ByteLength,
QUERY_CHANGES_VIRTUAL_DISK_FLAG Flags,
PQUERY_CHANGES_VIRTUAL_DISK_RANGE Ranges,
PULONG RangeCount,
PULONG64 ProcessedLength
);
I am trying to get difference between two virtual disk or two Resillent Change Tracking ID (RCT)
but RangeCount always return as 0
I opened virtual disk file (vhdx) with two enum parameter VIRTUAL_DISK_ACCESS_GET_INFO, OPEN_VIRTUAL_DISK_FLAG_NONE
opStatus = OpenVirtualDisk(
&storageType,
VirtualDiskPath,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
NULL,
&vhdHandle ); // output handle
then use QueryChangesVirtualDisk()
opStatus = QueryChangesVirtualDisk(
vhdHandle,
ChangeTrackingId,
0,
32212254720,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
pRctRanges,
&rctRangeCnt,
&processedLength
);
OpenVirtualDisk() QueryChangesVirtualDisk()
Both function did not return error but in every case RangeCount always has a value of 0
There is definitely a difference between virtual disk file and RCT ID
please give me some advice
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <initguid.h>
#include <strsafe.h>
#include <virtdisk.h>
#include "Storage.h"
DWORD QueryChangesVirtualDisk(_In_ LPCWSTR VirtualDiskPath, _In_ LPCWSTR ChangeTrackingId)
{
VIRTUAL_STORAGE_TYPE storageType;
PGET_VIRTUAL_DISK_INFO diskInfo;
ULONG diskInfoSize;
DWORD opStatus;
HANDLE vhdHandle;
QUERY_CHANGES_VIRTUAL_DISK_RANGE *pRctRanges;
ULONG rctRangeCnt;
ULONG64 processedLength;
UINT i;
vhdHandle = INVALID_HANDLE_VALUE;
diskInfo = NULL;
diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);
rctRangeCnt = 0L;
processedLength = 0L;
pRctRanges = NULL;
i = 0;
diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
if (diskInfo == NULL)
{
opStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;
//////////////////////////////////////////////////////////////////
opStatus = OpenVirtualDisk(
&storageType,
VirtualDiskPath,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
NULL,
&vhdHandle);
if (opStatus != ERROR_SUCCESS)
{
wprintf(L"OpenVirtualDisk fail\n");
goto Cleanup;
}
opStatus = QueryChangesVirtualDisk(
vhdHandle,
ChangeTrackingId,
0,
32212254720,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
pRctRanges,
&rctRangeCnt,
&processedLength
);
wprintf(L"rctRangeCnt : %lu\n", rctRangeCnt);
wprintf(L"processedLength : %llu\n", processedLength);
for (i = 0; i < rctRangeCnt; i++)
{
wprintf(L"ByteOffset : %lld ByteLength : %lld\n", pRctRanges[i].ByteOffset, pRctRanges[i].ByteLength);
}
if (opStatus != ERROR_SUCCESS)
{
wprintf(L"QueryChangesVirtualDisk fail\n");
goto Cleanup;
}
Cleanup:
if (opStatus == ERROR_SUCCESS)
{
wprintf(L"success\n");
}
else
{
wprintf(L"error = %u\n", opStatus);
}
if (vhdHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(vhdHandle);
}
if (diskInfo != NULL)
{
free(diskInfo);
}
if (pRctRanges != NULL)
{
for (i = 0; i < rctRangeCnt; i++)
{
free(&pRctRanges[i]);
}
}
return opStatus;
}
The problem is that you pass a null-pointer for the Ranges argument and zero for RangeCount.
For Ranges you're supposed to pass a pointer to the first element or an array of QUERY_CHANGES_VIRTUAL_DISK_RANGE elements, and the RangeCount should be initialized to the number of elements in that array.
When the QueryChangesVirtualDisk function returns it will have modified RangeCount to be the number of initialized elements in the Ranges array.
From the documentation you linked to, about the RangeCount argument:
On input, the value indicates the number of QUERY_CHANGES_VIRTUAL_DISK_RANGE structures that the array that the Ranges parameter points to can hold. On output, the value contains the number of QUERY_CHANGES_VIRTUAL_DISK_RANGE structures that the method placed in the array.
In short: The function doesn't create this array for you, you must do it before you call the function.
Within the property window of a JPEG image, there is a tab called 'Summary'. Within this tab, there is a field called 'Comments' I would like to write some MFC code which will add a given string to this field e.g "This is a photo".
Does some kind soul out there know how to do this?
Many thanks.
MFC doesn't provide this functionality, however you can use GDI+ for the task. The Image class is capable of reading and writing Exif metadata.
This is almost trivial, and explained under Reading and Writing Metadata. However, since the UserComment metadata tag allows for different character encodings, things get a little more involved. The following code1) implements a command line utility that allows to set (or replace if present) the UserComment field:
#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "Gdiplus.lib")
int wmain( int argc, const wchar_t* argv[] ) {
// Input format: AddExifComment "<input filename>" "<comment>" "<output filename>"
if (argc != 4)
return -1;
// Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken{ 0 };
GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, nullptr );
// Load image
Image* img = new Image(argv[1]);
// Construct Unicode comment
const auto& comment = MakeUnicodeComment(argv[2]);
// Assign the UserComment property
PropertyItem propertyItem;
propertyItem.id = PropertyTagExifUserComment;
propertyItem.length = comment.size();
propertyItem.type = PropertyTagTypeUndefined;
propertyItem.value = (void*)comment.data();
img->SetPropertyItem(&propertyItem);
// Save image
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
img->Save(argv[3], &clsid);
// Cleanup
delete img;
GdiplusShutdown(gdiplusToken);
return 0;
}
Constructing an appropriately formatted comment takes a bit of work. This is implemented in the following function:
#include <vector>
using std::vector;
#include <iterator>
using std::back_inserter;
vector<BYTE> MakeUnicodeComment(const wchar_t* text){
// Exif 2.2 header for Unicode (UCS-2): 'U', 'N', 'I', 'C', 'O', 'D', 'E', '\0'
static const char header[]{"UNICODE"};
static const size_t headerSize{ sizeof(header) / sizeof(header[0]) };
// UserComment field contains the 8-byte header followed by UTF-16LE encoded code units
vector<BYTE> buffer;
std::copy(header, header + headerSize, back_inserter(buffer));
// Append comment text (NUL terminator is not required)
auto current = text;
while (*current) {
buffer.push_back(*current & 0xFF);
buffer.push_back((*current >> 8) & 0xFF);
++current;
}
return buffer;
}
Retrieving the JPEG encoder from its MIME type is copied from Retrieving the Class Identifier for an Encoder for reference:
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j) {
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
1) Error handling elided for brevity.
OK,Finally I manage to solove the problem!There is the code:
OK,Finally I manage to solove the problem!There is the code:
#include "stdafx.h"
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num= 0;
UINT size= 0;
ImageCodecInfo* pImageCodecInfo= NULL;
GetImageEncodersSize(&num, &size);
if(size== 0)
{
return -1;
}
pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo== NULL)
{
return -1;
}
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j=0; j< num; ++j)
{
if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
{
*pClsid= pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
// load bitmap from memory,sync way
Bitmap* LoadBitmapFromMemory(const void* memory, DWORD size)
{
Bitmap* bmp = NULL;
IStream* stream = NULL;
if (CreateStreamOnHGlobal(NULL, TRUE, &stream) == S_OK)
{
ULARGE_INTEGER uli;
uli.QuadPart = size;
stream->SetSize(uli);
if (stream->Write(memory, size, NULL) == S_OK)
bmp = new Bitmap(stream);
stream->Release();
}
return bmp;
}
// load bitmap from file,sync way
Bitmap* LoadBitmapFromFile(const TCHAR* file_name)
{
Bitmap* bmp = NULL;
HANDLE file_handle = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file_handle != INVALID_HANDLE_VALUE)
{
DWORD temp = 0;
DWORD file_size = GetFileSize(file_handle, &temp);
if (file_size && !temp) // the file must be less than 4G
{
unsigned char* buffer = new unsigned char[file_size];
if (ReadFile(file_handle, buffer, file_size, &temp, NULL))
bmp = LoadBitmapFromMemory(buffer, temp);
delete [] buffer;
}
CloseHandle(file_handle);
}
return bmp;
}
int _tmain(int argc, _TCHAR* argv[])
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Status stat;
CLSID clsid;
char propertyValue[] = "Fake Photograph";
Bitmap* bitmap = LoadBitmapFromFile(L"E:/sandbox/stone.jpg");
PropertyItem* propertyItem = new PropertyItem;
// Get the CLSID of the JPEG encoder.
GetEncoderClsid(L"image/jpeg", &clsid);
propertyItem->id = PropertyTagCopyright;
propertyItem->length = 16; // string length including NULL terminator
propertyItem->type = PropertyTagTypeASCII;
propertyItem->value = propertyValue;
bitmap->SetPropertyItem(propertyItem);
stat = bitmap->Save(L"E:/sandbox/stone.jpg", &clsid, NULL);
if(stat == Ok)
printf("FakePhoto2.jpg saved successfully.\n");
delete propertyItem;
delete bitmap;
GdiplusShutdown(gdiplusToken);
return 0;
return 0;
}
when I run this code on g++ , it runs smoothly, but when I run this code on visual studio wiith unicode char set option, it doesn't print product id.
can you explain me how to fix this problem and why it happens?
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
wchar_t* GetRegistryKeyValue(const char* RegKey, const char* pPIDName)
{
HKEY Registry;
long ReturnStatus;
DWORD regType = 0;
DWORD regSize = 0;
char* pPID = 0;
ReturnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegKey, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &Registry);
if (ReturnStatus == ERROR_SUCCESS)
{
ReturnStatus = RegQueryValueEx(Registry, pPIDName, 0, ®Type, 0, ®Size);
pPID = new char[regSize];
/* Get Value. */
ReturnStatus = RegQueryValueEx(Registry, pPIDName, 0, ®Type, (LPBYTE)pPID, ®Size);
RegCloseKey(Registry);
if (pPID[regSize] > 127 || pPID[regSize] < 32)
{
pPID[regSize] = '\0';
}
if (regSize > 1)
{
int s = 0;
int i=0;
while (pPID[i] != NULL)
{
s++;
i++;
}
const size_t cSize = s ;
wchar_t* wc = new wchar_t[cSize];
mbstowcs(wc, pPID, cSize);
return wc;
}
else
{
printf("Size not > 1 (%d)\n", regSize);
return NULL;
}
}
else
{
RegCloseKey(Registry);
return NULL;
}
}
int main()
{
wchar_t * resultData=NULL;
resultData = GetRegistryKeyValue("SOFTWARE\\MICROSOFT\\Windows NT\\CurrentVersion", "ProductId");
wcout << resultData;
cout << endl;
delete resultData;
system("PAUSE");
return 0;
}
You are using TCHAR-based APIs that rely on char* data when compiling for MBCS and wchar_t* data when compiling for Unicode. You are not taking that difference into account correctly. Your code should not even compile when set for Unicode, because you would be passing ANSI parameters to Unicode functions. Since you want to return a Unicode string, you should be using the Unicode API functions to begin with.
There are other logic errors in your code, such as leaking memory, not allocating the right number of bytes for the wc buffer, insufficient error handling, etc.
Try something more like this instead:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
wchar_t* GetRegistryKeyValue(const wchar_t* RegKey, const wchar_t* pValueName)
{
long ReturnStatus;
DWORD regType = 0;
DWORD regSize = 0;
DWORD dwFlags = RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ | RRF_SUBKEY_WOW6464KEY;
wchar_t* ws = 0;
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, ®Type, 0, ®Size);
if (ReturnStatus == ERROR_SUCCESS)
{
ws = new wchar_t[regSize / sizeof(WCHAR)];
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, ®Type, ws, ®Size);
if (ReturnStatus != ERROR_SUCCESS)
{
delete[] ws;
ws = NULL;
}
}
return ws;
}
int main()
{
wchar_t* resultData = GetRegistryKeyValue(L"SOFTWARE\\MICROSOFT\\Windows NT\\CurrentVersion", L"ProductId");
wcout << resultData << endl;
delete[] resultData;
system("PAUSE");
return 0;
}
Alternatively:
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
wstring GetRegistryKeyValue(const wchar_t* RegKey, const wchar_t* pValueName)
{
long ReturnStatus;
DWORD regType = 0;
DWORD regSize = 0;
DWORD dwFlags = RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ | RRF_SUBKEY_WOW6464KEY;
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, ®Type, 0, ®Size);
if (ReturnStatus == ERROR_SUCCESS)
{
vector<BYTE> buf;
buf.resize(regSize);
ReturnStatus = RegGetValueW(HKEY_LOCAL_MACHINE, RegKey, pValueName, dwFlags, ®Type, &buf[0], ®Size);
if (ReturnStatus == ERROR_SUCCESS)
return wstring((wchar_t*)&buf[0], (regSize / sizeof(WCHAR)) - 1);
}
return wstring();
}
int main()
{
wcout << GetRegistryKeyValue(L"SOFTWARE\\MICROSOFT\\Windows NT\\CurrentVersion", L"ProductId") << endl;
system("PAUSE");
return 0;
}
According to this documentation:
http://www.cplusplus.com/reference/cstdlib/mbstowcs/
If max characters are successfully translated, the resulting string stored in dest is not null-terminated.
The tricky way you're trying to calculate string length (which, btw, could be replaced by strlen(pPID) ) will skip the '\0' in the first string and thus the result might not have '\0' on the end. Why don't you use regSize there?
I'm just beginning with directx/directinput development and I'm running some tests with some code samples I've found online. Anyway, I want to hook an application that uses dinput8 to send my own custom input to the forewindow and I'm working with this base to do it:
// dllmain.cpp : Defines the entry point for the DLL application.
#define _CRT_SECURE_NO_WARNINGS // ignore some warnings...
#define _CRT_NON_CONFORMING_SWPRINTFS // ...
#include "stdio.h"
#include <windows.h>
#include "detours.h"
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <time.h>
#include "dinput.h"
#pragma comment(lib, "detours.lib")
#pragma comment(lib, "user32.lib")
typedef HRESULT(__stdcall* GetDeviceState_t)(LPDIRECTINPUTDEVICE, DWORD, LPVOID *);
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE pDevice, DWORD cbData, LPVOID *lpvData);
DWORD Base = 0;
DWORD GetDeviceStateOffset = 0x7670; // This is the offset of GetDeviceState from DInput8.dll
// Open IDA and Import the DInput8.dll, then look in the Functions Table for DirectInput8Create
// There is an Address (1000XXXX or 0CXXXXX) - copy it and save it for later
// Then take a look for CDIDev_GetDeviceState and copy that address too
// Now substract the Address from CDIDev_GetDeviceState from DIrectInput8Create and u'll get your offset
HANDLE tmpHandle = NULL;
HMODULE hModDInput8 = NULL;
DWORD dwGetDeviceState = NULL;
FARPROC dwDirectInput8Create = NULL;
struct MyKeys
{
BYTE Key;
DWORD StartTime;
DWORD TTL;
BOOLEAN isDown;
};
MyKeys KeyBuffer[256];
DWORD WINAPI HookThread();
void add_log(char* format, ...);
void SendKeyDInput(byte DIK_, DWORD time);
GetDeviceState_t pGetDeviceState;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
add_log("==========LOG START==========");
add_log("DLL Attached");
add_log("Creating Thread...");
tmpHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&HookThread, 0, 0, 0);
if (!tmpHandle)
{
add_log("ThreadCreation Failed!");
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD WINAPI HookThread()
{
Base = (DWORD)GetModuleHandleA("test.exe");
add_log("Thread Created");
add_log("game.exe Base: %x", Base);
while (!hModDInput8)
{
add_log("Searching dinput8.dll...");
hModDInput8 = GetModuleHandle(L"dinput8.dll");
Sleep(100);
}
add_log("Found dinput8.dll: %x !", hModDInput8);
while (!dwDirectInput8Create)
{
add_log("Searching GetDeviceState...");
dwDirectInput8Create = GetProcAddress(hModDInput8, "DirectInput8Create");
Sleep(100);
}
add_log("Found DirectInput8Create: %x !", dwDirectInput8Create);
dwGetDeviceState = (DWORD)((DWORD)dwDirectInput8Create - GetDeviceStateOffset);
add_log("GetDevicestate is here (DirectInput8Create - %x): %x", GetDeviceStateOffset, dwGetDeviceState);
add_log("Hooking GetDeviceState...");
pGetDeviceState = (GetDeviceState_t)DetourAttach(&(PVOID&)dwGetDeviceState, (PBYTE)hkGetDeviceState);
add_log("Initiate Keyboard Buffer...");
//initiate buffer
for (int i = 0; i < 256; i++)
{
KeyBuffer[i].isDown = false;
KeyBuffer[i].Key = 0;
KeyBuffer[i].StartTime = 0;
KeyBuffer[i].TTL = 0;
}
add_log("Going into Main Loop...");
while (true)
{
if (GetAsyncKeyState(VK_F5) & 1 << 15)
{
// We check the Most Sigificant Bit from VK_F5 (F5) whilst we shifted it with 15 bits to left 1
// and then a small delay so we have enaught time to release the key
add_log("F5 pushed attempting to sendkey");
// Sleep a short time so we have time to release the F5 Key
Sleep(500);
// Now we send a A Key with 1 sec time to our Game
SendKeyDInput(DIK_A, 1000);
}
}
return 0;
}
void SendKeyDInput(byte DIK, DWORD time)
{
KeyBuffer[DIK].Key = DIK;
KeyBuffer[DIK].TTL = time;
KeyBuffer[DIK].StartTime = GetTickCount();
}
HRESULT __stdcall hkGetDeviceState(LPDIRECTINPUTDEVICE lpDevice, DWORD cbData, LPVOID *lpvData)
{
HRESULT hResult = DI_OK;
static BYTE buffer[256];
int key_count = 0;
for (int i = 0; i<256; i++)
{
if (KeyBuffer[i].Key != 0 && KeyBuffer[i].TTL>0 && KeyBuffer[i].StartTime != 0)
{
if (GetTickCount() > KeyBuffer[i].StartTime + KeyBuffer[i].TTL && KeyBuffer[i].isDown)
{
KeyBuffer[i].Key = 0;
KeyBuffer[i].StartTime = 0;
KeyBuffer[i].TTL = 0;
KeyBuffer[i].isDown = false;
buffer[KeyBuffer[i].Key] = 0;
}
else {
KeyBuffer[i].isDown = true;
buffer[KeyBuffer[i].Key] = 0x80;
key_count += 1;
add_log("Sending Key %x for %i milliseconds count: %i", KeyBuffer[i].Key, KeyBuffer[i].TTL, key_count);
}
}
}
if (key_count != 0)
{
cbData = 256;
memcpy(lpvData, buffer, cbData);
}
else {
hResult = pGetDeviceState(lpDevice, cbData, lpvData);
}
return hResult;
}
//Creates a Logfile in the Game Directory
void add_log(char* format, ...)
{
HANDLE filehandle;
DWORD dwReadBytes;
char buffer[2048];
char writebuffer[2048];
va_list args;
va_start(args, format);
vsprintf_s(buffer, format, args);
filehandle = CreateFile(L"Log.txt", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);
SetFilePointer(filehandle, 0, 0, FILE_END);
sprintf_s(writebuffer, 2048, "Log Added: %s\r\n", buffer);
WriteFile(filehandle, writebuffer, strlen(writebuffer), &dwReadBytes, 0);
CloseHandle(filehandle);
}
The only issue in this code is when I attempt to send input, it doesn't go through. I've gotten some help and narrowed down a solution to this, which was: "Try GetDeviceState hk just memset(buffer, 0, size) or SendDeviceData". I've searched around a bit and I've been unable to find more on how to implement this solution and I'm stumped.
Could one of you kind people show me how I could use this information to fix this base? I'd be extremely grateful, thanks.