Using the following code, more or less copy-pasted from the MSDN example of
GetAdaptersAddresses, I get the return value 122, which means ERROR_INSUFFICIENT_BUFFER (according to this system error code list).
ULONG outBufLen = 150000; // Tried for different (large) values here...
PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
DWORD dwRetVal = GetAdaptersAddresses(AF_INET, 0, NULL, pAddresses, &outBufLen);
// ....
free(pAddresses);
The documentation of GetAdaptersAddresses does not list ERROR_INSUFFICIENT_BUFFER as one of the expected return values. (It lists ERROR_BUFFER_OVERFLOW, which should adjust outBufLen to the needed value, but that remains unchanged).
Using GetAdaptersInfo instead leads to the same symptoms.
This error does not occur on my development machine, but on one virtual and one real clean Windows 7 x86 SP1 installation (added the VC++ redistributables).
As a c++ newbie, am I doing something wrong? What could cause this error and how to fix it? =)
First of all, you can - as others suggested - do two calls, to find out required buffer size, and then do the query itself. Especially if you are seeing the error, your first try would be to ask API what size it expected.
Second, you need to know that this API is not quite safe in 32-bit processes consuming high amounts of memory, so that buffers span into higher 2GB of address space. API might start acting in a weird way, either due to its own bug, or a bug in an underlying layer. See details on this on MS Connect here: GetAdaptersAddresses API incorrectly returns no adapters for a process with high memory consumption.
The fact that error code is not "one of the expected return values" tells for the versions that the error comes from an underlying layer and this API just passes it up on internal failure. As a clue, having disabled some network adapter on the system, you might get rid of the error.
Visual Studio deployed a library named "IPHLPAPI.dll" together with my project which caused the problem. Deleting this file solved it.
Why this was the case is subject to further research =)
First, a buffer is a block of memory.
So insufficient could mean that you haven't given it enough memory somehow. Our could be a block of memory which you don't have access to. Maybe the address doesn't even exist.
Look at this:
ERROR_INSUFFICIENT_BUFFER
122 (0x7A)
The data area passed to a system call is too small.
This sounds really like the buffer hasn't got enough allocated memory. Or similar.
Maybe the
outBufLen
has to be a specific length, maybe the size of the memory block. Because sometimes it doesn't check for the 'name' but tries to compare for each of the variables size. This idea came from the High Level Shader Language.
So i would try to look a bit more on the:
ULONG outBufLen = 150000; // Tried for different (large) values here...
PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
Good luck!
To know the exact buffer size required, you can just pass NULL into pAddresses and size will be set to the required size. You may want to rewrite your code slightly to make that work;
DWORD rv, size = 0;
PIP_ADAPTER_ADDRESSES adapter_addresses;
rv = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &size);
if (rv != ERROR_BUFFER_OVERFLOW)
return false; // ERROR
adapter_addresses = (PIP_ADAPTER_ADDRESSES)malloc(size);
rv = GetAdaptersAddresses(AF_INET, 0, NULL, adapter_addresses, &size);
if (rv != ERROR_SUCCESS) {
free(adapter_addresses);
return false; // ERROR
}
Related
I have to correct a bug where Leadtools function " L_LoadBitmap() returns ERROR_NO_MEMORY " , more info about it you can find Here.
The application I am working on has to be able to handle images despites the size of each image or their count.
Here the function is called:
HENHMETAFILE hemf = 0;
BITMAPHANDLE bmh = {0};
hemf = LoadMetaFile( (LPCTSTR)strPath, hDC );
if ( !hemf )
{
memset( &bmh, 0, sizeof(BITMAPHANDLE) );
L_INT nResult = 0;
nResult = L_LoadBitmap( const_cast<LPTSTR>( (LPCTSTR)strPath ), &bmh, 0, ORDER_BGR );
if ( nResult != SUCCESS )
{
MFDebugString( DL_FORMULAR, __FUNCTION__ "( %s ): Can't load background file via L_LoadBitmap (%d)\n", (LPCTSTR)strPath, nResult );
return nullptr;
}
}
pOrigBg = std::make_shared<CBackgroundImage>(strPath, hemf, bmh);
m_ImageCache[strKey.GetString()] = pOrigBg;
return pOrigBg;
Here pOrigBgis an std::shared_ptr<CBackgroundImage> object that gets constructed this way:
NxFE::CBackgroundImage::CBackgroundImage(LPCTSTR strPath, HENHMETAFILE emf, const BITMAPHANDLE& bmp)
: m_Filename(strPath), m_Metafile(emf), m_pLeadBitmap(new BITMAPHANDLE(bmp)),
m_pGdiplusBitmap(NxClass::Win32::GDIPlus::CreateBitmapFromFile((LPCSTR) m_Filename))
{
}
How can you see, pOrigBg contains a std::unique_ptr of type BITMAPHANDLE and Gdiplus::Bitmap.
Firstly, I thought that removing constructor of m_pGdiplusBitmap may help , but it doesn't.
Is any possible way to deallocate/reduce the usage of graphic memory ? Or at least some tools of inspecting Graphic Memory Usage (I'm using Microsoft Visual Studio 2017).
As you found out, functions in LEADTOOLS that allocate pixel data must be followed by calling L_FreeBitmap() when you no longer need the bitmap in memory. This is actually mentioned in the help topic you mentioned in your original question, which states: “Since the function allocates storage to hold the image, it is up to you to free this storage by calling L_FreeBitmap.”
Placement of the L_FreeBitmap call can be crucial in avoiding memory leaks. Since pixel data is typically the largest memory object in the bitmap handle, failing to free it correctly could cause huge leaks.
Also, if your code is allocating the BITMAPHANDLE structure itself using the “new” operator, you need to delete it once done with it. Even though the structure itself is typically much smaller in size than the pixel data, you should never allow any type of memory leak in your application.
If you run into any problem related to LEADTOOLS functions, feel free to email the details to our support address support#leadtools.com. Email support is free for all versions of the toolkit, whether Release (purchased) or free evaluation.
Ok, this statement worked, just had to put it in a different place
if ((bmh).Flags.Allocated)
L_FreeBitmap(&bmh);
Still got problems with GdiplusBitmap and loading images with .bmp extension, but that's already something else.
Also, in VS2017 you can go Debug -> Performance Profiler()... (Alt+F2) to use some tools for inspecting CPU / GPU / Memory Usage.
I am trying to pass some data from my kernel driver up to the user application.
I have defined the structure in my header file shared by my driver and application:
typedef struct _CallBack
{
HANDLE hParId;
HANDLE hProId;
BOOLEAN bCreate;
}CB_INFO, *PCB_INFO;
In my driver, I have a switch statement
case IOCTL_CODE:
if (outputBufferLength >= sizeof(PCB_INFO))
{
callback->hParId = deviceExtension->hParId;
callback->hProId = deviceExtension->hProId;
callback->bCreate = deviceExtension->bCreate;
Irp->IoStatus.Information = outputBufferLength;
Status = STATUS_SUCCESS;
}
I have tried debugging the code by using DbgPrint, there was nothing wrong with the if statement, as outputBufferLength is 12 and PCB_INFO is 8.
As for the DeviceIoControl code in my application:
DeviceIoControl(
driver,
IOCTL_CODE,
0,
0,
&callback,
sizeof(callback),
&bytesReturn,
NULL);
I have checked the bytesReturn and it does not return 0, it returns a 12.
Other info:
I am using 64-bit Windows 7.
I really have no idea what is wrong, and really would appreciate any form of help. I would be glad to provide more of my code if you need more details. Could it be something to do with me writing the driver on a 64-bit platform, or is there just something wrong with my code?
Thanks in advance!
Firstly, PCB_INFO is a pointer type, so sizeof(PCB_INFO) is the size of a pointer, not the size of the buffer you're pointing to. Use sizeof(CB_INFO) or sizeof(*PCB_INFO) instead. The code shown in the question is actually writing past the end of the buffer, so the results are unpredictable.
Secondly, your structure includes two elements of type HANDLE which has a different size in 32-bit and 64-bit architectures. In most situations Windows automatically takes care of converting ("thunking") between 32-bit and 64-bit structures, but in the case of I/O control codes this is your driver's responsibility. This is described in the DDK article Supporting 32-Bit I/O in Your 64-Bit Driver.
Alternatively you can make your application 64-bit, or change the structure so that it uses only elements of constant size.
I have an issue with WinInet's InternetReadFile (C++).
In some rare cases the function fails and GetLastError returns the mentioned error 0x8007007a (which according to ErrorLookup corresponds to "The data area passed to a system call is too small").
I have a few questions regarding this:
Why does this happen in some rare cases but in other cases works
fine (I'm talking of course about always downloading the same ~15MB
zip file) ?
Is this really related to the buffer size passed to the API call ? I am using a const buffer size of 1024 BYTES for this call. Should I use a bigger buffer size ? If so, how can I know what is the "right" buffer size ?
What can I do to recover during run time if I do get this error ?
Adding a code snippet (note that this will not work as is because some init code is necessary):
#define HTTP_RESPONSE_BUFFER_SIZE 1024
std::vector<char> responseBuffer;
DWORD dwResponseBytesRead = 0;
do
{
const size_t oldBufferSize = responseBuffer.size();
responseBuffer.resize(oldBufferSize + HTTP_RESPONSE_BUFFER_SIZE);
// Now we read again to the last place we stopped
// writing in the previous iteration.
dwResponseBytesRead = 0;
BOOL bInternetReadFile = ::InternetReadFile(hOpenRequest, // hFile. Retrieved from a previous call to ::HttpOpenRequest
(LPVOID)&responseBuffer[oldBufferSize], // lpBuffer.
HTTP_RESPONSE_BUFFER_SIZE, // dwNumberOfBytesToRead.
&dwResponseBytesRead); // lpdwNumberOfBytesRead.
if(!bInternetReadFile)
{
// Do clean up and exit.
DWORD dwErr = ::GetLastError(); // This, in some cases, will return: 0x7a
HRESULT hr = HRESULT_FROM_WIN32(dwErr); // This, in some cases, will return: 0x8007007a
return;
}
// Adjust the buffer according to the actual number of bytes read.
responseBuffer.resize(oldBufferSize + dwResponseBytesRead);
}
while(dwResponseBytesRead != 0);
It is a documented error for InternetReadFile:
WinINet attempts to write the HTML to the lpBuffer buffer a line at a time. If the application's buffer is too small to fit at least one line of generated HTML, the error code ERROR_INSUFFICIENT_BUFFER is returned as an indication to the application that it needs a larger buffer.
So you are supposed to handle this error by increasing the buffer size. Just double the size, repeatedly if necessary.
There are some discrepancies in question. It isn't clear that you are reading an HTML file for one, 15MB seems excessive. Another is that this error should repeat well. But most troubling is the error code value, it is wrapped in an HRESULT, the kind of error code that a COM component would return. You should be getting a Windows error code back from GetLastError(), just 0x7a and not 0x8007007a.
Do make sure that your error checking is correct. Only ever call GetLastError() when InternetReadFile() returned FALSE. If that checks out (always post a snippet please) then do consider that this error is actually generated upstream, perhaps the firewall or flaky anti-malware.
I am tring to create a Remote thread that will load a DLL I wrote, and run a function from it.
The DLL is working fine (Checked) but from some reason, the Remote thread fails and the proccess in which it was created stop responding.
I used ollyDebug to try and see what is going wrong and I noticed two things...
My strings (dll name and function name) are passed to the remote thread correctly
The thread fails on LoadLibrary with lasterror code 87 "ERROR_INVALID_PARAMETER"
My best guess is that somehow, The remote thread can't find LoadLibrary (Is this because the linker is done with repspect to my proccess???, Just a guess...)
What am I doing wrong?
This is the code to the remote function:
static DWORD WINAPI SetRemoteHook (DATA *data)
{
HINSTANCE dll;
HHOOK WINAPI hook;
HOOK_PROC hookAdress;
dll = LoadLibrary(data->dll);
hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
if (hookAdress != NULL)
{
(hookAdress)();
}
return 1;
}
Edit:
This is the part in which I allocate the memory to the remote proccess:
typedef struct
{
char* dll;
char* func;
} DATA;
char* dllName = "C:\\Windows\\System32\\cptnhook.dll";
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );
Edit:
It looks like the problem is that the remote thread is calling a "garbage" address
instead of LoadLibrary base address. Is there a possibily Visual studio linked
the remote proccess LoadLibrary address wrong?
Edit:
when I try to run the same exact code as a local thread (I use a handle to the current procces in CreateRemoteThread) the entire thing works just fine. What can cause this?
Should I add the calling function code? It seems to be doing its job as
the code is being executed in the remote thread with the correct parameters...
The code is compiled under VS2010.
data is a simple struct with char* 's to the names. (As explicetly writing the strings in code would lead to pointers to my original proccess).
What am I doing wrong?
Failing with ERROR_INVALID_PARAMETER indicates that there is a problem with the parameters passed.
So one should look at data->dll which represents the only parameter in question.
It is initialised here:
lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);
So let's add a check whether the allocation of the memory which's reference should be store into lData.dll really succeded.
if (!lData.dll) {
// do some error logging/handling/whatsoever
}
Having done so, you might have detected that the call as implemented failed because (verbatim from MSDN for VirtualAllocEx()):
The function fails if you attempt to commit a page that has not been
reserved. The resulting error code is ERROR_INVALID_ADDRESS.
So you might like to modifiy the fourth parameter of the call in question as recommended (again verbatim from MSDN):
To reserve and commit pages in one step, call VirtualAllocEx with
MEM_COMMIT | MEM_RESERVE.
PS: Repeat this exercise for the call to allocate lData.func. ;-)
It's possible that LoadLibrary is actually aliasing LoadLibraryW (depending on project settings), which is the Unicode version. Whenever you use the Windows API with "char" strings instead of "TCHAR", you should explicitly use ANSI version names. This will prevent debugging hassles when the code is written, and also in the future for you or somebody else in case the project ever flips to Unicode.
So, in addition to fixing that horrible unterminated string problem, make sure to use:
LoadLibraryA(data->dll);
If I use a class/method like the one described here how can I get the description/address of the call at the top of the stack?
Basically I want some value I can use in a call to our bug tracking system. I want to "uniquely" identify based on the address of the instruction that caused the exception.
(It is usually something of the form of mydll.dll!1234ABDC())
EDIT:
Some background information:
I am creating a minidump to email to a defect tracking system (fogbugz). In order to reduce duplicates I am trying to come up with a reasonable "signature" for the crash. I know there is an xml PI for FB, but it requires a user logon and we are not sure yet that we can afford to have people sniffing our traffic and getting user information. Emailing is also simpler for now to implement. Later on we will use the XML API to submit minidumps.
You need to put the code to do this in your exception filter, by the time you get to the exception handler much of the context information for the exception has been lost.
try
{
// whatever
}
except (MyExceptionFilter(GetExceptionInformation()))
{
}
Your filter will look something like this
LONG WINAPI MyExceptionFilter (
EXCEPTION_POINTERS * pExcept,
BOOL fPassOn)
{
EXCEPTION_RECORD * pER = pExcept->ExceptionRecord;
DWORD dwExceptionCode = pER->ExceptionCode;
TCHAR szOut[MAX_PATH*4]; // exception output goes here.
szOut[0] = 0;
MEMORY_BASIC_INFORMATION mbi;
DWORD cb = VirtualQuery (pER->ExceptionAddress, &mbi, sizeof(mbi));
if (cb == sizeof(mbi))
{
TCHAR szModule[MAX_PATH];
if (GetModuleFileName ((HMODULE)mbi.AllocationBase, szModule, MAX_PATH))
{
wsprintf(szOut, "Exception at '%s' + 0x%X", szModule,
(ULONG_PTR)pER->ExceptionAddress - (ULONG_PTR)mbi.AllocationBase);
}
}
return EXCEPTION_EXECUTE_HANDLER;
}
Of course, you will need to adjust your output a bit for 64 bit architectures, since the ExceptionAddress and AllocationBase will be 64 bit quantities in that case.
The EXCEPTION_POINTERS struct which is sent to TopLevelFilter() contains an EXCEPTION_RECORD struct which contains the ExceptionAddress. Which this address you can figure out in which DLL the offending opcode is by enumerating the modules with CreateToolhelp32Snapshot. You can also use the functions in dbghelp.dll to find the symbol which correspond to the address (the function it is in)
GetExceptionInformation will return the EXCEPTION_POINTERS struct which contains information about the exception. The ExceptionRecord member contains an ExceptionAddress member, which is the address of the exception.
You'll need to map this address to a module relative location in your code to be useful. You can use GetModuleHandleEx with the GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS to get the HMODULE (which is also the base address of the module). GetModuleInformation can then be used to get the actual name of the module that the exception occurred in.
This may not be that helpful to you if the fault is actually inside of a system DLL. A more sophisticated scheme would be to generate a stack trace (using Stackwalk64 in dbghelp), and ignoring the topmost frames that are not in your code.
You can avoid the pain of printing a string for the exception (what happens if you can save the minidump but can't format a string without crashing?) by saving the minidump instead and using cdb.exe or windbg.exe to extract the exception information.