How to get description of winhttp errors using error codes? - error-handling

I am making a program that uses winhttp library. To handle various exceptions, I have created a header file. The error is thrown by using GetLastError() function which is passed to the exception class as DWORD variable. But I want to print the description of error and not just the error number. I tried using FormatMessage function, its working for error 6 but not for others viz error 12002. I am using it like:
WinHttpException(DWORD error)
{
LPTSTR lpszFunction = "Function";
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = error;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
m_message = boost::lexical_cast<std::string>(lpDisplayBuf);
}
I got this code from this Microsoft link.. Is there any other way to do that? Or what arguments should i use in FormatMessage function to make this work?
Thanks in advance.

WinHTTP error messages are contained in the winhttp.dll module and FormatMessage() function allows you to retrieve them using FORMAT_MESSAGE_FROM_HMODULE flag (as per FormatMessage() documentation):
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_IGNORE_INSERTS,
GetModuleHandle(TEXT("winhttp.dll")),
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPTSTR>(&lpMsgBuf),
0, NULL);

Related

error: use of undeclared identifier 'LP_c_uint'

I am using cppyy in my project to call C APIs.
I get below error log captured by capfd plugin in pytest, when an exception happens:
input_line_33:2:11: error: use of undeclared identifier 'LP_c_uint'
(sizeof (LP_c_uint))
It is coming from below code block, specifically logger.error() call:
try:
....
except Exception as e:
out, err = capfd.readouterr()
if err:
logger.error(err)
Now, if I grep my python source code, I don't any hits to 'LP_c_uint'.
Any pointers on how to debug this (like what may be causing this)?
Edit:
simple reproducer:
from ctypes import c_uint32, pointer, byref
import cppyy
from cppyy import sizeof
cppyy.cppdef(
"""
void func(uint32_t *param) {
std::cout << "param: " << *param << std::endl;
}
"""
)
if __name__ == "__main__":
param = pointer(c_uint32(17))
cppyy.gbl.func(param)
print(sizeof(param))
Output:
param: 17
input_line_22:2:11: error: use of undeclared identifier 'LP_c_uint'
(sizeof (LP_c_uint))
^
0
Yes, using ctypes.sizeof would solve it. I see the need for using ctypes.c_uint32 here (although using ctypes.pointer is not necessary) as there is no way of creating a pointer type from cppyy.gbl.uint32_t (which is basically Python's int, so internals to take a pointer to are not exposed).
cppyy.sizeof is now changed to forward to ctypes.sizeof as necessary. That'll make your code work and will be part of next release. As a current workaround, you can do something similar. For example:
def my_sizeof(tt):
try:
return ctypes.sizeof(tt)
except TypeError:
pass
return cppyy.sizeof(tt)

How to get DXGI_ERROR description?

In a D3D12 program, I encounter a DGXI_ERROR (CreateSharedHandle returns an int <0), but I could not find a way to translate it into the "error description" or "error name" (or both).
I have a description by Microsoft: https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-error
Is there such function out there ?
For development purposes, the "Error Lookup Tool" in Visual Studio can tell you the translation and code from a value.
You can also enable "DXGI Debugging" which will provide more information about error cases in the debug output window for your debug builds. See this blog post.
Programmatically, you can do it with FormatMessage on Windows 10:
LPWSTR errorText = nullptr;
DWORD result = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ALLOCATE_BUFFER, nullptr, hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&errorText), 0, nullptr );
if (result > 0)
{
// errorText contains the description of the error code hr
LocalFree( errorText );
}
else
{
// Error not known by the OS
}
See this blog post.

How to correctly implement error handling?

