Calling a dll function C++ rad studio xe3 - c++

I try to call a function from a dll, but it doesn't seem to work fine. Here is the code:
HMODULE dllhandle;
#include "Unit1.h"
#include <windows.h>
#include <iostream.h>
#include <conio.h>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
dllhandle = LoadLibrary((wchar_t*)"PBusDrv.dll");
if(dllhandle)
{
typedef int (*PBUSCONNECTEX)(String aux1, String aux2, String ip);
PBUSCONNECTEX PBusConnectEx;
PBusConnectEx = (PBUSCONNECTEX)GetProcAddress(dllhandle, "PBusConnectEx");
PBusConnectEx(" "," ","192.168.30.252");
}
}
dllhandle keeps returning with a null value.

The problem is probably here:
(wchar_t*)"PBusDrv.dll"
You are casting an ANSI string (1 byte per char) as a wide-string (2 bytes per char). This is never going to work.
You have 3 options:
1- Use the ANSI version of the LoadLibrary function
dllhandle = LoadLibraryA("PBusDrv.dll");
2- Use the appropriate string type according to the project configuration:
dllhandle = LoadLibrary(_T("PBusDrv.dll"));
3- Use the wide-string version of LoadLibrary, while passing a wide-string as input
dllhandle = LoadLibraryW(L"PBusDrv.dll");
Note: Don't mix non-specific function macros with one particular type of string. For example, don't do this:
dllhandle = LoadLibrary(L"PBusDrv.dll");

Related

Why does LoadLibrary fail whilst LoadLibraryA succeeds in loading a DLL? [duplicate]

This question already has answers here:
Cast to LPCWSTR?
(4 answers)
Closed 3 years ago.
I'm trying to load a DLL into C++ but was getting error code 126, which I think means the DLL couldn't be found. After some poking around I changed LoadLibrary to LoadLibraryA and suddendly it worked. However, I am at a complete loss as to why. I realise that I haven't provided the dll for this code to be runable but would be greatful if somebody could provide an explaination as to why this is happening? And prehaps an example of how to get LoadLibary working.
Broken version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
Error loading dll: 126/nHit any key to continue
to console
Working version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibraryA("libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
version is: 1.3.4
The problem with your LoadLibrary((LPCWSTR)"libsbnw.dll") call is that your build environment converts that to a LoadLibraryW call, but the way you are trying to pass a wide-character string is wrong.
As you have it, you are simply casting a const char* pointer to a const wchar_t* pointer, which won't work (for example, it will interpret the initial "li" characters as a single 16-bit character).
What you need to do is specify the string literal as a wide character constant, using the L prefix:
HINSTANCE hLib = LoadLibrary(L"libsbnw.dll");
Or, alternatively, using the TEXT() macro (which will boil down to the same, when using the UNICODE build environment):
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));
Feel free to ask for further explanation and/or clarification.
Ordinarily the compiler will try to point out when you're making a mistake. But in this case you've told it not to by adding an explicit cast to the string.
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
//^^^^^^^^^
I'm assuming you've built your app with Unicode enabled, which defines a macro converting LoadLibrary to LoadLibraryW. The parameter must be a wide-character string.
HINSTANCE hLib = LoadLibraryW(L"libsbnw.dll");
There's another macro you can use when you're not sure if the app will be compiled with Unicode or not, TEXT() or the shorter form _T(). Not recommended for modern code since needing to turn Unicode on or off hasn't been a problem in many years, just use Unicode always.
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));

Converting string to LPWSTR [duplicate]

