Feeling stupid here but why is this code giving me a syntax error in Visual
Studio when trying to compile it?
DetourAttach(&(PVOID&)true_create_file, create_file);
The compiler complains with (underlining the & after PVOID)
Error (active) E0018 expected a ')'
The code is literally copied from the Detours example page. I'm assuming it is because my containing file has a .c extension and is thus compiled as C by VS while the example has a .cpp extension and is compiled as C++.
I'm not entirely sure what's going on in this line with all the casting. Why doesn't the C compiler like it and how do I get it to compile this line?
Here's the complete listing of the code:
#include <Windows.h>
#include "detours.h"
#pragma comment(lib, "detours.lib")
static HANDLE(WINAPI *true_create_file) (LPCSTR file, DWORD access,
DWORD share, LPSECURITY_ATTRIBUTES sec, DWORD disp, DWORD flags,
HANDLE tmpl) = CreateFileA;
HANDLE WINAPI create_file(LPCSTR file, DWORD access, DWORD share,
LPSECURITY_ATTRIBUTES sec, DWORD disp, DWORD flags, HANDLE tmpl) {
}
int hook_create_file() {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
/* syntax error */
DetourAttach(&(PVOID&)true_create_file, create_file);
DetourTransactionCommit();
}
PVOID is defined as
typedef void *PVOID;
The &(PVOID&) part: cast the parameter to a reference to a pointer to void first, and then taking the address of that. As comment point out, you compile it as C, but the reference operation do not exist in C. So the compiler recognizes "&" as taking address, but only ")" behind it, then get the expected a ')' error.
Since PVOID& doesn't make sense here, just to increase readability. You could use PVOIDinstead of PVOID& here:
DetourAttach(&(PVOID)true_create_file, create_file);
You could also get the DetourAttach function details from here.
Related
I have code from BASS lib.
#ifndef BASSDEF
#define BASSDEF(f) WINAPI f
#else
#define NOBASSOVERLOADS
#endif
HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags);
I need redefine BASSDEF to call dlsym function. How can i do this?
Update:
I using this on Android NDK (Linux) i loaded bass module via function dlopen and i need to make all functions point (here is original header file of bass lib https://pastebin.com/Z2Ty9UsY ) to this loaded module via dlsym function. I need this to call all functions (from JNI inside bass.so) module easily.
Actually, BASSDEF is not a function. It's macro which is known at compile time. So let's unwrap it ourselves:
HSAMPLE WINAPI BASS_SampleLoad(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags);
Whoa, just function declaration here. Now "WINAPI" is basicly __stdcall call convention (Microsoft-specific). But, looking to BASS header you provided one can find for non-WIN32 systems:
#define WINAPI
Basicly, under Linux it's just a placeholder which expands to nothing. Now function declaration looks like this:
HSAMPLE BASS_SampleLoad(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags);
What's next? You would like to find this function in some shared library via dlsym?
I assume you wants something like this:
// Declare a function pointer in C++11 style
using BASS_SampleLoad_FuncPtr = std::add_pointer<decltype(BASS_SampleLoad)>::type;
// Open library you wants
void* soHandle = dlopen("your_lib_here.so", RTLD_LAZY);
// Error check!
if (nullptr == soHandle) {
// Fail here
}
// Finally, get pointe to function!
BASS_SampleLoad_FuncPtr BASS_SampleLoad = reinterpret_cast<BASS_SampleLoad_FuncPtr>(dlsym(soHandle, "BASS_SampleLoad"));
// Error check!
if (nullptr == BASS_SampleLoad) {
// Fail here
}
// Now only here it's safe to call "BASS_SampleLoad" with required params
auto sample = BASS_SampleLoad(...);
...
// Don't forget to close lib
dlclose(soHandle);
Please, NOTE!
Provided code is not tested and might contain errors. And, it's C++11 standard.
Also, for C++14 and higher replace 'std::add_pointer<...>::type' with 'std::add_pointer_t<...>'
P.S. this code valid because BASS is cross-platform library and all WinAPI-look-a-like stuff (WINAPI, QWORD, BOOL, DWORD, etc.) is defined for Linux in BASS header
I wrote some native C++ code with the help of the Internet that loads the .NET Runtime and invokes a method that has the signature: public static int MethodNameHere(String pwzArgument) from a class in a managed assembly.
However, I can't seem to compile the code using Visual Studio into a native DLL (64-bit), because there seems to be a linking issue with CLRCreateInstance(), even though I am including "MetaHost.h" in the .cpp source file.
Here is the entire code:
#include "MetaHost.h"
extern "C" {
__declspec(dllexport) DWORD __stdcall CallManagedMethod(LPCWSTR managedDLLPath, LPCWSTR classPathInAssembly, LPCWSTR methodName, LPCWSTR parameter) {
// Bind to the CLR runtime..
ICLRMetaHost* pMetaHost = nullptr;
CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*) &pMetaHost);
ICLRRuntimeInfo* pRuntimeInfo = nullptr;
pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*) &pRuntimeInfo);
ICLRRuntimeHost* pClrRuntimeHost = nullptr;
pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*) &pClrRuntimeHost);
pClrRuntimeHost->Start();
// Okay, the CLR is up and running in this (previously native) process.
// Now call a method on our managed C# class library.
DWORD dwRet = 0;
pClrRuntimeHost->ExecuteInDefaultAppDomain(managedDLLPath, classPathInAssembly, methodName, parameter, &dwRet);
// Don't forget to clean up.
pClrRuntimeHost->Release();
pRuntimeInfo->Release();
pMetaHost->Release();
return dwRet;
}
}
Any help?
A .h file does not solve a linking problem, it merely adds them. The MSDN article you linked to fumbles the usual way that include and link hints are documented, "Included as a resource" is quite unhelpful. In C++ you have to link mscoree.lib to get the symbol resolved. It is the import library for mscoree.dll and included in the SDK.
Simplest way is to add #pragma comment(lib, "mscoree.lib") after your #include.
this is the test code
#include "windows.h"
#include "iostream"
using namespace std;
__declspec(thread) int tls_int = 0;
void NTAPI tls_callback(PVOID, DWORD dwReason, PVOID)
{
tls_int = 1;
}
#pragma data_seg(".CRT$XLB")
PIMAGE_TLS_CALLBACK p_thread_callback = tls_callback;
#pragma data_seg()
int main()
{
cout<<"main thread tls value = "<<tls_int<<endl;
return 0;
}
build with Multi-threaded Debug DLL (/MDd)
run result : main thread tls value = 1
build with Multi-threaded Debug (/MTd)
run result : main thread tls value = 0
Looks like can not capture the main thread created when use the MTd
why ?
While Ofek Shilon is right that the code is missing an ingredient, his answer contains only part of the whole ingredient. Full working solution can be found here which is in turn taken from here.
For explanation on how it works you may refer to this blog (assume we are working with VC++ compiler).
For convenience the code is posted below (note both x86 & x64 platforms are supported):
#include <windows.h>
// Explained in p. 2 below
void NTAPI tls_callback(PVOID DllHandle, DWORD dwReason, PVOID)
{
if (dwReason == DLL_THREAD_ATTACH)
{
MessageBox(0, L"DLL_THREAD_ATTACH", L"DLL_THREAD_ATTACH", 0);
}
if (dwReason == DLL_PROCESS_ATTACH)
{
MessageBox(0, L"DLL_PROCESS_ATTACH", L"DLL_PROCESS_ATTACH", 0);
}
}
#ifdef _WIN64
#pragma comment (linker, "/INCLUDE:_tls_used") // See p. 1 below
#pragma comment (linker, "/INCLUDE:tls_callback_func") // See p. 3 below
#else
#pragma comment (linker, "/INCLUDE:__tls_used") // See p. 1 below
#pragma comment (linker, "/INCLUDE:_tls_callback_func") // See p. 3 below
#endif
// Explained in p. 3 below
#ifdef _WIN64
#pragma const_seg(".CRT$XLF")
EXTERN_C const
#else
#pragma data_seg(".CRT$XLF")
EXTERN_C
#endif
PIMAGE_TLS_CALLBACK tls_callback_func = tls_callback;
#ifdef _WIN64
#pragma const_seg()
#else
#pragma data_seg()
#endif //_WIN64
DWORD WINAPI ThreadProc(CONST LPVOID lpParam)
{
ExitThread(0);
}
int main(void)
{
MessageBox(0, L"hello from main", L"main", 0);
CreateThread(NULL, 0, &ThreadProc, 0, 0, NULL);
return 0;
}
EDIT:
Definitely some explanations are required so let us take a look on what's going on in the code.
If we want to use TLS callbacks then we are to tell the compiler about it explicitly. It is done with the including of the variable _tls_used which has a pointer to the callback array (null-terminated). For the type of this variable you may consult tlssup.c in CRT source code coming along with Visual Studio:
For VS 12.0 by default it lies here: c:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\
For VS 14.0 by default it lies here: c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\vcruntime\
It is defined in the following way:
#ifdef _WIN64
_CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY64 _tls_used =
{
(ULONGLONG) &_tls_start, // start of tls data
(ULONGLONG) &_tls_end, // end of tls data
(ULONGLONG) &_tls_index, // address of tls_index
(ULONGLONG) (&__xl_a+1), // pointer to call back array
(ULONG) 0, // size of tls zero fill
(ULONG) 0 // characteristics
};
#else /* _WIN64 */
_CRTALLOC(".rdata$T")
const IMAGE_TLS_DIRECTORY _tls_used =
{
(ULONG)(ULONG_PTR) &_tls_start, // start of tls data
(ULONG)(ULONG_PTR) &_tls_end, // end of tls data
(ULONG)(ULONG_PTR) &_tls_index, // address of tls_index
(ULONG)(ULONG_PTR) (&__xl_a+1), // pointer to call back array
(ULONG) 0, // size of tls zero fill
(ULONG) 0 // characteristics
};
This code initializes values for IMAGE_TLS_DIRECTORY(64) structure which is pointed to by the TLS directory entry. And pointer to call back array is one of its fields. This array is traversed by the OS loader and pointed functions are being called until null pointer is met.
For info about directories in PE file consult this link from MSDN and search for a description of IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES].
x86 note: as you can see, the same name _tls_used is met in tlssup.c for both x86 & x64 platforms, but additional _ is added when including this name for x86 build. It's not a typo but linker feature, so effectively naming __tls_used is taken.
Now we are at the point of creating our callback. Its type can be obtained from the definition of IMAGE_TLS_DIRECTORY(64) which can be found in winnt.h, there is a field
for x64:
ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *;
and for x86:
DWORD AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *
The type of callbacks is defined as follows (also from winnt.h):
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (PVOID DllHandle, DWORD Reason, PVOID Reserved);
It is the same as for DllMain and it can handle the same set of events: process\thread attach\detach.
It is time to register callback.
First of all take a look at the code from tlssup.c:
Sections allocated in it:
_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
/* NULL terminator for TLS callback array. This symbol, __xl_z, is never
* actually referenced anywhere, but it must remain. The OS loader code
* walks the TLS callback array until it finds a NULL pointer, so this makes
* sure the array is properly terminated.
*/
_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
It is very important to know what is special in $ when naming PE section, so the quote from the article named "Compiler and linker support for implicit TLS":
Non-header data in a PE image is placed into one or more sections,
which are regions of memory with a common set of attributes (such as
page protection). The __declspec(allocate(“section-name”)) keyword
(CL-specific) tells the compiler that a particular variable is to be
placed in a specific section in the final executable. The compiler
additionally has support for concatenating similarly-named sections
into one larger section. This support is activated by prefixing a
section name with a $ character followed by any other text. The
compiler concatenates the resulting section with the section of the
same name, truncated at the $ character (inclusive).
The compiler alphabetically orders individual sections when
concatenating them (due to the usage of the $ character in the section
name). This means that in-memory (in the final executable image), a
variable in the “.CRT$XLB” section will be after a variable in the
“.CRT$XLA” section but before a variable in “.CRT$XLZ” section. The C
runtime uses this quirk of the compiler to create an array of null
terminated function pointers to TLS callbacks (with the pointer stored
in the “.CRT$XLZ” section being the null terminator). Thus, in order
to ensure that the declared function pointer resides within the
confines of the TLS callback array being referenced by _tls_used, it
is necessary place in a section of the form “.CRT$XLx“.
There may be actually 2+ callbacks (we will actually use only one) and we may want to call them in order, now we know how. Just place these callbacks in sections named in alphabetical order.
EXTERN_C is added to forbid C++-style name mangling and use a C-style one.
const and const_seg are used for x64 version of the code because otherwise it fails to work, I don't know exact reason for this, the guess may be that CRT sections' access rights are different for x86 & x64 platforms.
And finally we are to include name of the callback function for linker to know it is to be added to the TLS call back array. For note about additional _ for x64 build see the end of p.1 above.
You also must explicitly add the symbol __tls_used. With this your code should work:
#pragma comment(linker,"/include:__tls_used")
This is my first time dealing with windows. I tried to create thread, but I can't compile my code.
This is a part of my code:
WORD _tid;
HANDLE readerThread= CreateThread(0,0,readFromPort,0,0,&_tid);
DWORD WINAPI readFromPort(LPVOID lpParam ){}
I also tried :
LPDWORD_tid;
HANDLE readerThread= CreateThread(0,0,readFromPort,0,0,_tid);
DWORD WINAPI readFromPort(LPVOID lpParam ){}
Neither compiled. onyone knows what is the problem?
(I'm using windows xp)
thanks.
well, don't know what's error you have. But can provide a good example to you
#include "windows.h"
DWORD WINAPI readFromPort(LPVOID lpParam ){return 0;}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD _tid;
HANDLE readerThread= CreateThread(0,0,readFromPort,0,0,&_tid);
return 0;
}
difference to yours:
_tid is DWORD, not WORD.
the readFromPort returns value 0.
Let me guess: readFromPort must return a value?
Next time please add the error also.
Well, it would have been nice if you have provided a minimal code example and at least a compilation error. But fine, I will pretend to be a compiler. Assuming that your code snippet is inside a function, you have a function declaration in there:
DWORD WINAPI readFromPort(LPVOID lpParam ){}
I believe that is screwing you up. You have to declare/define functions outside other function's scope.
Also, readFromPort function is declared after the call to CreateThread where it is being referenced as a parameter. So it won't work even if you put all of that in a global scope (which is a bad idea in itself).
I'm using the following code (from MSDN) to rename a C++ thread:
#include <windows.h>
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void SetThreadName( DWORD dwThreadID, char* threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
And it is working great overall. However, when trying to execute this code in Visual Studio (2010) extension package, I get the following unhanded exception and the name of the thread doesn't change:
System.Runtime.InteropServices.SEHException occurred
Message: External component has thrown an exception.
Anyone has any clue what's going on there? I realize there might be some issues with changing a thread that way from extensions, however, it is undocumented and it seems to be working fine from a standard add-in.
Thanks!
I'm not certain whether this is the cause of your problem but according to this MSDN documentation the SetThreadName function only applies to native code. Judging from the exception you're seeing you're compiling with the /clr option so you should probably use the managed code equivalent of this. Follow the link under the See Also section in the first link, it shows the snippet to use for managed code.
HTH,
Ashish.
Sounds familiar. Here's what the insides of our SetThreadName looks like (in a mixed native C++, C++/CLI, C# app):
#pragma warning(disable: 6312 6322)
__try
{
RaiseException( 0x406D1388, 0, sizeof(info) / sizeof(DWORD), (DWORD*)&info );
}
// don't implement MSDN's suggested fix for 6312 here - it causes a nasty unhandled exception
// to bubble up into managed code. Disable the compiler warning instead.
__except(EXCEPTION_CONTINUE_EXECUTION)
{
}
#pragma warning(default: 6312 6322)