I am calling a function fit_circle that may or may not call the MESSAGE procedure. fit_circle calls a function poly_fit that may call the MESSAGE procedure, but also occasionaly produces a math error (there is nothing I can do about this).
Is it possible to contruct an error handler that will take care of all of these scenarios without returning to the interactive prompt? I have tried the following:
FUNCTION arb_funct,circular_data
CATCH, ERROR
IF ERROR NE 0 THEN BEGIN
CATCH, /CANCEL
print, 'An Error Occured'
return, []
ENDIF
circle_fit_result = fit_circle(circular_data)
return, circle_fit_result
END
However the error handler never triggers. The documentation only seems to mention looking for error handlers defined in procedures.
Works for me. Here is my example code:
pro mg_error_demo_helper2
compile_opt strictarr
a = b
end
pro mg_error_demo_helper1
compile_opt strictarr
mg_error_demo_helper2
end
pro mg_error_demo
compile_opt strictarr
catch, error
if (error ne 0L) then begin
catch, /cancel
print, 'An error occurred'
return
endif
mg_error_demo_helper1
end
When I run it, I get:
IDL> mg_error_demo
% Compiled module: MG_ERROR_DEMO.
error happened
IDL has three different types of "catchable" errors:
"Normal" Errors: These are the most common type of error to handle. They are thrown when message is called. Use catch or on_error to deal with them.
IO Errors: These happen when a conversion, disk read, memory, or other "IO" error occurs. Usually, these will also be caught by catch and on_error. When they aren't, use on_ioerror to deal with them.
Math Errors: These happen when you divide by 0, do certain math with NaN or infinity, etc. Deal with them using check_math and !except.
Here's an example of using all three in one program:
function arb_funct, circular_data
; handle normal errors
catch, error
if error ne 0 then begin
catch, /cancel
print, 'A normal error occured: ' + !error_state.msg
return, []
endif
; handle IO errors
on_ioerror, arb_funct__ioerror
if 0B then begin
arb_funct__ioerror:
print, 'An IO error occured: ' + !error_state.msg
return, []
endif
; clear math errors from previous routines
math_err = check_math(/print)
previous_except = !except
!except = 0
; do stuff
circle_fit_result = fit_circle(circular_data)
; handle math errors
math_err = check_math()
!except = previous_except
if math_err ne 0 then begin
print, 'A math error occured: ' + strtrim(math_err, 1)
return, []
endif
; and finally return
return, circle_fit_result
end
Here is an example of to what I referred:
FUNCTION some_function
;;--------------------------------------------------------------------------
;; Error handling [put towards beginning of routine]
;;--------------------------------------------------------------------------
CATCH, error_status
IF (error_status NE 0) THEN BEGIN
;; Cancel error handler
CATCH, /CANCEL
;; Print error message
PRINT, 'Error index: ', error_status
PRINT, 'Error message: ', !ERROR_STATE.MSG
;; Define return variable or how to handle error
;; --> I usually use a formatted output consistent with the expected
;; output, but here I will just use 0 for example.
dumb = 0
;; Return defined variable
RETURN,dumb
ENDIF
;;--------------------------------------------------------------------------
;; Main body of routine
;;--------------------------------------------------------------------------
blah = 0
; blah
; blah
; blah
;;--------------------------------------------------------------------------
;; Return to user
;;--------------------------------------------------------------------------
RETURN,return_variable
END
Hope that helps...

DeviceIoControl works in C++ and C# but return ERROR_INVALID_FUNCTION when called in C++/CLI

I am trying to enumerate the MFT to get list of file names.
This code works when used in a Win32 project:
MFT_ENUM_DATA med;
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = ujd.NextUsn;
BYTE pData[sizeof(DWORDLONG) + 0x10000];
DWORD cb;
while (DeviceIoControl(handleToVolume, FSCTL_ENUM_USN_DATA, &med, sizeof(med),
pData, sizeof(pData), &cb, NULL) != FALSE) {
//do the processing
}
But when I use the same code in C++/CLI, DeviceIoControl gives false and GetLastError gives ERROR_INVALID_FUNCTION.
When the same code is translated into C#, it works.
Any idea what is happening?
check if you have this define:
#define FSCTL_ENUM_USN_DATA
CTL_CODE(FILE_DEVICE_FILE_SYSTEM,44,METHOD_NEITHER,FILE_READ_DATA)
and replace FILE_READ_DATA with FILE_ANY_ACCESS

Listing WIA devices in C++/CLI fails with "cannot convert from 'int' to 'System::Object ^%'"

I'm trying to list all WIA devices with C++/CLI. I'm fairly new to C++/CLI (although I consider myself an intermediate C++ programmer), but I keep getting this error:
error C2664: 'WIA::IDeviceInfos::default::get' : cannot convert parameter 1 from 'int' to 'System::Object ^%'
when using the following code snippet:
DeviceManager^ dm = (gcnew WIA::DeviceManager());
for (int i = 1; i <= dm->DeviceInfos->Count; i++)
{
String^ deviceName = dm->DeviceInfos[i].Properties("Name")->get_Value()->ToString();
this->devices->Items->Add(deviceName);
}
Why should I treat that int as an Object? In Managed C++ there was the concept of boxing, but it doesn't work here and anyway I thought C++/CLI was introduced in order to get rid of it?
The Value property needs some non-obvious code to get it out. Try this:
WIA::DeviceInfo ^ info = dm->DeviceInfos[gcnew System::Int32(i)];
WIA::Property ^ propName = info->Properties[gcnew System::String(L"Name")];
String ^ strName = propName->default->ToString();