This question already has answers here:
How to convert std::string to LPCWSTR in C++ (Unicode)
(6 answers)
Closed 8 years ago.
I'm having a hard time converting a string into LPWSTR so I can use the PathStripToRoot() function.
Well for one the MSDN documation says I need LPTSTR variable (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773757(v=vs.85).aspx), but Visual Studio 2013 says I need LPWSTR.
Here is a code snippet of my function:
fileStat fileCreate(const string& targetFile)
{
fileStat filez;
fstream file(targetFile.c_str());
if (!file)
{
cout << "File does not exist" << endl;
}
std::ifstream in(targetFile, ios::binary | ios::ate);
int a = in.tellg();
cout << "File size(bytes): " << in.tellg() << endl << endl;
file.close();
wstring stemp = strChange(targetFile);
LPCWSTR result = stemp.c_str();
/* Tried the below code but that did not work
LPWSTR ws = new wchar_t[targetFile.size() + 1];
copy(targetFile.begin(), targetFile.end(), ws);
ws[targetFile.size()] = 0;
*/
cout<<"\n\n"<<PathStripToRoot(ws)<<"\n\n";
...
filez.fileSize = a;
return filez;
}
A lot of people have said to use MultiByteToWideChar() function but I looked at the MSDN documation and have no idea how it works. Is there an easier way than using MultiByteToWideChar() ?
You may want to use Unicode UTF-16 strings in modern Windows applications when dealing with Win32 APIs: the std::wstring class (based on wchar_t) is OK for that with Visual C++.
Then, you can wrap the Win32 C API PathStripToRoot() in some C++ code, using convenient string classes instead of raw C-like string buffers.
Consider the following commented code as an example:
// Set Unicode mode
#define UNICODE
#define _UNICODE
// Windows SDK Headers
#include <Windows.h> // Win32 Platform SDK
#include <Shlwapi.h> // For PathStripToRoot()
#include <Strsafe.h> // For StringCchCopy()
// Standard C++ Headers
#include <exception> // For std::exception
#include <iostream> // For console output
#include <stdexcept> // For std::invalid_argument, std::runtime_error
#include <string> // For std::wstring
// For using PathStripToRoot()
#pragma comment(lib, "Shlwapi.lib")
// C++ wrapper around PathStripToRoot() Win32 API
std::wstring RootFromPath(const std::wstring& path)
{
// Buffer for PathStripToRoot()
wchar_t pathBuffer[MAX_PATH];
// Copy the input string into the buffer.
// Beware of buffer overruns!
HRESULT hr = ::StringCchCopy(pathBuffer, // dest
_countof(pathBuffer), // dest size
path.c_str()); // source
if (hr == STRSAFE_E_INSUFFICIENT_BUFFER)
{
// Copy failed due to insufficient buffer space.
// May accept this case or throw an exception
// based on the context...
// In this case, I just throw here.
throw std::invalid_argument("RootFromPath() - Path string too long.");
}
if (hr != S_OK)
{
throw std::runtime_error("RootFromPath() - StringCchCopy failed.");
}
// Call the Win32 C API using the raw C buffer
if (! ::PathStripToRoot(pathBuffer))
{
// No valid drive letter was found.
// Return an empty string
return std::wstring();
}
// Return a std::wstring with the buffer content
return std::wstring(pathBuffer);
}
// Test
int main()
{
try
{
const std::wstring path = L"C:\\Path1\\Path2";
const std::wstring root = RootFromPath(path);
std::wcout << "The content of the path before is:\t" << path << std::endl;
std::wcout << "RootFromPath() returned: \t" << root << std::endl;
}
catch(const std::exception& ex)
{
std::cerr << "\n*** ERROR: " << ex.what() << std::endl;
}
}
Compiled from command line:
C:\Temp\CppTests>cl /EHsc /W4 /nologo TestPathStripToRoot.cpp
Output:
C:\Temp\CppTests>TestPathStripToRoot.exe
The content of the path before is: C:\Path1\Path2
RootFromPath() returned: C:\
On that particular point of your question:
Well for one the MSDN documation says I need LPTSTR variable, but
Visual Studios says I need LPWSTR.
LPTSTR is a typedef equivalent to TCHAR*.
LPWSTR is a typedef equivalent to WCHAR*, i.e. wchar_t*.
TCHAR is a placeholder for a character type, that can be expanded to char or wchar_t, depending if you are in ANSI/MBCS or Unicode build mode.
Since VS2005, Visual Studio has been using Unicode builds as default.
So, unless you are maintaining an old legacy app that must use ANSI/MBCS, just use Unicode in modern Win32 applications. In this case, you can directly use wchar_t-based strings with Win32 APIs, without bothering with the old obsolete TCHAR-model.
Note that you can still have std::strings (which are char-based) in your code, e.g. to represent Unicode UTF-8 text. And you can convert between UTF-8 (char/std::string) and UTF-16 (wchar_t/std::wstring) at the Win32 API boundaries.
For that purpose, you can use some convenient RAII wrappers to raw Win32 MultiByteToWideChar() and WideCharToMultiByte() APIs.
The right way to think about building a Windows application is to pretend that 8-bit strings do not exist. Otherwise, the encoding of your string will vary based on the user's language settings, and your app will not be able "global ready" because there will always be some characters not representable by the user's current settings. 8-bit strings in Win32 are legacy from the 1990s and a good Win32 app uses PWSTR everywhere. Notice for instance that on Windows CE or WinRT the "A functions" don't even exist, that should give you some hint about how Microsoft feels about the issue.
Now, in practical terms, you may be interacting with non-Windows specific code that uses 8-bit strings. IMO the best approach to use for that is to say by convention that all such strings are UTF-8, and use MultiByteToWideChar and WideCharToMultiByte to convert to and from PWSTR. Be sure to use CP_UTF8. But for Windows specific code, please do define the UNICODE and _UNICODE macros, forget that TCHAR, TSTR, *A functions and other such accidents of history exist and use PWSTR and WCHAR everywhere. Your code will be saner for it.
You can use ATL conversion macros:
cout<<"\n\n"<<PathStripToRoot(CA2T(targetFile.c_str()))<<"\n\n";
If targetFile is ASCII string, use PathStripToRootA. Here you do not need any conversion, targetFile.c_str() will work.
If targetFile is UTF8 string, use MultiByteToWideChar to convert it to WideChar. Then use PathStripToRoot.
Otherwise make targetFile wstring, pass it to API without any conversion.
Please go through
Unicode Programming Summary
There are several ways to solve this.
The right approach is to enclose the string definitions with _T(). PathStripToRoot is defined as
#ifdef _UNICODE
#define PathStripToRoot PathStripToRootA
#else
#define PathStripToRoot PathStripToRootW
#endif
_T, and Windows APIs follows what you define the character set support you defined for your project under project settings. If you're taking file name as single byte string (string holds ANSI string) use PathStripToRootA. You can avoid converting file name in between to UNICODE string.

