How to "WINAPI::GetLastError" in QT application? - c++

Why is last error in QT application always zero ?
SetLastError(23);
qDebug() << "LastError: " << GetLastError();
expected output:
LastError: 23
actual output:
LastError: 0
I can't google anything about this issue. Are these functions hooked by QT ?

DWORD lastError = GetLastError();
qDebug() << "LastError: " << lastError;
Always grab the last error immediately after the API call that failed. Those intervening qDebug() and operator<< calls themselves call Windows API functions, which may or may not reset the last error.

When you make calls to the runtime library then that in turn can call Win32 API functions, and reset the error value. Fix your code like this:
SetLastError(23);
DWORD err = GetLastError();
qDebug() << "LastError: " << err;
This ensures that you read the error value before the runtime makes calls to Win32 functions.

Related

FindWindowA() returns 0 and when i check the error code with GetLastError() it's also 0 (ERROR_SUCCESS)

This is a segment out of a dll injection code i'm writing.
I'm using FindWindowA() to get a HWND to the window procces defined in INJ_PROC_NAME.
The problem is that the function always returns 0 and when I check the error with GetLastError() it also returns 0. I can't tell what's the problem because the error code doesn't give me the correct information about the error.
HWND Hwnd = FindWindowA(NULL, INJ_PROC_NAME);
if (Hwnd == NULL)
{
std::cout << "Couldn't find window named \"" << INJ_PROC_NAME << "\": error-"
<< GetLastError() << std::endl;
getchar();
return -1;
}
This is the output:
Couldn't find window named "notepad.exe": error-0
Is this a known issue? I wasn't able to find any information about it in Microsoft's documentation or in stack overflow. I just can't figure this one out...
edit:
Obviously, notepad is open when i run the program.
Most likely the error gets clobberd somewhere in std::cout.
Try this:
if (Hwnd == NULL)
{
DWORD error = GetLastError(); // first thing we retrieve the error
std::cout << "Couldn't find window named \"" << INJ_PROC_NAME << "\": error-"
<< error << std::endl;
getchar();
return -1;
}
Saving the error number right after the failure as shown above must be done anyway.
But the true reason why FindWindow does not succeed is because it is not looking for the process name, but for the window title which is something like Untitled - Notepad.
Otherwise if FindWindow does not find the window, the last error is in deed not set in spite of what the the Microsoft documentation pretends.
Conclusion
Using FindWindow is probably not the best approach, you should rather enumerate processes as described in this Microsoft documentation.

How to locate where an error arises in a "PackageManager.AddPackageAsync" method call?

