I'm trying to get started with calling Windows APIs using Kotlin/Native. So far, I can get some file metadata:
memScoped {
CoInitialize(null, 0)
val fileInfo = alloc<SHFILEINFOA>()
// flags: ICON, DISPLAYNAME, TYPENAME, ICONLOCATION, SMALLICON
SHGetFileInfo("C:\\path\\to.file", 0, fileInfo.ptr, 0, 5889)
println(fileInfo.szDisplayName.toKString()) // prints the file name
println(fileInfo.szTypeName.toKString()) // prints the file type
val iconInfo = alloc<ICONINFO>()
GetIconInfo(iconInfo, fileInfo.hIcon.ptr)
println(iconInfo.hbmColor) // prints some CPointer value
println(iconInfo.hbmMask) // prints some CPointer value
}
I can pass those HBITMAPs into GetDIBits:
val bitmap = alloc<BITMAPINFO>()
val bytes: COpaquePointerVar = alloc() // ??
GetDIBits(GetDC(null), iconInfo.hbmColor /* or iconInfo.hbmMask */, 0, UInt.MAX_VALUE, bytes.ptr, bitmap.ptr, 0)
println(bytes) // a NativePointed value
Am I going in the right direction? I'm not sure. I want to get the image bytes, so I can then do further processing.
The documentation doesn't give me any useful information.
Related
In the following program I print to the console using two different functions
#include <windows.h>
int main() {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD byteswritten;
WriteConsole(h, "WriteConsole", 12, &byteswritten, NULL);
WriteFile(h, "WriteFile", 9, &byteswritten, NULL);
}
If when I execute this program and redirect it's output using a > out.txt or a 1> out.txt nothing gets printed to the console (as expected) but the contents of out.txt are only
WriteFile
What is different between the two that allows calls to WriteFile to be redirected to the file and calls to WriteConsole to go to ... nowhere
Tested with gcc and msvc on windows 10
WriteConsole only works with console screen handles, not files nor pipes.
If you are only writing ASCII content you can use WriteFile for everything.
If you need to write Unicode characters you can use GetConsoleMode to detect the handle type, it fails for everything that is not a console handle.
When doing raw output like this you also have to deal with the BOM if the handle is redirected to a file.
This blog post is a good starting point for dealing with Unicode in the Windows console...
Edit 2021:
Windows 10 now has the ConPTY API (aka pseudo-console), which basically allows any program to act like the console for another program, thus enables capturing output that is directly written to the console.
This renders my original answer obsolete for Windows versions that support ConPTY.
Original answer:
From the reference:
WriteConsole fails if it is used with a standard handle that is
redirected to a file. If an application processes multilingual output
that can be redirected, determine whether the output handle is a
console handle (one method is to call the GetConsoleMode function and
check whether it succeeds). If the handle is a console handle, call
WriteConsole. If the handle is not a console handle, the output is
redirected and you should call WriteFile to perform the I/O.
This is only applicable if you control the source code of the application that you want to redirect. I recently had to redirect output from a closed-source application that unconditionally called WriteConsole() so it could not be redirected normally.
Reading the console screen buffer (as suggested by this answer) prooved to be unreliable, so I used Microsoft Detours library to hook the WriteConsole() API in the target process and call WriteFile() if necessary. Otherwise call the original WriteConsole() function.
I created a hook DLL based on the example of Using Detours:
#include <windows.h>
#include <detours.h>
// Target pointer for the uninstrumented WriteConsoleW API.
//
auto WriteConsoleW_orig = &WriteConsoleW;
// Detour function that replaces the WriteConsoleW API.
//
BOOL WINAPI WriteConsoleW_hooked(
_In_ HANDLE hConsoleOutput,
_In_ const VOID *lpBuffer,
_In_ DWORD nNumberOfCharsToWrite,
_Out_ LPDWORD lpNumberOfCharsWritten,
_Reserved_ LPVOID lpReserved
)
{
// Check if this actually is a console screen buffer handle.
DWORD mode;
if( GetConsoleMode( hConsoleOutput, &mode ) )
{
// Forward to the original WriteConsoleW() function.
return WriteConsoleW_orig( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved );
}
else
{
// This is a redirected handle (e. g. a file or a pipe). We multiply with sizeof(WCHAR), because WriteFile()
// expects the number of bytes, but WriteConsoleW() gets passed the number of characters.
BOOL result = WriteFile( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite * sizeof(WCHAR), lpNumberOfCharsWritten, nullptr );
// WriteFile() returns number of bytes written, but WriteConsoleW() has to return the number of characters written.
if( lpNumberOfCharsWritten )
*lpNumberOfCharsWritten /= sizeof(WCHAR);
return result;
}
}
// DllMain function attaches and detaches the WriteConsoleW_hooked detour to the
// WriteConsoleW target function. The WriteConsoleW target function is referred to
// through the WriteConsoleW_orig target pointer.
//
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (DetourIsHelperProcess()) {
return TRUE;
}
if (dwReason == DLL_PROCESS_ATTACH) {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)WriteConsoleW_orig, WriteConsoleW_hooked);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)WriteConsoleW_orig, WriteConsoleW_hooked);
DetourTransactionCommit();
}
return TRUE;
}
Note: In the WriteFile() branch I don't write a BOM (byte order mark), because it is not always wanted (e. g. when redirecting to a pipe instead of a file or when appending to an existing file). An application that is using the DLL to redirect process output to a file can simply write the UTF-16 LE BOM on its own before launching the redirected process.
The target process is created using DetourCreateProcessWithDllExW(), specifying the name of our hook DLL as argument for the lpDllName parameter. The other arguments are identical to how you create a redirected process via the CreateProcessW() API. I won't go into detail, because these are all well documented.
The code below can be used to redirect console output if the other party uses WriteConsole. The code reads the output via a hidden console screen buffer. I've written this code to intercept debug output some directshow drivers write to the console. Directshow drivers have the habit of doing things drivers should not do, like writing unwanted logfiles, writing to console and crashing.
// info to redirected console output
typedef struct tagRedConInfo
{
// hidden console
HANDLE hCon;
// old console handles
HANDLE hOldConOut;
HANDLE hOldConErr;
// buffer to read screen content
CHAR_INFO *BufData;
INT BufSize;
//
} TRedConInfo;
//------------------------------------------------------------------------------
// GLOBALS
//------------------------------------------------------------------------------
// initial handles
HANDLE gv_hOldConOut;
HANDLE gv_hOldConErr;
//------------------------------------------------------------------------------
// PROTOTYPES
//------------------------------------------------------------------------------
/* init redirecting the console output */
BOOL Shell_InitRedirectConsole(BOOL,TRedConInfo*);
/* done redirecting the console output */
BOOL Shell_DoneRedirectConsole(TRedConInfo*);
/* read string from hidden console, then clear */
BOOL Shell_ReadRedirectConsole(TRedConInfo*,TCHAR*,INT);
/* clear buffer of hidden console */
BOOL Shell_ClearRedirectConsole(TRedConInfo*);
//------------------------------------------------------------------------------
// IMPLEMENTATIONS
//------------------------------------------------------------------------------
/***************************************/
/* init redirecting the console output */
/***************************************/
BOOL Shell_InitRedirectConsole(BOOL in_SetStdHandles, TRedConInfo *out_RcInfo)
{
/* locals */
HANDLE lv_hCon;
SECURITY_ATTRIBUTES lv_SecAttr;
// preclear structure
memset(out_RcInfo, 0, sizeof(TRedConInfo));
// prepare inheritable handle just in case an api spans an external process
memset(&lv_SecAttr, 0, sizeof(SECURITY_ATTRIBUTES));
lv_SecAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
lv_SecAttr.bInheritHandle = TRUE;
// create hidden console buffer
lv_hCon = CreateConsoleScreenBuffer(
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
&lv_SecAttr, CONSOLE_TEXTMODE_BUFFER, 0);
// failed to create console buffer?
if (lv_hCon == INVALID_HANDLE_VALUE)
return FALSE;
// store
out_RcInfo->hCon = lv_hCon;
// set as standard handles for own process?
if (in_SetStdHandles)
{
// mutex the globals
WaitForGlobalVarMutex();
// remember the old handles
out_RcInfo->hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
out_RcInfo->hOldConErr = GetStdHandle(STD_ERROR_HANDLE);
// set hidden console as std output
SetStdHandle(STD_OUTPUT_HANDLE, lv_hCon);
SetStdHandle(STD_ERROR_HANDLE, lv_hCon);
// is this the first instance?
if (!gv_hOldConOut)
{
// inform our own console output code about the old handles so our own
// console will be writing to the real console, only console output from
// other parties will write to the hidden console
gv_hOldConOut = out_RcInfo->hOldConOut;
gv_hOldConErr = out_RcInfo->hOldConErr;
}
// release mutex
ReleaseGlobalVarMutex();
}
// done
return TRUE;
}
/***************************************/
/* done redirecting the console output */
/***************************************/
BOOL Shell_DoneRedirectConsole(TRedConInfo *in_RcInfo)
{
// validate
if (!in_RcInfo->hCon)
return FALSE;
// restore original handles?
if (in_RcInfo->hOldConOut)
{
// mutex the globals
WaitForGlobalVarMutex();
// restore original handles
SetStdHandle(STD_OUTPUT_HANDLE, in_RcInfo->hOldConOut);
SetStdHandle(STD_ERROR_HANDLE, in_RcInfo->hOldConErr);
// was this the first instance?
if (in_RcInfo->hOldConOut == gv_hOldConOut)
{
// clear
gv_hOldConOut = NULL;
gv_hOldConErr = NULL;
}
// release mutex
ReleaseGlobalVarMutex();
}
// close the console handle
CloseHandle(in_RcInfo->hCon);
// free read buffer
if (in_RcInfo->BufData)
MemFree(in_RcInfo->BufData);
// clear structure
memset(in_RcInfo, 0, sizeof(TRedConInfo));
// done
return TRUE;
}
/***********************************************/
/* read string from hidden console, then clear */
/***********************************************/
BOOL Shell_ReadRedirectConsole(TRedConInfo *in_RcInfo, TCHAR *out_Str, INT in_MaxLen)
{
/* locals */
TCHAR lv_C;
INT lv_X;
INT lv_Y;
INT lv_W;
INT lv_H;
INT lv_N;
INT lv_Len;
INT lv_Size;
INT lv_PrvLen;
COORD lv_DstSze;
COORD lv_DstOfs;
DWORD lv_Written;
SMALL_RECT lv_SrcRect;
CHAR_INFO *lv_BufData;
CONSOLE_SCREEN_BUFFER_INFO lv_Info;
// preclear output
out_Str[0] = 0;
// validate
if (!in_RcInfo->hCon)
return FALSE;
// reserve character for eos
--in_MaxLen;
// get current buffer info
if (!GetConsoleScreenBufferInfo(in_RcInfo->hCon, &lv_Info))
return FALSE;
// check whether there is something at all
if (!lv_Info.dwSize.X || !lv_Info.dwSize.Y)
return FALSE;
// limit the buffer passed onto read call otherwise it
// will fail with out-of-resources error
lv_DstSze.X = (INT16)(lv_Info.dwSize.X);
lv_DstSze.Y = (INT16)(lv_Info.dwSize.Y < 8 ? lv_Info.dwSize.Y : 8);
// size of buffer needed
lv_Size = lv_DstSze.X * lv_DstSze.Y * sizeof(CHAR_INFO);
// is previous buffer too small?
if (!in_RcInfo->BufData || in_RcInfo->BufSize < lv_Size)
{
// free old buffer
if (in_RcInfo->BufData)
MemFree(in_RcInfo->BufData);
// allocate read buffer
if ((in_RcInfo->BufData = (CHAR_INFO*)MemAlloc(lv_Size)) == NULL)
return FALSE;
// store new size
in_RcInfo->BufSize = lv_Size;
}
// always write to (0,0) in buffer
lv_DstOfs.X = 0;
lv_DstOfs.Y = 0;
// init src rectangle
lv_SrcRect.Left = 0;
lv_SrcRect.Top = 0;
lv_SrcRect.Right = lv_DstSze.X;
lv_SrcRect.Bottom = lv_DstSze.Y;
// buffer to local
lv_BufData = in_RcInfo->BufData;
// start at first string position in output
lv_Len = 0;
// loop until no more rows to read
do
{
// read buffer load
if (!ReadConsoleOutput(in_RcInfo->hCon, lv_BufData, lv_DstSze, lv_DstOfs, &lv_SrcRect))
return FALSE;
// w/h of actually read content
lv_W = lv_SrcRect.Right - lv_SrcRect.Left + 1;
lv_H = lv_SrcRect.Bottom - lv_SrcRect.Top + 1;
// remember previous position
lv_PrvLen = lv_Len;
// loop through rows of buffer
for (lv_Y = 0; lv_Y < lv_H; ++lv_Y)
{
// reset output position of current row
lv_N = 0;
// loop through columns
for (lv_X = 0; lv_X < lv_W; ++lv_X)
{
// is output full?
if (lv_Len + lv_N > in_MaxLen)
break;
// get character from screen buffer, ignore attributes
lv_C = lv_BufData[lv_Y * lv_DstSze.X + lv_X].Char.UnicodeChar;
// append character
out_Str[lv_Len + lv_N++] = lv_C;
}
// remove spaces at the end of the line
while (lv_N > 0 && out_Str[lv_Len+lv_N-1] == ' ')
--lv_N;
// if row was not blank
if (lv_N > 0)
{
// update output position
lv_Len += lv_N;
// is output not full?
if (lv_Len + 2 < in_MaxLen)
{
// append cr/lf
out_Str[lv_Len++] = '\r';
out_Str[lv_Len++] = '\n';
}
}
}
// update screen position
lv_SrcRect.Top = (INT16)(lv_SrcRect.Top + lv_H);
lv_SrcRect.Bottom = (INT16)(lv_SrcRect.Bottom + lv_H);
// until nothing is added or no more screen rows
} while (lv_PrvLen != lv_Len && lv_SrcRect.Bottom < lv_Info.dwSize.Y);
// remove last cr/lf
if (lv_Len > 2)
lv_Len -= 2;
// append eos
out_Str[lv_Len] = 0;
// total screen buffer size in characters
lv_Size = lv_Info.dwSize.X * lv_Info.dwSize.Y;
// clear the buffer with spaces
FillConsoleOutputCharacter(in_RcInfo->hCon, ' ', lv_Size, lv_DstOfs, &lv_Written);
// reset cursor position to (0,0)
SetConsoleCursorPosition(in_RcInfo->hCon, lv_DstOfs);
// done
return TRUE;
}
/**********************************/
/* clear buffer of hidden console */
/**********************************/
BOOL Shell_ClearRedirectConsole(TRedConInfo *in_RcInfo)
{
/* locals */
INT lv_Size;
COORD lv_ClrOfs;
DWORD lv_Written;
CONSOLE_SCREEN_BUFFER_INFO lv_Info;
// validate
if (!in_RcInfo->hCon)
return FALSE;
// get current buffer info
if (!GetConsoleScreenBufferInfo(in_RcInfo->hCon, &lv_Info))
return FALSE;
// clear from (0,0) onward
lv_ClrOfs.X = 0;
lv_ClrOfs.Y = 0;
// total screen buffer size in characters
lv_Size = lv_Info.dwSize.X * lv_Info.dwSize.Y;
// clear the buffer with spaces
FillConsoleOutputCharacter(in_RcInfo->hCon, ' ', lv_Size, lv_ClrOfs, &lv_Written);
// reset cursor position to (0,0)
SetConsoleCursorPosition(in_RcInfo->hCon, lv_ClrOfs);
// done
return TRUE;
}
I'm trying to read the .pdata section of a x64 exe.
I'm mapping the file to the memory, finding the .pdata section, and then I use it's PointerToRawData to get to the actual data of the section...
But then my "pdata" pointer points at a illegal address :(
This is what I do:
void* mappingHandle = CreateFileMapping(fileHandle,
NULL,
PAGE_READONLY,
0,
1,
NULL);
char* fileMemory = (char*)MapViewOfFile(mappingHandle, FILE_MAP_READ, 0, 0, 1);
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)fileMemory;
IMAGE_SECTION_HEADER* pdataSectionHeader = NULL;
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) // "MZ" signature
{
IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)(fileMemory + dosHeader->e_lfanew);
if (ntHeaders->Signature == IMAGE_NT_SIGNATURE) // Supposed to be "PE"
{
unsigned int sectionCount = ntHeaders->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER* sectionHeaders = IMAGE_FIRST_SECTION(ntHeaders);
pdataSectionHeader = sectionHeaders + 3; // Going to .pdata section.
}
}
unsigned long pdataSize = pdataSectionHeader->SizeOfRawData;
char* pdata = fileMemory + pdataSectionHeader->PointerToRawData;
can anybody tell me what I doing wrong?
The problem was in the way I mapped the file to the memory.
I should have done it this way:
void* mappingHandle = CreateFileMapping(fileHandle,
NULL,
PAGE_READONLY,
0,
0, //Here: 0 instead of 1
NULL);
I am a new member and joined this site after referring to it loads of times when i was stuck with some programming problems. I am trying to code a media player (Win32 SDK VC++ 6.0) for my college project and I am stuck. I have searched on various forums and msdn and finally landed on the function GetShortPathName which enables me to play through folders and files which have a whitespace in their names. I will paste the code here so it will be much more clearer as to what i am trying to do.
case IDM_FILE_OPEN :
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Media Files (All Supported Types)\0*.avi;*.mpg;*.mpeg;*.asf;*.wmv;*.mp2;*.mp3\0"
"Movie File (*.avi;*.mpg;*.mpeg)\0*.avi;*.mpg;*.mpeg\0"
"Windows Media File (*.asf;*.wmv)\0*.asf;*.wmv\0"
"Audio File (*.mp2;*.mp3)\0*.mp2;*.mp3\0"
"All Files(*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_CREATEPROMPT;
ofn.lpstrDefExt = "mp3";
if(GetOpenFileName(&ofn))
{
length = GetShortPathName(szFileName, NULL, 0);
buffer = (TCHAR *) malloc (sizeof(length));
length = GetShortPathName(szFileName, buffer, length);
for(i = 0 ; i < MAX_PATH ; i++)
{
if(buffer[i] == '\\')
buffer[i] = '/';
}
SendMessage(hList,LB_ADDSTRING,0,(LPARAM)buffer);
mciSendString("open buffer alias myFile", NULL, 0, NULL);
mciSendString("play buffer", NULL, 0, NULL);
}
return 0;
using the GetShortPathName function i get the path as : D:/Mp3z/DEEPBL~1/03SLEE~1.mp3
Putting this path directly in Play button case
mciSendString("open D:/Mp3jh/DEEPBL~1/03SLEE~1.mp3 alias myFile", NULL, 0, NULL);
mciSendString("play myFile", NULL, 0, NULL);
the file opens and plays fine. But as soon as i try to open and play it through the open file dialog box, nothing happens. Any input appreciated.
It looks like the problem is that you're passing the name of the buffer variable to the mciSendString function as a string, rather than passing the contents of the buffer.
You need to concatenate the arguments you want to pass (open and alias myFile) with the contents of buffer.
The code can also be much simplified by replacing malloc with an automatic array. You don't need to malloc it because you don't need it outside of the block scope. (And you shouldn't be using malloc in C++ code anyway; use new[] instead.)
Here's a modified snippet of the code shown in your question:
(Warning: changes made using only my eyes as a compiler! Handle with care.)
if(GetOpenFileName(&ofn))
{
// Get the short path name, and place it in the buffer array.
// We know that a short path won't be any longer than MAX_PATH, so we can
// simply allocate a statically-sized array without futzing with new[].
//
// Note: In production code, you should probably check the return value
// of the GetShortPathName function to make sure it succeeded.
TCHAR buffer[MAX_PATH];
GetShortPathName(szFileName, buffer, MAX_PATH);
// Add the short path name to your ListBox control.
//
// Note: In C++ code, you should probably use C++-style casts like
// reinterpret_cast, rather than C-style casts!
SendMessage(hList, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(buffer));
// Build the argument string to pass to the mciSendString function.
//
// Note: In production code, you probably want to use the more secure
// alternatives to the string concatenation functions.
// See the documentation for more details.
// And, as before, you should probably check return values for error codes.
TCHAR arguments[MAX_PATH * 2]; // this will definitely be large enough
lstrcat(arguments, TEXT("open"));
lstrcat(arguments, buffer);
lstrcat(arguments, TEXT("alias myFile"));
// Or, better yet, use a string formatting function, like StringCbPrintf:
// StringCbPrintf(arguments, MAX_PATH * 2, TEXT("open %s alias myFile"),
// buffer);
// Call the mciSendString function with the argument string we just built.
mciSendString(arguments, NULL, 0, NULL);
mciSendString("play myFile", NULL, 0, NULL);
}
Do note that, as the above code shows, working with C-style strings (character arrays) is a real pain in the ass. C++ provides a better alternative, in the form of the std::string class. You should strongly consider using that instead. To call Windows API functions, you'll still need a C-style string, but you can get one of those by using the c_str method of the std::string class.
My program is combined with some additional data at the end of the original exe. The program would extract the additional data to disk when running the program.
However my program can't get the right offset of the appended data after signing the combined executable program.
I compared the signed exe and the original exe, the signing information is appended at the end of the exe. So I'm looking for a Win32 API to get the length of signing segment from the signed program. After that, my program could find the right offset of combined data, then extract them correctly.
Could anyone give me a hint?
I find a tool named PEDump(written by Matt Pietrek for his book) with source code to demonstrate how to get the size of signing information.
Below is the code extracted from PEDump for my purpose,
// MakePtr is a macro that allows you to easily add to values (including
// pointers) together without dealing with C's pointer arithmetic. It
// essentially treats the last two parameters as DWORDs. The first
// parameter is used to typecast the result to the appropriate pointer type.
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
// Names of the data directory elements that are defined
const char *ImageDirectoryNames[] = {
"EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC",
"DEBUG", "COPYRIGHT", "GLOBALPTR", "TLS", "LOAD_CONFIG",
"BOUND_IMPORT", "IAT", // These two entries added for NT 3.51
"DELAY_IMPORT" }; // This entry added in NT 5
#define NUMBER_IMAGE_DIRECTORY_ENTRYS \
(sizeof(ImageDirectoryNames)/sizeof(char *))
HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(getProgramFile()));
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if ( hFileMapping == 0 )
{
printf("%s", "Couldn't open file mapping with CreateFileMapping()\n");
} else {
LPVOID lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
if ( lpFileBase == 0 )
{
printf("%s", "Couldn't map view of file with MapViewOfFile()\n");
} else {
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
PIMAGE_FILE_HEADER pImgFileHdr = (PIMAGE_FILE_HEADER)lpFileBase;
// it's EXE file
if ( dosHeader->e_magic == IMAGE_DOS_SIGNATURE )
{
PIMAGE_NT_HEADERS pNTHeader;
DWORD base = (DWORD)dosHeader;
pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew );
PIMAGE_OPTIONAL_HEADER optionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNTHeader->OptionalHeader;
for ( int i=0; i < optionalHeader->NumberOfRvaAndSizes; i++)
{
// DataDirectory[4] represents security directory
if ( 4 == i ) {
signingLength = optionalHeader->DataDirectory[i].Size;
break;
}
}
}
UnmapViewOfFile(lpFileBase);
}
CloseHandle(hFileMapping);
}
Put a long signature line before and after your data, and then just search for those lines at the expected offsets.
Specifically, does "result" change in the following code when the DPI is increased via the windows control panel display settings?
UINT result = 0;
if(SystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &result, 0) != FALSE)
{
result = ?;
}
The reason I can't check this myself is that I can't change the DPI setting on the computer I'm working on because the admin has disabled the option.
The documents are unclear but in general the 3rd param is only in/out because the Win32 API here is overloaded as both a getter and a setter. I would not expect this to change on a SET
call but on the GET call you have above, yes it will change to indicate the current value. Did you intend to actually post a SET call? The question text implies you are trying to set the value.
For the following code, the value ought not to change:
UINT result = REQUIRED_NEW_VALUE;
if(SystemParametersInfo(SPI_SETFOCUSBORDERHEIGHT, 0, &result, 0) != FALSE)
{
// result == the same as what was input
}
For the code you posted, result will change from 0 to the current configured value:
UINT result = 0;
if(SystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &result, 0) != FALSE)
{
// result == the current configured value
}