How to access a function inside a dll file in C++

I am currently trying to communicate with a device using CAN. To do so I am using PCAN Basic using C++.
Unfortunately, I know nothing about accessing a function inside a dll file (which is what is provided). I found this link:
Calling a dll function from C++
and am trying to use LoadLibrary via code I found here:
http://www.goffconcepts.com/techarticles/development/cpp/calldll.html
My Code:
// dll_get_func.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h> /* For sqrt() */
#include <windows.h>
#define DELCLDIR __declspec("Pcan_usb.dll")
#define PCAN_USBBUS1 0x51
#define CAN_BAUD_1M 0x0014 // 1 MBit/s
#define MSGTYPE_STANDARD 0x00
typedef struct {
DWORD ID; // 11/29 bit identifier
BYTE MSGTYPE; // Bits from MSGTYPE_*
BYTE LEN; // Data Length Code of the Msg (0..8)
BYTE DATA[8]; // Data 0 .. 7
} TPCANMsg;
int hardCodeInit(void)
{
/* get handle to dll */
HINSTANCE hGetProcIDDLL = LoadLibrary(_T("Pcan_usb.dll"));
/* get pointer to the function in the dll*/
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"CAN_Init");
/*
Define the Function in the DLL for reuse. This is just prototyping the dll's function.
A mock of it. Use "stdcall" for maximum compatibility.
*/
typedef int (__stdcall * pICFUNC)(WORD wBTR0BTR1, int CANMsgType);
pICFUNC CAN_Init;
CAN_Init = pICFUNC(lpfnGetProcessID);
//DWORD __stdcall CAN_Init(WORD wBTR0BTR1, int CANMsgType);
/* The actual call to the function contained in the dll */
int intMyReturnVal = CAN_Init(PCAN_USBBUS1,CAN_BAUD_1M);
/* Release the Dll */
FreeLibrary(hGetProcIDDLL);
/* The return val from the dll */
return intMyReturnVal;
}
int hardCodeWrite(void)
{
HINSTANCE hGetProcIDDLL = LoadLibrary(_T("Pcan_usb.dll"));
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"CAN_Write");
typedef int (__stdcall * pICFUNC)(WORD wBTR0BTR1, TPCANMsg CANMsgType);
pICFUNC CAN_Write;
CAN_Write = pICFUNC(lpfnGetProcessID);
TPCANMsg msgOut;
msgOut.MSGTYPE = MSGTYPE_STANDARD;
msgOut.LEN = 1;
msgOut.DATA[0] = 0x03; // 0x03 = Get ID
int toReturn;
toReturn = CAN_Write(PCAN_USBBUS1,msgOut);
FreeLibrary(hGetProcIDDLL);
return toReturn;
}
int _tmain(int argc, _TCHAR* argv[])
{
int derp=hardCodeInit();
int herp=hardCodeWrite();
std::cout<<derp;
std::cout<<herp;
_getch();
return 0;
}
However, Visual Studio says that there is a:
Unhandled exception at 0x10001D95 (Pcan_usb.dll) in dll_get_func.exe: 0xC0000005:
Access violation reading location 0x00000051.
I have Pcan_usb.dll and Pcan_usb.lib in the same folder and I am using visual studio 2012.
There are several points here. Signature of the LoadLibrary:
HMODULE WINAPI LoadLibrary(_In_ LPCTSTR lpFileName);
Remove unneeded casts. This will simplify reading and understanding your code.
FARPROC lpfnGetProcessID - the name of the variable is confusing. This might be a source of confusion or misunderstanding.
Regarding the AV - the signature of the CAN_Init function as you are trying to use it is wrong. From your post it is hard to tell for sure what is should be. Look into manual (if possible), header file, etc.
Main point - you should not release the library. There are rare cases when this is needed. Most likely your case does not need this. It is very difficult to believe that you need to reload the library (and this what happens when you call FreeLibrary/LoadLibrary!) between initing it and writing.
Access violation reading location 0x00000051.
This tells me the function is treating PCAN_USBBUS1 as a pointer. Perhaps:
#define PCAN_USBBUS1 0x51
should be changed to
WORD pcan_usbbus1 = 0x51;
And the call to CAN_Init should be changed to:
int intMyReturnVal = CAN_Init(&pcan_usbbus1, CAN_BAUD_1M);
The function signature should probably be something like:
typedef int (__stdcall * pICFUNC)(WORD* wBTR0BTR1, int CANMsgType);
^ pointer here
I imagine CAN_BAUD_1M might also need to be changed in the same way but maybe not.

