I'm looking to disable the LFH for an application I'm trying to debug. I'm able to rebuild and redeploy the application, but I cannot attach a debugger or set any gflags.
What's a good way to disable the LFH with these constraints? Is there maybe an attribute I can modify on the executable itself? Or some startup code I can add to the program?
On Vista and Win7, I think you can disable the Low-Fragmentation Heap on a per-executable basis with the Application Compatibility Toolkit.
On XP, the documentation suggests you don't get a LFH by default. So probably it is your C++ runtime library (which you haven't named) that is turning it on. And it cannot be disabled once enabled. So check the documentation for your particular runtime library to see if you can tell it not to enable LFH, or if there's another version of the runtime library you can link with that doesn't enable it.
See also this thread on the Microsoft forums
Based on Michael Burr's comment above about the IMAGE_LOAD_CONFIG_DIRECTORY containing GlobalFlagSet I wrote the following code to demonstrate enabling the correct GlobalFlag to disable the Low Fragmentation Heap. One caveat about writing your own IMAGE_LOAD_CONFIG_DIRECTORY at compile time is that it disables SafeSEH.
// editloadconfig.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
/*
typedef struct {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD Reserved1;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
} IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
*/
extern "C"
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { 0x48, 0, 0, 0,0, 0x00000020/*enable heap free checking*/};
// change the last value to 0 to not enable any globalflags
#define HEAP_STANDARD 0
#define HEAP_LAL 1
#define HEAP_LFH 2
#define SIZE 100
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bResult;
HANDLE hHeap;
ULONG HeapInformation;
void* allocb[0x12+1];
// based on "Understanding the LFH" paper at
// http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CE0QFjAE&url=http%3A%2F%2Fillmatics.com%2FUnderstanding_the_LFH.pdf&ei=GlBvT9yrMKHy0gGHpLnaBg&usg=AFQjCNGsvVtl54X7MWGyWYqiSrsdTBrbXQ
int i = 0;
for(i = 0; i < 0x12; i++)
{
printf("Allocation 0x%02x for 0x%02x bytes\n", i, SIZE);
allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE);
}
printf("Allocation 0x%02x for 0x%02x bytes\n", i++, SIZE);
printf("\tFirst serviced by the LFH\n");
allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE);
// LFH is now activated so the query below will return 0 or 2.
// sample code from MSDN for querying heap information
//
// Get a handle to the default process heap.
//
hHeap = GetProcessHeap();
if (hHeap == NULL) {
_tprintf(TEXT("Failed to retrieve default process heap with LastError %d.\n"),
GetLastError());
return 1;
}
//
// Query heap features that are enabled.
//
bResult = HeapQueryInformation(hHeap,
HeapCompatibilityInformation,
&HeapInformation,
sizeof(HeapInformation),
NULL);
if (bResult == FALSE) {
_tprintf(TEXT("Failed to retrieve heap features with LastError %d.\n"),
GetLastError());
return 1;
}
//
// Print results of the query.
//
_tprintf(TEXT("HeapCompatibilityInformation is %d.\n"), HeapInformation);
switch(HeapInformation)
{
case HEAP_STANDARD:
_tprintf(TEXT("The default process heap is a standard heap.\n"));
break;
case HEAP_LAL:
_tprintf(TEXT("The default process heap supports look-aside lists.\n"));
break;
case HEAP_LFH:
_tprintf(TEXT("The default process heap has the low-fragmentation ") \
TEXT("heap enabled.\n"));
break;
default:
_tprintf(TEXT("Unrecognized HeapInformation reported for the default ") \
TEXT("process heap.\n"));
break;
}
return 0;
}
You can use the gflags.exe tool that's included with the WDK (maybe also the SDK via the Debugging Tools for Windows package) to manipulate a subset of the gflags in the executable image's PE header. Just go to the "Image File" tab in 'gflags.exe'.
As pointed out by jcopenha in a comment, it looks like gflags.exe does not manipulate the PE file header (I was relying on information from "Windows Internals, Fifth Edition" in Chapter 9's "Heap Debugging Features" section) - apparently it only manipulates the "Image File Execution Options" registry key.
However, it may still be possible possible to set (or clear) the gflags bits for a particular executable in the image - see the docs for the IMAGE_LOAD_CONFIG_DIRECTORY structure; in particular the GlobalFlagsClear and GlobalFlagsSet fields:
GlobalFlagsClear - The global flags that control system behavior. For more information, see Gflags.exe.
GlobalFlagsSet - The global flags that control system behavior. For more information, see Gflags.exe.
You can dump these fields with dumpbin (or link /dump) using the /loadconfig option:
C:\temp>dumpbin /loadconfig test.exe
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file test.exe
File Type: EXECUTABLE IMAGE
Section contains the following load config:
00000048 size
0 time date stamp
0.00 Version
0 GlobalFlags Clear
0 GlobalFlags Set // <=======
0 Critical Section Default Timeout
// remainder of dump snipped...
You can get the RVA of the "Load Configuration Directory" using dumpbin /headers:
C:\temp>dumpbin /headers test.exe
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file test.exe
// ...
OPTIONAL HEADER VALUES
// ...
142B0 [ 40] RVA [size] of Load Configuration Directory
// ^^^^^ ^^^
// ...
As a point of interest, the /loadconfig and /headers option disagree on the size of the structure (for the record, it looks like the /header info isn't right)
Unfortunately, I'm unaware of PE editor that directly supports these fields - you'll probably have to use a hex editor (or the hex editing feature of a PE editor) to change those fields. The RVA of the IMAGE_LOAD_CONFIG_DIRECTORY structure should help you find it in the hex editor.
I believe that setting one or more of the heap debugging flags in the image header (maybe any of them, but you might have to experiment) will disable the low fragmentation heap. But I haven't tested whether or not setting bits in these fields actually works. If you try this, please let us know how it fares.
The simplest way if you can't change the configuration on the machine, is to set the heap information.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705(v=vs.85).aspx
I believe you can disable the LFH heap programmatically this way, although I haven't tried it.
Related
I have to read some data line by line from a large file (more than 7GB), it contains a list of vertex coordinates and face to vertex connectivity information to form a mesh. I am also learning how to use open, mmap on Linux and CreateFileA, CreateFileMapping, MapViewOfFile on Windows. Both Linux and Windows versions are 64bit compiled.
When I am on Linux (using docker) with g++-10 test.cpp -O3 -std=c++17 I get around 6s.
When I am on Windows (my actual PC) both with (version 19.29.30037 x64) cl test.cpp /EHsc /O3 /std:c++17 I get 13s, and with clang++-11 (from Visual Studio Build Tools) I get 11s.
Both systems (same PC, but one is using docker) use the same exact code except for generating the const char* that represents the memory array and the uint64_t size that reprents the memory size.
This is the way I switch platforms:
// includes for using a specific platform API
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// using windows handle void*
#define handle_type HANDLE
#else
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
// using file descriptors
#define handle_type int
#endif
Specifically the code for getting the memory in an array of char-s is:
using uint_t = std::size_t;
// open the file -----------------------------------------------------------------------------
handle_type open(const std::string& filename) {
#ifdef _WIN32
// see windows file mapping api for parameter explanation
return ::CreateFileA(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // private access
#else
return ::open(filename.c_str(), O_RDONLY);
#endif
}
// get the memory size to later have a bound for reading -------------------------------------
uint_t memory_size(handle_type fid) {
#ifdef _WIN32
LARGE_INTEGER size{};
if (!::GetFileSizeEx(fid, &size)) {
std::cerr << "file not found\n";
return size.QuadPart;
}
return size.QuadPart;
#else
struct stat sb;
// get the file stats and check if not zero size
if (fstat(fid, &sb)) {
std::cerr << "file not found\n";
return decltype(sb.st_size){};
}
return sb.st_size;
#endif
}
// get the actual char array to access memory ------------------------------------------------
const char* memory_map(handle_type fid, uint_t memory_size) {
#ifdef _WIN32
HANDLE mapper = ::CreateFileMapping(fid, NULL, PAGE_READONLY, 0, 0, NULL);
return reinterpret_cast<const char*>(::MapViewOfFile(mapper, FILE_MAP_READ, 0, 0, memory_size));
#else
return reinterpret_cast<const char*>(::mmap(NULL, memory_size, PROT_READ, MAP_PRIVATE, fid, 0));
#endif
}
I am completely new to this sort of parsing and was wondering if I am doing something wrong in choosing the parameters in the Windows API (to mimic the behaviour of mmap) or if the difference in time is a matter of compilers/systems and have to accept it?
The actual time to open, get the memory size, and the memory map is negligible both on Linux and on Windows, the rest of the code is identical, as it only operates using the const char* and size_t info.
Thanks for taking the time to read. Any tip is greatly appreciated and sorry if anything is unclear.
Maybe you should take a look at https://github.com/alitrack/mman-win32 which is a mmap implementation for Windows. That way you don't need to write different code for Windows.
I'm working with trying to get some information from the Sensors and Indicators module, but the program always crashes. When I debug step by step I get the result -48 (WFS_ERR_TIMEOUT) from WFSGetInfo() which means that it has timed out. The Sensor and Indicator registry key is present and the vendor DLL is also present. All the other modules are able to open just fine. Any idea what gives?
The SIU SPI version is 3.02 and I'm using SPI/XFS version 0x0B020003 and XFS SDK 3.20. Would this be one of the issues?
#include "XFS.h"
#include "XFSSIU.h"
int main()
{
XFS xfs = XFS();
xfs.start();
HRESULT hResult = XFSObj.openSession("SIU");
LPWFSRESULT lpResult = NULL;
HRESULT open_result = NULL;
open_result = WFSGetInfo(xfs.getServiceHandle(), WFS_INF_SIU_STATUS, NULL, 120000, &lpResult);
std::cout << open_result << std::endl;
XFSObj.CloseSession();
return 0;
}
My app is written in C++Builder for Win32. My code uses the SHGetSpecialFolderLocation() API to get the CSIDL_APPDATA and CSIDL_MYDOCUMENTS paths.
I noticed on Microsoft's website dated 12/04/2018 that it says:
[SHGetSpecialFolderLocation is not supported and may be altered or unavailable in the future. Instead, use SHGetFolderLocation.]
Then for SHGetFolderLocation it says:
Deprecated
What is the current way to get these two paths?
My current code is below.
LPITEMIDLIST List = NULL;
wchar_t wPath[MAX_PATH + 1];
UnicodeString S01, Fi;
if( !SHGetSpecialFolderLocation(0, CSIDL_APPDATA, &List) ){
if( SHGetPathFromIDListW(List, wPath ) ){
S01 = wPath;
Fi = (S01+"\\my_files\\");
Form1->MyRoamingPath_Mh = Fi;
}
}
SHGetSpecialFolderLocation() was first introduced in Windws 95/NT4. It was deprecated in Windows 2000/XP in favor of SHGetFolderLocation() (which returns a folder location as an IDLIST_ABSOLUTE) and SHGetFolderPath() (which returns a folder location as a path string).
So, in your example, you could have used SHGetFolderPath() instead:
#include <Shlobj.h>
#include <SysUtils.hpp>
wchar_t wPath[MAX_PATH + 1];
if (SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK)
{
Form1->MyRoamingPath_Mh = IncludeTrailingPathDelimiter(wPath) + L"my_files\\";
}
In Vista, use of CSIDL was deprecated in favor of KNOWNFOLDERID. The above functions have been deprecated in favor of SHGetKnownFolderIDList()/IKnownFolder::GetIDList() and SHGetKnownFolderPath()/IKnownFolder::GetPath(), respectively.
This is actually stated at the bottom of the SHGetFolderLocation() documentation 1:
1: I guess you did not scroll down far enough to see it.
Note As of Windows Vista, this function is merely a wrapper for SHGetKnownFolderIDList. The CSIDL value is translated to its associated KNOWNFOLDERID and SHGetKnownFolderIDList is called. New applications should use the known folder system rather than the older CSIDL system, which is supported only for backward compatibility.
So, in your example, you can now use SHGetKnownFolderPath() instead:
#include <Shlobj.h>
#include <SysUtils.hpp>
PWSTR pwPath;
if (SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, NULL, &pwPath) == S_OK)
{
try
{
Form1->MyRoamingPath_Mh = IncludeTrailingPathDelimiter(pwPath) + L"my_files\\";
}
__finally
{
CoTaskMemFree(pwPath);
}
}
For the "My Documents" folder, use FOLDERID_Documents.
I am using GetBinaryType to check if an executable is 32 or 64bit. I am testing against a 64bit file and it keeps failing. I believe this is due to the way I am comparing the DWORD result?
I am using Visual Studio 2010 C++:
DWORD dwBinaryType;
if (GetBinaryType(ChildFile(), &dwBinaryType) == 6)
{
MessageBox(NULL, L"64bit Detected...", L"Debug: GetBinaryType", MB_OK); // DEBUG
}
else
{
MessageBox(NULL, L"Probably 32bit...", L"Debug: GetBinaryType", MB_OK); // DEBUG
}
Any advice would be great thanks.
According to MSDN for GetBinaryType:
Return value
If the file is executable, the return value is nonzero. The function sets the variable pointed to by lpBinaryType to indicate the file's executable type.
Changing your above code to this should do the trick:
if (GetBinaryType(ChildFile(), &dwBinaryType)
&& dwBinaryType == SCS_64BIT_BINARY)
{
// ...
}
I've been trying to compile an exe in Microsoft Visual C++ 6.0 using the psapi.h library but I keep getting this error;
fatal error C1083: Cannot open include file: 'psapi.h': No such file or directory Error executing cl.exe.
I've looked all over the internet, I found many posts directing me to download and install versions of the Windows SDK. However all those links were dead. If anyone could walk me though configuring the Microsoft Visual C++ 6.0 so that it could compile with psapi.h, that would be awesome!
Get the windows or platform sdk directly from microsoft, they shouldn't have any dead links. Failing that, download visual studio 08 or higher and see if it installs the lib & header(I had the exact same problem as you, I solved it by copying the lib and header from the windows sdk that visual studio 2008 comes with).
If psapi.h is not included with the SDK included with VC++ 6.0, then you should probably rather update your compiler that try to use a new SDK with an old tool-chain. PSAPI is supported on versions of Windows released after VC++ 6.0.
Either way the header file alone will not solve your problem; you will also need the appropriate export library and DLL.
The latest versions of the Platform SDK are not compatible with Visual C++ 6.0 - support for that compiler ended years ago. If you didn't get the SDK back when it was available I'm afraid you're out of luck. Microsoft is not bashful about obsoleting things and wiping them out completely.
This works for me:
/*
* Simple utility to call GetProcessMemoryInfo without having
* to compile or link with psapi.h / psapi.lib.
*/
typedef struct {
DWORD cb;
DWORD PageFaultCount;
DWORD PeakWorkingSetSize;
DWORD WorkingSetSize;
DWORD QuotaPeakPagedPoolUsage;
DWORD QuotaPagedPoolUsage;
DWORD QuotaPeakNonPagedPoolUsage;
DWORD QuotaNonPagedPoolUsage;
DWORD PagefileUsage;
DWORD PeakPagefileUsage;
} PROCESS_MEMORY_COUNTERS;
#define Win32MemArgs HANDLE, PROCESS_MEMORY_COUNTERS *, DWORD
extern BOOL WINAPI GetProcessMemoryInfo( Win32MemArgs );
typedef BOOL (WINAPI *GetMemInfo)( Win32MemArgs );
PROCESS_MEMORY_COUNTERS GetMemInfo()
{
PROCESS_MEMORY_COUNTERS pmc;
HANDLE hProc;
char *pf;
BOOL bOK;
static HINSTANCE _hLib = (HINSTANCE)0;
static GetMemInfo _fcn = (GetMemInfo)0;
/*
* Dynamically Load library (once)
*/
if ( !_hLib && (_hLib=::LoadLibrary( "psapi.dll" )) ) {
pf = "GetProcessMemoryInfo";
_fcn = (BOOL (WINAPI *)( Win32MemArgs ))::GetProcAddress( _hLib, pf );
}
/*
* Call fcn
*/
bOK = FALSE
if ( _fcn && (hProc=::GetCurrentProcess()) )
bOK = (*_fcn)( hProc, &pmc, sizeof( pmc ) );
}
if ( !bOK )
memset( &pmc, 0, sizeof( pmc ) );
return pmc;
}