I'm debugging an example app that deploys an Windows Metro App Package (".Appx" file). It call a WinRT method "PackageManager.AddPackageAsync" which fails with detailed error code text (retrieved from the call return value after the operation was finished):
error 0x80070002: Windows cannot register the package because of an
internal error or low memory.
My target is to find where exactly this error arises in the WinRT call. I think the best way for achieving this is by finding where the error code is set. I've done this before with the old simple Win32 API but now with this new complex com-based, async Interface I got completely lost.
The example project files can be found at. Its main function looks like this:
[MTAThread]
int __cdecl main(Platform::Array<String^>^ args)
{
wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl;
wcout << L"AddPackage sample" << endl << endl;
if (args->Length < 2)
{
wcout << "Usage: AddPackageSample.exe packageUri" << endl;
return 1;
}
HANDLE completedEvent = nullptr;
int returnValue = 0;
String^ inputPackageUri = args[1];
try
{
completedEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (completedEvent == nullptr)
{
wcout << L"CreateEvent Failed, error code=" << GetLastError() << endl;
returnValue = 1;
}
else
{
auto packageUri = ref new Uri(inputPackageUri);
auto packageManager = ref new PackageManager();
auto deploymentOperation = packageManager->AddPackageAsync(packageUri, nullptr, DeploymentOptions::None);
deploymentOperation->Completed =
ref new AsyncOperationWithProgressCompletedHandler<DeploymentResult^, DeploymentProgress>(
[&completedEvent](IAsyncOperationWithProgress<DeploymentResult^, DeploymentProgress>^ operation, AsyncStatus)
{
SetEvent(completedEvent);
});
wcout << L"Installing package " << inputPackageUri->Data() << endl;
wcout << L"Waiting for installation to complete..." << endl;
WaitForSingleObject(completedEvent, INFINITE);
if (deploymentOperation->Status == AsyncStatus::Error) //Here I decided to track "deploymentOperation->Status"
{
auto deploymentResult = deploymentOperation->GetResults();
wcout << L"Installation Error: " << deploymentOperation->ErrorCode.Value << endl;
wcout << L"Detailed Error Text: " << deploymentResult->ErrorText->Data() << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Canceled)
{
wcout << L"Installation Canceled" << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Completed)
{
wcout << L"Installation succeeded!" << endl;
}
}
}
catch (Exception^ ex)
{
wcout << L"AddPackageSample failed, error message: " << ex->ToString()->Data() << endl;
returnValue = 1;
}
if (completedEvent != nullptr)
CloseHandle(completedEvent);
return returnValue;
}
As the operation (PackageManager.AddPackageAsync) should be async and am not really sure how to track the code executed in the new thread I decided to search where the "deploymentOperation->Status" variable was set (it appeared that this was actually a function call) to "AsyncStatus::Error" (or the integer 3). After I gone through a LOT of code and function calls I understand that whenever this variable will be set or no (it seems it doesn't matter BUT it's certain that this function retrieves the operation error data) depends of a member of variable initialised by an Undocumented ntdll function call named "NtGetCompleteWnfStateSubscription" by it's pointer. It was called from ntdll too. The structure of the variable member I mentioned is the following:
struct Unknown
{
AsyncStatus /*? 32bit long*/ dw0; // it was set to '3' during the current operation as the AsyncStatus::error enum value so I think it should belong to it
DWORD dw4; //was set to 0x5F
DWORD dw8; //was set to 0x80073CF6 (some generic error)
} ;
The code in ntdll where the "NtGetCompleteWnfStateSubscription" function was called, initing the variable which member have this structure type (in assembly, IDA PRO generated):
ntdll.dll:77906200 loc_77906200: ; CODE XREF: ntdll.dll:ntdll_strncpy_s+1A3j
ntdll.dll:77906200 push 1030h
ntdll.dll:77906205 push esi ; the variable pointer
ntdll.dll:77906206 push edi
ntdll.dll:77906207 push eax
ntdll.dll:77906208 lea eax, [ebp-0Ch]
ntdll.dll:7790620B push eax
ntdll.dll:7790620C push ebx
ntdll.dll:7790620D call near ptr ntdll_NtGetCompleteWnfStateSubscription
ntdll.dll:77906212 test eax, eax ; now "[esi+2Ch] + esi" contains data from the "Unkown" structure and contains the operation error data
ntdll.dll:77906214 jns short loc_7790623F
The above code is actually called 3 times but with the same "esi" pointer. So now my question is how to find where the error code is set to be retrieved using this function. I tried capturing most of the function in ntdll that looks like doing this but without success. I can't debug NtGetCompleteWnfStateSubscription for some strange reason. Any suggestions will be helpful. I'm using IDA PRO 6.5, VS 2013 U1, Windows 8.1 x64 U1.
EDIT: If you don't want to bother with problem specific details my generic question is how to locate where WinRT async methods sets the "IAsyncInfo::Status" property or what function or method is called when an error arrises while executing them.

CLR ICLRControl::GetCLRManager fails with error HOST_E_INVALIDOPERATION

I have a native process which uses .NET component via COM interop. Once the process is up, I am trying to get interface pointers to the various CLR managers such as ICLRDebugManager, ICLRGCManager, etc. using the ICLRControl interface pointer. I'm able to reach up to acquiring ICLRControl interface without a glitch. ICLRRuntimeInfo also correctly tells me that it is 4.0.x .net version when I call GetVersionString on it.
It is only that the ICLRControl::GetCLRManager keeps failing with error 0x80130122, which error code stands for HOST_E_INVALIDOPERATION. Searched the internet, but could not get information as to why this might be failing. Any help is much appreciated.
TIA.
WinCPP
Edit 1. Adding code snippet.
// ICLRRuntimeInfo interface pointer
CComQIPtr<ICLRRuntimeInfo> pCLRRuntimeInfo = pUnk;
if (!pCLRRuntimeInfo)
{
cout << "failed to get run time info interface pointer" << endl;
return;
}
TCHAR version[128];
memset(version, 0, 128);
DWORD count = 127;
pCLRRuntimeInfo->GetVersionString(version, &count);
cout << version << endl;
// ICLRRuntimeHost
CComPtr<ICLRRuntimeHost> pCLRRuntimeHost = 0;
hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pCLRRuntimeHost);
if (FAILED(hr))
{
cout << "failed to get run time host interface pointer" << endl;
return;
}
// ICLRControl
CComPtr<ICLRControl> pCLRControl = 0;
hr = pCLRRuntimeHost->GetCLRControl(&pCLRControl);
if (FAILED(hr))
{
cout << "failed to get clr control interface pointer" << endl;
return;
}
///////////////////////////////////////////
// Everything is successful upto this point
///////////////////////////////////////////
// ICLRGCManager
CComPtr<ICLRGCManager> pCLRGCManager = 0;
hr = pCLRControl->GetCLRManager(IID_ICLRGCManager, (LPVOID *)&pCLRGCManager);
if (FAILED(hr))
{
cout << "failed to get GC manager interface pointer" << endl;
return;
}
// Above call fails with the error 0x81031022, though everything is as per the MSDN documentation for the API
Looking at this source code on GitHub, it looks like CCorCLRControl::GetCLRManager will return HOST_E_INVALIDOPERATION if the runtime has already been started.
This explains why you are receiving that error code when attempting to "latch on to already loaded CLR instance," but that you meet with success when you create a CLR instance explicitly.