GetCurrentDirectory buffer doesn't return the right value

I have an issue with GetCurrentDirectory(), and i don't really understand why. The thing i don't understand is that it works for XP but not for Seven (or at least on my computer). There is my code:
char dir_name[1024]; // as a global variable
int get_files() {
// ...
DWORD dwRet;
dwRet = GetCurrentDirectory(MAX_PATH, dir_name);
printf("%s\n",dir_name);
printf("%d\n",dwRet);
//...
}
This code will return:
printf("%s\n",dir_name); -> return "c"
printf("%d\n",dwRet); -> 42 (which is the right length of the string that should be returned)
I don't understand why dir_name only takes the value "c".
I think, the result is Unicode in Windows Seven! and after each ascii character of this function there is zero. And you are printing it by printf. You should use wide-char functions in your program. Like wprintf.
Try below code: (Tested in Visual Studio 2008 + Windows 7)
#include <stdio.h>
#include <windows.h>
#include <wchar.h>
WCHAR dir_name[1024]; // as a global variable
int get_files()
{
// ...
DWORD dwRet;
dwRet = GetCurrentDirectory(MAX_PATH, dir_name);
wprintf(L"%s\n", dir_name);
printf("%d\n", dwRet);
//...
return 0;
}
Im not sure, but could it be GetCurrentDirectory() returns 2-byte chars under win7?
In such case you'll be getting a 0 in each second bytes of the char array returned.
So you should use a wide-char aware version of the printf() function such as wprintf().
Also I wonder whether the compiler wouldn't have warned you about something being wrong regarding types.
what compiler are you using? Under Visual C++ 2005, GetCurrentDirectory is a macro that resolves to GetCurrentDirectoryW if UNICODE macro is defined and to GetCurrentDirectoryA otherwise. Do you have UNICODE defined by any chance?

