How to access SetThreadDescription() in Windows 2016 Server, Version 1607 - c++

If I just call SetThreadDescription() from WinAPI, it works on Windows 10, Version 2004. However, on Windows 2016 Server, 1607 it produces the following message box:
The procedure entry point SetThreadDescription could not be located in the dynamic link library
and the path to my executable program follows in the message.
According to this article:
SetThreadDescription is only available by Run Time Dynamic Linking on
Windows Server 2016, 1607.
So I tried dynamic linking as follows:
typedef HRESULT (WINAPI *TSetThreadDescription)(HANDLE, PCWSTR);
namespace {
TSetThreadDescription gpSetThreadDescription = nullptr;
}
void Initialize() {
HMODULE hKernel32 = GetModuleHandleA("Kernel32.dll");
if (hKernel32 == nullptr) {
cerr << "FATAL: failed to get kernel32.dll module handle, error: " << GetLastError() << endl;
quick_exit(5);
}
gpSetThreadDescription = reinterpret_cast<TSetThreadDescription>(
GetProcAddress(hKernel32, "SetThreadDescription"));
if (gpSetThreadDescription == nullptr) {
cerr << "FATAL: failed to get SetThreadDescription() address, error: " << GetLastError() << endl;
quick_exit(6);
}
}
This code also works on Windows 10. However, I'm getting error 127 ("The specified procedure could not be found") on Windows Server 2016.
What am I doing wrong about the run-time dynamic linking?

Apparently, despite MSDN says "DLL: Kernel32.dll", the function is actually in KernelBase.DLL, so I've fixed the problem after changing to:
HMODULE hKernelBase = GetModuleHandleA("KernelBase.dll");

Related

CEN XFS: Opening Sensors and Indicator Module Causes Crash

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;
}

loadlibrary fails for current path with GetLastError() == 0

I have a simple program that loads a DLL from the current path
#include <iostream>
#include <windows.h>
using namespace std;
auto loaddll(const char * library) {
auto dllModule = LoadLibrary(library);
if(dllModule == NULL)
throw "Can't load dll";
return dllModule;
}
int main() {
try {
auto Handle = loaddll("ISab.dll");
} catch(const char * error) {
cerr << "An Unexpected error :" << error << endl;
cerr << "Get Last Error : " << GetLastError();
}
}
the load library fails for every DLL in the current path but succeeds for DLL like User.dll
if I ran it output will be like
An Unexpected error :Can't load dll
Get Last Error : 0
this also fails if i specify full path to dll
When a Win32 API call fails, and sets the error code, you must call GetLastError before calling any other Win32 API function. You don't do that.
Raising an exception, streaming to cerr etc. are all liable to call other Win32 API functions and so reset the error code.
Your code must look like this:
auto dllModule = LoadLibrary(library);
if (dllModule == NULL)
auto err = GetLastError();
Once you have the error code you should be better placed to understand why the module could not be loaded. Common error codes for LoadLibrary include:
ERROR_MOD_NOT_FOUND which means that the module, or one of its dependencies, cannot be located by the DLL search.
ERROR_BAD_EXE_FORMAT which invariably means a 32/64 bit mismatch, either with the module you load, or one of its dependencies.

WinRT library not working in Release mode

I've have been trying to build a desktop application using WinRT libraries in Visual Studio 2012.
The code snippet goes as follows.
[STAThread]
int wmain (Platform :: Array <String ^> ^ args)
{
wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl;
wcout << L"FindPackages sample" << endl << endl;
try
{
auto packageManager = ref new Windows::Management::Deployment::PackageManager();
auto packages = packageManager->FindPackages();
int packageCount = 0;
std::for_each(Windows::Foundation::Collections::begin(packages), Windows::Foundation::Collections::end(packages),
[&packageManager, &packageCount](Windows::ApplicationModel::Package^ package)
{
DisplayPackageInfo(package);
DisplayPackageUsers(packageManager, package);
wcout << endl;
packageCount += 1;
});
}
catch (AccessDeniedException^)
{
wcout << L"FindPackagesSample failed because access was denied. This program must be run from an elevated command prompt." << endl;
return 1;
}
catch (Exception^ ex)
{
wcout << L"FindPackagesSample failed, error message: " << ex->ToString()->Data() << endl;
return 1;
}
getchar();
return 0;
}
This is used to list the metro apps details. And this code works fine in DEBUG mode. But when I change it to release mode, I am getting an error:
error LNK2001: unresolved external symbol _NtProcessStartup
NOTE:
I've changed certain settings such as
Configuration properties -> C/C++-> COnsume Windows Runtime Exception to Yes(/ZW)Configuration properties -> C/C++-> Code Generation-> Enable Minimal Rebuild to NO(/gm-)Configuration properties -> C/C++-> Code Generation-> Runtime LIbrary to Multi-threaded DLL(/MD)
Its been told that these settings are mandatory for WinRT library inclusion.
So basically, I have to run my code in Multi_Threaded (/MT) format for Release mode. But /MT or /Mtd is not compatible with (/ZW) method which is necessary for WinRT libraries.
Please guide me on my mistakes.
The fact that you get a message about a missing NtProcessStartup symbol implies that the linker switch /SUBSYSTEM:NATIVE was used. Because this in the only option that requires a NtProcessStartup function instead of wmain/main. So your release mode options have somehow marked your application as a NATIVE (usually device driver) application. (Or you specifically added a /ENTRY:NtProcessStartup but that seems very unlikely to me).

GLFW 3 initialized, yet not?

