I've follow the next tutorial:
https://msdn.microsoft.com/en-us/library/64tkc9y5(v=vs.80).aspx
It is working fine for me. But I need to printf the response of the callbackfunctions:
printf(uReturnVal);
I get the error: cannot convert argument 1 from 'UINT' to 'const char *const '
I've tried another options:
printf(Convert.ToString(uReturnVal)); //ERROR :'Convert': undeclared identifier [
And:
printf(uReturnVal->ToString()); //ERROR: '->ToString' must point to class/struct/union/generic
And:
printf(uReturnVal.ToString());//error: /ERROR: '->ToString' must point to class/struct/union/generic
This is the code of the tutorial:
typedef UINT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT);
HINSTANCE hDLL; // Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
DWORD dwParam1;
UINT uParam2, uReturnVal;
hDLL = LoadLibrary("MyDLL");
if (hDLL != NULL)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,
"DLLFunc1");
if (!lpfnDllFunc1)
{
// handle the error
FreeLibrary(hDLL);
return true;
}
else
{
// call the function
uReturnVal = lpfnDllFunc1(dwParam1, uParam2);
}
}
Many thanks in advance.
First argument to printf functions is always format specifier. In your case printf("%u\n",uReturnVal) should work. See Format Specification Syntax: printf and wprintf Functions.
To Expand:
The code above is pure C.
You can also do it in C++ style, even more elegant:
#include <iostream>
...
uReturnVal = lpfnDllFunc1(dwParam1, uParam2);
std::cout << "Result is: " << uReturnVal << std::endl;
Related
I am getting the warning (treated as error):
Type Cast Pointer Truncation from HANDLE to ULONG
When I try to compile, I understand that the type has a different length as I am compiling ARM64 rather than ARM, therefore I need to change the type or static_cast it, however I receive errors such as "expected (" when changing the line to something like this:
return static_cast<ULONG>PsGetProcessId(current_process); //this gives me invalid conversion type as
//there are no brackets around the static cast
//because I am returning its value
I add brackets, however there is always a problem and it never seems to work, always "Expected (":
return (static_cast<ULONG>)PsGetProcessId(current_process); //this bracket error
ORIGINAL CODE BELOW
ULONG memory::get_process_id_by_name(PEPROCESS start_process, const char* process_name)
{
PLIST_ENTRY active_process_links;
PEPROCESS current_process = start_process;
do
{
PKPROCESS kproc = (PKPROCESS)current_process;
PDISPATCHER_HEADER header = (PDISPATCHER_HEADER)kproc;
LPSTR current_process_name = (LPSTR)((PUCHAR)current_process + IMAGE_FILE_NAME);
if (header->SignalState == 0 && strcmp(current_process_name, process_name) == 0)
{
return (ULONG)PsGetProcessId(current_process); //warning occurs here
}
active_process_links = (PLIST_ENTRY)((PUCHAR)current_process + ACTIVE_PROCESS_LINKS_FLINK);
current_process = (PEPROCESS)(active_process_links->Flink);
current_process = (PEPROCESS)((PUCHAR)current_process - ACTIVE_PROCESS_LINKS_FLINK);
} while (start_process != current_process);
return 0;
}
The HANDLE type is used to point to an opaque structure.
It usually stores an index value, but in the winnt.h header file, it is defined as a pointer-length type.
typedef void *HANDLE;
So the correct approach is to treat the process id as a pointer-length type as well.
I know you don't like HANDLE, so you can use ULONG_PTR, it has the same length as the pointer type.
Here is the fixed code:
ULONG_PTR memory::get_process_id_by_name(PEPROCESS start_process, const char* process_name)
{
PLIST_ENTRY active_process_links;
PEPROCESS current_process = start_process;
do
{
PKPROCESS kproc = (PKPROCESS)current_process;
PDISPATCHER_HEADER header = (PDISPATCHER_HEADER)kproc;
LPSTR current_process_name = (LPSTR)((PUCHAR)current_process + IMAGE_FILE_NAME);
if (header->SignalState == 0 && strcmp(current_process_name, process_name) == 0)
{
return (ULONG_PTR)PsGetProcessId(current_process);
}
active_process_links = (PLIST_ENTRY)((PUCHAR)current_process + ACTIVE_PROCESS_LINKS_FLINK);
current_process = (PEPROCESS)(active_process_links->Flink);
current_process = (PEPROCESS)((PUCHAR)current_process - ACTIVE_PROCESS_LINKS_FLINK);
} while (start_process != current_process);
return 0;
}
If you have to use ULONG for other reasons, you can refer to #SoronelHaetir's solution.
Example for comment:
Before:
void test()
{
ULONG value = (ULONG_PTR)0xFFFFFFFFFFFF;
UNREFERENCED_PARAMETER(value);
}
EXTERN_C NTSTATUS DriverEntry(DRIVER_OBJECT *pDriverObject, UNICODE_STRING *pRegistryPath)
{
UNREFERENCED_PARAMETER(pDriverObject);
UNREFERENCED_PARAMETER(pRegistryPath);
test();
return STATUS_UNSUCCESSFUL;
}
Warnings:
error C2220: the following warning is treated as an error
warning C4305: 'initializing': truncation from 'ULONG_PTR' to 'ULONG'
warning C4309: 'initializing': truncation of constant value
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
After:
#pragma warning(push)
#pragma warning(disable: 4305)
#pragma warning(disable: 4309)
void test()
{
ULONG value = (ULONG_PTR)0xFFFFFFFFFFFF;
UNREFERENCED_PARAMETER(value);
}
#pragma warning(pop)
EXTERN_C NTSTATUS DriverEntry(DRIVER_OBJECT *pDriverObject, UNICODE_STRING *pRegistryPath)
{
UNREFERENCED_PARAMETER(pDriverObject);
UNREFERENCED_PARAMETER(pRegistryPath);
test();
return STATUS_UNSUCCESSFUL;
}
No warnings:
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
Use ULONG_PTR instead of ULONG:
static_cast<ULONG_PTR>(hHandle)
If the value the handle holds is actually meant to be used as a ULONG then cast the ULONG_PTR to ULONG:
static_cast<ULONG>(static_cast<ULONG_PTR>(hHandle))
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <dos.h>
using namespace std;
class Dir
{
public:
char* cat;
Dir()
{
cout << "(C:/*)\n";
cat = new char[50];
cin >> cat;
}
void virtual ShowFiles()
{
}
};
class Inside : public Dir
{
public:
void virtual ShowFiles()
{
HANDLE hSearch;
WIN32_FIND_DATA pFileData;
hSearch = FindFirstFile(cat, &pFileData);
if (hSearch != INVALID_HANDLE_VALUE)
do
{
// if ((pFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
cout << pFileData.cFileName << "\n";
} while (FindNextFile(hSearch, &pFileData));
FindClose(hSearch);
}
};
int main()
{
Dir *obj1[2];
obj1[1] = new Inside;
obj1[1]->ShowFiles();
return 0;
}
So I have a program, I need to show with dynamic char cat all file in directory, but it is compilable in Borland C++ but in Visual Studio 15 + Resharper it doesn't work. Severity Code Description Project File Line
Error (active) argument of type "char *" is incompatible with parameter of type "LPCWSTR"
To compile your code in Visual C++ you need to use Multi-Byte char WinAPI functions instead of Wide char ones.
Set Project -> Properties -> Advanced (or. General for older versions) -> Character Set option to Use Multi-Byte Character Set
also see the screenshot
I actually found another way to resolve this error since above method did not work for me.
I casted all my constant character strings with (LPCWSTR). The solution looks like this
Earlier
MessageBox(NULL,"Dialog creation failed! Aborting..", "Error", MB_OK);
After casting to LPCWSTR
MessageBox(NULL, (LPCWSTR) "Dialog creation failed! Aborting..", (LPCWSTR) "Error", MB_OK);
So just copying the (LPCWSTR) and pasting wherever this error was generated resolved all my errors.
Another way to come by this issue, is to use the Lmacro in front of your string.
MessageBox(NULL, L"Dialog creation failed! Aborting..", L"Error", MB_OK);
See: What does the 'L' in front a string mean in C++?
or
L prefix for strings in C++
you can use wchar_t
class Dir
{
public:
wchar_t* cat;
Dir()
{
wcout << "(C:/*)\n";
cat = new wchar_t[50];
wcin >> cat;
}
void virtual ShowFiles()
{
}
};
In Visual Studio 2013 and later, the MFC libraries for multi-byle character encoding (MBCS) will be provided as an add-on to Visual Studio
It will work for any settings:
#include <tchar.h>
MessageBox(NULL, _T("Dialog creation failed! Aborting.."), _T("Error"), MB_OK);
I'm trying to find the address of the SetProcessDEPPolicy function of the Windows API in kernel32 (see my problem here and the first answer I got).
I've never written a Windows C++ program before so I'm a bit lost but I have this so far:
#include <windows.h>
#include <iostream>
int main(int argc, char* argv[])
{
HANDLE kernel32 = GetModuleHandle("kernel32");
FARPROC* funcAddr = (FARPROC *) GetProcAddress(kernel32, "SetProcessDEPPolicy");
std::cout << "# ";
}
I'm getting the following error on line 7:
C:\Documents and Settings\John\Desktop>c++ finddep.cpp -o finddep.exe finddep.cpp: In function 'int main(int, char**)': finddep.cpp:7:79: error: invalid conversion from 'HANDLE {aka void*}' to 'HINSTA NCE' [-fpermissive] FARPROC funcAddr = (FARPROC *) GetProcAddress(kernel32, "SetProcessDEPPolicy") ;
^
In file included from c:\mingw\include\windows.h:50:0,
from finddep.cpp:1: c:\mingw\include\winbase.h:1675:27: error: initializing argument 1 of 'int (__ attribute__((__stdcall__)) * GetProcAddress(HINSTANCE, LPCSTR))()' [-fpermissive ] WINBASEAPI FARPROC WINAPI GetProcAddress(HINSTANCE,LPCSTR);
^ finddep.cpp:7:79: error: cannot convert 'int (__attribute__((__stdcall__)) **)() ' to 'FARPROC {aka int (__attribute__((__stdcall__)) *)()}' in initialization FARPROC funcAddr = (FARPROC *) GetProcAddress(kernel32, "SetProcessDEPPolicy") ;
I couldn't find any good ideas on how to solve this from Google.
(Once I get this to compile, how can I print the address in the pointer?)
EDIT: Added Cyclone's suggestion from the comment, getting same error Invalid conversion from HANDLE to HINSTANCE
This is how you should do it:
#include <windows.h>
#include <iostream>
int main(int argc, char* argv[])
{
HMODULE kernel32 = GetModuleHandleA("kernel32");
FARPROC *funcAddr = (FARPROC *)GetProcAddress(kernel32, "SetProcessDEPPolicy");
std::cout << "#" << funcAddr;
}
I found this code for reading data from my USB peripheral:
#include "stdafx.h"
#define IWEARDRV_EXPLICIT
#include <windows.h>
#include <iweardrv.h>
int _tmain(int argc, _TCHAR* argv[])
{
// Load functions dynamically (in case they don't have a VR920)
HINSTANCE iweardll = LoadLibraryA("iweardrv.dll");
if (!iweardll) {
printf("VR920 drivers are not installed, you probably don't have a VR920.");
return 2;
}
IWROpenTracker = (PIWROPENTRACKER) GetProcAddress(iweardll, "IWROpenTracker");
IWRCloseTracker = (PIWRCLOSETRACKER) GetProcAddress(iweardll, "IWRCloseTracker");
IWRZeroSet = (PIWRZEROSET) GetProcAddress(iweardll, "IWRZeroSet");
IWRGetTracking = (PIWRGETTRACKING) GetProcAddress(iweardll, "IWRGetTracking");
IWRGetVersion = (PIWRGETVERSION) GetProcAddress(iweardll, "IWRGetVersion");
// Try to connect to the VR920 tracker
if (IWROpenTracker()) {
printf("VR920 is not connected.");
return 1;
}
// Read 20 samples
for (int i=1; i<=20; i++) {
LONG y, p, r;
double yaw, pitch, roll;
if (!IWRGetTracking(&y,&p,&r)) {
yaw = y*(180.0/32768.0);
pitch = p*(180.0/32768.0);
roll = r*(180.0/32768.0);
printf("Yaw=%lf degrees, Pitch=%lf degrees, Roll=%lf degrees", yaw, pitch, roll);
} else {
printf("Unable to read tracking.");
}
Sleep(500);
}
// Tidy up
IWRCloseTracker();
FreeLibrary(iweardll);
return 0;
}
Where I've setted additional include directory for include file iweardrv.h. It returns me these errors:
IntelliSense: argument of type "const char *" is incompatible with parameter of type "LPCWSTR"
IntelliSense: identifier "printf" is undefined
How do I avoid the errors? First error refers to LoadLibrary argument "iweardrv.dll" (a dynamic Library related to iweardrv.h) and second error refers to all printf calling lines.
EDIT: I corrected the first error using LoadLibraryA() because it takes a const char* but I cannot correct the second error.
The first error is because you are compiling with UNICODE defined and LoadLibrary expects a wide string. Use the L prefix to specify a wide literal:
LoadLibrary(L"iweardrv.dll");
The second error is due to a missing #include. You need to include stdio.h to define printf:
#include <stdio.h>
For C++ it would be more normal to use std::cout rather than printf.
I have a problem I've been struggeling with for a full week now, and I'm not able to solve it by myself. I've been googeling, and searching in all kind of forums... I have found lots of "this might work", tried it, but no, no success. If anyone have any clue, please, please, help me!
I'v got, from an external source, lots of classes and functions written in VB that I need to be able to use from a C++ application. My first though was: no problem, I turn the VB code into a dll, and load it from my C++-program. This was though harder than I ever could imagine. My C++-program is not written in Visual Studio, but for simplicity I started with trying to load my VB dll (written in Visual Studio 2010) from a Visual Studio C++ application. This is my code so far:
VB-code : DllModule : Class-library project
DllModule.vb
Namespace DllModule
Public Module DllModule
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long,
ByVal lpvReserved As Long) As Boolean
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
DllMain = True
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
Return True
End Function
'Simple function
Public Function Add(ByVal first As Integer, ByVal sec As Integer) As Integer
Dim abc As Integer
abc = first + sec
Return abc
End Function
End Module
End Namespace
DllModule.def
NAME DllModule
LIBRARY DllModule
DESCRIPTION "My dll"
EXPORTS DllMain #1
Add #2
C++-code : TryVbDllLoad : Console application
TryVbDllLoad.cpp
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <strsafe.h>
extern "C" {
__declspec(dllimport) int __stdcall Add(int, int);
}
typedef int (__stdcall *ptf_test_func_1_type)(int, int);
int __cdecl _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hdll = NULL;
hdll = LoadLibrary("DllModule.dll"); // load the dll
if(hdll) {
ptf_test_func_1_type p_func1=(ptf_test_func_1_type)GetProcAddress(hdll,"Add");
if(p_func1) {
int ret_val = (*p_func1)(1, 2);
} else {
DWORD dw = GetLastError();
}
FreeLibrary(hdll); // free the dll
} else {
DWORD dw = GetLastError();
}
return 0;
}
I can load the dll, but GetProcAddess returns NULL with error code 127 (the specified procedure could not be found).
I have tried to load the dll from a VB-application. This works (even without the .def-file). But I'm guessing there is no proper entry point created that the C++ application can use (when I open the dll in Dependency Walker I see no entry point or functions). I've tried compiling the VB-code both with and without "Register for COM interop".
1) What am I doing wrong?
2) If there isn't any nice way to solve this properly, what can I do instead of creating a dll? Is there any other way I can use the VB-classes and functions in my C++ application?
Kind Regards
Sara
Thanks for your answer Mare!
There must be some kind of error in my dll though, cause when I try to register is using regsvr32 I get: "The module C:/tmp/DllModule.dll was loaded, but the start address for DllRegisterServer was not found. Check that C:/tmp/DllModule.dll is a valid DLL- or OCX-file and try again."
Also, when I use
#import "C\tmp\DllModule.dll"
I get
fatal error C1083: Cannot open type library file: 'c:\tmp\dllmodule.dll'
I looked at the link with the tutorial, but there is a small problem: there are no such thing as "ActiveX DLL" to choose among all the project types. And yes, I do have Visual Studio 2010 Professional (a trial version, but still).
-- Sara
Thanks for all the input. I've come across another way to solve my problem, using a multifile assembly rather than my first dll approach.
I followed this HowTo-section: http://msdn.microsoft.com/en-us/library/226t7yxe.aspx#Y749
VB-code : DllModule : Class-library project
DllModule.vb
Imports System.Runtime.InteropServices
Namespace DllModuleNS
Public Class Class1
Public Function ClassAdd(ByRef first As Integer, ByRef sec As Integer) As Integer
Dim abc As Integer
abc = first + sec
Return abc
End Function
End Class
End Namespace
This file I compiled using both visual studio (to produce DllModule.dll-file) and cmd-line:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Vbc.exe /t:module DllModule.vb
(to produce DllModule.netmodule-file).
C++-code : TryVbDllLoad : Console application
TryVbDllLoad.cpp
#using <mscorlib.dll>
#using ".\..\ClassLibrary1\DllModule.netmodule"
using namespace DllModule::DllModuleNS;
int _tmain(int argc, _TCHAR* argv[])
{
Class1^ me = gcnew Class1();
int a = 1, b = 2;
int xx = me->ClassAdd(a, b);
return 0;
}
In the TryVBDllLoad-project properties I changed:
Common Properties -> Framework and References : added DllModule-project as reference
Configuration Properties -> C/C++ -> General : /clr flag set
Configuration Properties -> Linker -> Input : Add Module To Assembly set to path to DllModule.netmodule (/ASSEMBLYMODULE:"DllModule.netmodule")
This resulted in that I could use the VB-class Class1 in VC++ code!
PROBLEM SOLVED!
I now took it one step further, and changed the TryVBDllLoad-project to a dll:
Configuration Properties -> General : Configurationtype Dynamic Library (.dll)
Configuration Properties -> Linker -> System : SubSystem Windows (/SUBSYSTEM:WINDOWS)
TryVbDllLoadClass.h
#ifndef TryVbDllLoadClass_H
#define TryVbDllLoadClass_H
class TryVbDllLoadClass
{
public:
TryVbDllLoadClass();
int Add(int a, int b);
};
#endif // TryVbDllLoadClass_H
TryVbDllLoadClass.cpp
#include "TryVbDllLoadClass.h"
#using <mscorlib.dll>
#using ".\..\ClassLibrary1\DllModule.netmodule"
using namespace DllModule::DllModuleNS;
TryVbDllLoadClass::TryVbDllLoadClass() {}
int TryVbDllLoadClass::Add(int a, int b)
{
Class1^ me = gcnew Class1();
int xx = me->ClassAdd(a, b);
return xx;
}
DllExport.h
#ifndef DLLEXPORT_H
#define DLLEXPORT_H
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#ifdef __dll__
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif // __dll__
extern "C" {
IMPEXP int __stdcall AddFunction(int);
}
#endif // DLLEXPORT_H
DllMain.h
#define __dll__
#include "dllExport.h"
#include " TryVbDllLoadClass.h"
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
TryVbDllLoadClass * my;
IMPEXP int __stdcall AddFunction(int first, int second)
{
my = new TryVbDllLoadClass();
int res = my->Add(first, second);
delete my;
return res;
}
This dll I could then add to a non-visual-studio project just like a normal dll:
C++-code : LoadDll : Non-Visual-Studio-project (CodeBlocks in this case)
main.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "dllExport.h"
typedef int( * LPFNDLL_CREATE)(int, int);
HINSTANCE hDLL;
LPFNDLL_CREATE func;
using namespace std;
int main()
{
cout << "Hello world!" << endl;
int key = 35;
hDLL = LoadLibrary("TryVbDllLoadClass.dll");
if(hDLL)
{
cout << "Loaded: " << hDLL << endl;
func = (LPFNDLL_CREATE) (GetProcAddress(hDLL, "_AddFunction#4"));
if(func != NULL)
{
cout << "Connected: " << func << endl;
cout << "Function returns: " << func(key, key) << endl;
}
else cout << " ::: fail: " << GetLastError() << endl;
FreeLibrary(hDLL);
cout << "Freed" << endl;
}
else cout << " ::: fail: " << GetLastError() << endl;
printf("-> Goodbye world!\n");
return 0;
}
This way I can use the VB-classes given to me in my existing C++-project created outside Visuabl Studio. Finally...:)
With VB you do not get a "normal" DLL (at least this was the case in former times).
And you do not get Entry Points for functions.
But as i understood you, you have the VB source code and you can do with it whatever
is necessary. Here is a possible solution:
http://www.codeproject.com/Articles/21/Beginner-s-Tutorial-Calling-Visual-Basic-ActiveX-D
but try out first this less complicated way,
because i think a VB dll is always a COM dll, so you can:
register the dll using the Windows command
regsvr32 F:\proj\VBDllModule.dll
now your C++ code :
#import "F:\proj\VBDllModule.dll"
using namespace DllModule;
void CDialogTestDlg::OnButton1()
{
HRESULT hresult;
CLSID clsid;
_CTest *t; // a pointer to the CTest object
_bstr_t bstrA = L"hello";
_bstr_t bstrB = L" world";
_bstr_t bstrR;
::CoInitialize(NULL);
hresult=CLSIDFromProgID(OLESTR("VBTestLib.CTest"), &clsid);
hresult= CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,
__uuidof(_CTest),(LPVOID*) &t);
if(hresult == S_OK)
{
bstrR = t->vbConcat(bstrA , bstrB);
AfxMessageBox((char*)bstrR);
}
}