debugging loop c++ undefined variable, what type? Hoglund

I have been reading one of the Hoglund titles and I though, reading great, but can I make it work? Why do they provide non-working examples in books?
#include "stdafx.h"
#include <cstdio>
#include <windows.h>
#include <winbase.h>
#include <tlhelp32.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess;
DEBUG_EVENT dbg_evt;
int aPID;
if(argc != 2)
{
printf("wrong number of params\nusage %s<pid>\n", argv[0]);
return 0;
}
//load the ptr to fDebugSetProcessKillOnExit
fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT)
GetProcAddress(GetModuleHandle("kernel32.dll"),
"DebugSetProcessKillOnExit");
if(!fDebugSetProcessKillOnExit)
{
printf("[!] failed to get fDebugSetProcessKillOnExit function!\n");
}
aPID = atoi(argv[1]);
}
I am getting two error messages:
fDebugSetProcessKillOnExit is an undeclared identifier
What type should it be?
"Error 4 error C2664: 'GetModuleHandleW' : cannot convert parameter 1 from 'const char [13]' to 'LPCWSTR'
What type should the fDebug... be? Why doesn't the aPid = atoi... line work?
Should the project be compiled in C instead of C++, as this is exactly as it is in the book?
Thanks, R.
Taking this from MSDN:
BOOL WINAPI DebugSetProcessKillOnExit(__in BOOL KillOnExit);
you can declare the function pointer as:
BOOL (*fDebugSetProcessKillOnExit)(BOOL) = /* ... */;
or ease your eyes by using typedef:
typedef BOOL (*DebugKillPtr)(BOOL);
DebugKillPtr fDebugSetProcessKillOnExit = /* ... */;
Function pointers can be somewhat confusing, InformITs guide on them should help with that.
Additionally, you are using a Unicode build. You can either use GetModuleHandle(L"Kernel32.dll") or _T() etc. or set your project to use the multi-byte-character-set (project properties -> configuration -> general -> character set).
The unicode-character-set is also the reason why the atoi() statement can't work:
argv is an array of _TCHAR*s, and _TCHAR is wchar_t for unicode-builds. atoi() however expects a const char* argument and you are handing it a wchar_t*.
So you can either again use a multi-byte-character set, convert the string or use Microsofts _wtoi()/_ttoi().
To ease switching between character sets and stick with the style of the book, prefer the _T* and _t* versions.
The declaration for fDebugSetProcessKillOnExit is missing; probably it should be something like
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit;
where DEBUGSETPROCESSKILLONEXIT should be a typedef to the prototype of that function.
You are compiling in Unicode and the book "thinks" that you're compiling in ANSI; you should change the strings passed to the APIs to generic strings with the _T() macro.
So, to sum everything up, you should simply change one line and add the typedef:
typedef BOOL (*DEBUGSETPROCESSKILLONEXIT)(BOOL);
//load the ptr to fDebugSetProcessKillOnExit
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), _T("DebugSetProcessKillOnExit"));