I'm struggling with creating a window with the GLFW 3 function, glfwCreateWindow.
I have set an error callback function, that pretty much just prints out the error number and description, and according to that the GLFW library have not been initialized, even though the glfwInit function just returned success?
Here's an outtake from my code
// Error callback function prints out any errors from GFLW to the console
static void error_callback( int error, const char *description )
{
cout << error << '\t' << description << endl;
}
bool Base::Init()
{
// Set error callback
/*!
* According to the documentation this can be use before glfwInit,
* and removing won't change anything anyway
*/
glfwSetErrorCallback( error_callback );
// Initialize GLFW
/*!
* This return succesfull, but...
*/
if( !glfwInit() )
{
cout << "INITIALIZER: Failed to initialize GLFW!" << endl;
return false;
}
else
{
cout << "INITIALIZER: GLFW Initialized successfully!" << endl;
}
// Create window
/*!
* When this is called, or any other glfw functions, I get a
* "65537 The GLFW library is not initialized" in the console, through
* the error_callback function
*/
window = glfwCreateWindow( 800,
600,
"GLFW Window",
NULL,
NULL );
if( !window )
{
cout << "INITIALIZER: Failed to create window!" << endl;
glfwTerminate();
return false;
}
// Set window to current context
glfwMakeContextCurrent( window );
...
return true;
}
And here's what's printed out in the console
INITIALIZER: GLFW Initialized succesfully!
65537 The GLFW library is not initialized
INITIALIZER: Failed to create window!
I think I'm getting the error because of the setup isn't entirely correct, but I've done the best I can with what I could find around the place
I downloaded the windows 32 from glfw.org and stuck the 2 includes files from it into minGW/include/GLFW, the 2 .a files (from the lib-mingw folder) into minGW/lib and the dll, also from the lib-mingw folder, into Windows/System32
In code::blocks I have, from build options -> linker settings, linked the 2 .a files from the download. I believe I need to link more things, but I can figure out what, or where I should get those things from.
I tried reinstalling codeblocks and mingw, which solved the issue.
Seems like GLFW3 doesn't like having previous versions installed at the same time for some reason, so if anyone else is having a similar problem, you might want to try that.
I experienced similar problems in Cocos 3.8.1 and 3.10.
I have never installed codeblocks or mingw, so it did not make sense to install them for me.
The GLFW.lib file in the cocos directory is out of date.
http://www.glfw.org/download.html, and replace the lib file in your project with the latest one, and it may resolve your error.

Meaning of a numerical ErrorMessage

I am trying to interface with an OEM library. Everything worked on one computer but I am getting lots of problems on another computer.
I the code is throwing a COM exception but I can't figure out the meaning of a error code that doesn't have a ErrorMessage();
The code
#include "stdafx.h"
#include <afx.h>
#include <iostream>
using namespace std;
#import "MTBApi.tlb" named_guids //raw_interfaces_only
using namespace MTBApi;
void DisplayError(_com_error* e)
{
CString message;
// if it is an application error thrown by .NET
if (e->Error() >= 0x80041000)
{
IErrorInfo* info;
BSTR msg;
info = e->ErrorInfo();
info->GetDescription(&msg);
info->Release();
message = CString(msg);
}
// other com errors
else
{
message = e->ErrorMessage();
}
cout << "MTB Error: " << message <<":"<<(unsigned int) e->Error()<< endl;
}
int main(int argc, char **argv)
{
for (int i = 0 ; i < 4 ; i++)
{
IMTBConnectionPtr m_MTBConnection;
try
{
cout <<"1" << endl;
HRESULT a = CoInitializeEx(NULL,COINIT_SPEED_OVER_MEMORY);
cout <<"2" << endl;
m_MTBConnection = IMTBConnectionPtr(CLSID_MTBConnection);
cout <<"3" << endl;
m_MTBConnection->Close();
cout <<"4" << endl;
CoUninitialize();
cout <<"5" << endl;
}
catch(_com_error e)
{
DisplayError(&e);
}
cout << endl;
}
}
The runtime output
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
1
2
MTB Error: 00000000002205F8:2147746132
Rather Verbose Output from Dependency Walker
http://pastebin.com/7Y33z3Pj
cout << "MTB Error: " << message <<":"<<(unsigned int) e->Error()<< endl;
cout isn't very good at displaying Unicode strings, it merely displays the string pointer value. Not useful of course, use wcout instead. And favor displaying the error code in hex. 0x80040154 is a very common COM error, "Class not registered". Thousands of questions about it already, you just need to get the COM server registered properly. Ask the vendor or author if you don't know how to do that.
00000000002205F8 looks like a memory pointer. You are passing a CString to cout, which only accepts char* or std::string for string values. Maybe the CString contains a Unicode string that is not being converted to Ansi correctly. Also, when calling IErrorInfo::GetDescription(), you are leaking the returned BSTR. You need to free it with SysFreeString() when you are done using it.
Error code 2147746132 (hex 0x80040154) is Severity=FAIL, Facility=FACILITY_ITF, Code=340. FACILITY_ITF typically means the error code is a custom error code defined by the interface that failed. But in this case, 0x80040154 is also a standard error code: REGDB_E_CLASSNOTREG.
If your problem is to rectify the error which you are getting then
then issue is as #Remy pointed out , your com assembly is not registered in the machine you are currently executing your program rather in the other machine it got registered. Register the assembly (for eg COMAssembly.dll which is in C:\ drive) by running the following command in command prompt.
regsvr32 c:\COMAssembly.dll
if its a C++ com assembly , if its a C# assembly register it by using command
regasm c:\COMAssembly.dll
(where regasm can be run in a VS command prompt , otherwise if you are running in normal command prompt then you have to first call vsvars32.bat then call regasm)