Inside exception handler, MessageBox() successfully returns IDOK but never shows

I'm using a self written exception class called windows_error that inherits from std::runtime_error, which I use to, well, properly handle unexpected errors from Windows API functions.
All the way on the bottom of the callstack, at the end of my WinMain function, I catch all windows_error exceptions that haven't been dealt with yet. I intend to handle them by display an error message right before the program terminates, like so:
int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, wchar_t *cmdline, int winshow)
{
// Initialize result to EXIT_FAILURE in case the program terminates due to
// an exception.
int result = EXIT_FAILURE;
try {
result = sIRC()();
}
catch (windows_error &e) {
e.basicHandler();
}
return result;
}
The basicHandler member function looks like this:
void windows_error::basicHandler() const
{
std::wostringstream ss;
ss << L"An unexpected error has occurred in a Windows function.\n\n" \
L"Function " << m_api << L" was called by " << m_caller << L" in " << m_srcFile << L" at line " << m_srcLine << L". " \
L"It returned error " << m_error << L":\n\n" << m_errorMessage;
#ifdef _CONSOLE
std::wcout << L"\n" << ss.str();
#else
auto result = MessageBox(HWND_DESKTOP, ss.str().c_str(), L"Windows error!", MB_ICONERROR);
result = result; // I added this line so I can put a breakpoint in the debugger
#endif // _CONSOLE
}
When I started out with the program I'm working on, this worked beautifully. But now the program is starting to grow. While trying out new code I noticed the program seemed to terminate unexpectedly. By running it in the Visual C++ 2010 debugger, I noticed a windows_error exception being thrown. By stepping through the basicHandler function, I could see that the MessageBox function returns 1 (IDOK) without actually showing the message box...
What could cause this behavior?
I know my description is a little vague, but I have no idea what else to add... I couldn't find anything on MSDN that would suggest this behavior is even possible. There is no parent window handle I could pass to MessageBox, since they're all being destroyed during stack unwinding. I'm also positive that the stack is not unwound through a window procedure or any other Windows callback.
Any hint at all would be appreciated.
Raymond provided the hint I needed in his comment to my question. During stack unwinding the destructor of my user_interface class calls DestroyWindow on the window handle because it is still valid at that point. What I didn't know was that MessageBox interprets the resulting WM_QUIT message to close itself. I thought a message box had its own internal message queue?
I was able to fix my issue by modifying the destructor of my user_interface class.
It was:
if (_wnd)
DestroyWindow(_wnd);
I changed it to:
if (_wnd) {
DestroyWindow(_wnd);
MSG msg = MSG();
while (msg.message != WM_QUIT) {
GetMessage(&msg, 0, 0, 0);
}
}
This works, but seems a little ugly. Any suggestions to improve this?

GetWindowText() returning empty string and strange error

I'm using the following code inside a global CBT hook procedure:
TCHAR title[256];
int getT = GetWindowText(hWnd, title, 256);
if (getT == 0) {
int err = GetLastError();
logFile << "Error GetWindowText(): " << err << endl;
} else {
logFile << "getT = " << getT << endl;
}
The problem is that for certain windows the GetWindowText() function works just fine and I get the correct window title, but for some others it returns 0 and I get an empty string. The GetLastError() returns 183 which is ERROR_ALREADY_EXISTS:
Cannot create a file when that file already exists.
The error is not random: I always get it with the same kind of window opened by the same application, but for all the other windows it seems to work fine.
You might not have the rights to retrieve text from certain windows on Windows Vista and above.
My guess is that ERROR_ALREADY_EXISTS comes from your log file when you print "Error GetWindowText(): ". You should get the error code first before doing anything else.
Another possibility is that the window returns 0 from its WM_GETTEXT handler without setting the last error. As GetWindowText documentation states, if you call it on a window belonging to the same process, it retrieves the text by sending this message. Since you are calling the function from a hook, you might be in the same process.