I try to create a managed C++ assembly in VS 2010 to interface with WinAPI and use it in my other C# assemblies. I've read all posts, even searched in code in GitHub, with no success.
Maybe its about the __clrcall in the error message, should not it be __stdcall? Any ideas?
The exact error message is:
error C2440: '=' : cannot convert from 'LRESULT (__clrcall xxx::Win32Demo::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
The source code:
#pragma once
using namespace System;
using namespace System::Drawing;
#include "stdafx.h"
#include "windows.h"
namespace xxx
{
ref class Win32Demo
{
private: HWND__ * handle;
private: static Char * windowClass;
public:
Win32Demo(void)
{
}
static Win32Demo()
{
tagWNDCLASSEXW w;
windowClass = (wchar_t*) L"Hello";
w.cbSize = sizeof(tagWNDCLASSEXW);
w.style = 0x803;
w.lpfnWndProc = WindowProc; // Error
w.cbClsExtra = 0;
w.cbWndExtra = 0;
w.hInstance = 0;
w.hIcon = 0;
w.hCursor = 0;
w.hbrBackground = CreateSolidBrush(0);
w.lpszMenuName = NULL;
w.lpszClassName = windowClass;
w.hIconSm = 0;
}
public :
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return 0;
}
};
}
This goes wrong because your WndProc() function is being compiled to IL, not machine code. Which happened because you compile it with /clr in effect. It is not just a compile time error, it also cannot work at runtime. Windows doesn't know how to call a managed method, not without the kind of help you get from Marshal::GetFunctionPointerForDelegate().
It is better to just not go there. Either move this code in a separate .cpp file that you compile without the /clr option. Or use #pragma managed(push, off) before this code so that it gets compiled to machine code instead of IL.
And consider the managed class wrappers that give you the same kind of functionality. Like the classes in the System.Windows.Forms namespace. Or if you want to keep this code then derive your own class from the NativeWindow class to attach the window handle, allowing you to override WndProc() with managed code.
Apparently the __stdcall calling convention is not supported for methods of managed classes. So you'll need to put WindowProc inside an unmanaged class:
class WindowProcCallback
{
public:
static LRESULT __stdcall WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
}
};
ref class Win32Demo
{
...
};
One suggestion: turn on warnings so that you get warnings about stuff like this. With warnings you would have gotten the following warning:
warning C4441: calling convention of '__stdcall ' ignored; '__clrcall ' used instead
Related
I am making an application for xbox 360 that will import functions which were exported from a system dll and call them when needed. I thought I did everything right as far as exporting then importing the functions, but it crashes on a single line of code.
I started by defining the functions inside of the system dll as follows:
void (__cdecl *SV_GameSendServerCommand)(int Client, int Type, char *Command) = (void(__cdecl * )(int, int, char * ))0x82254940;
bool (__cdecl *Dvar_GetBool)(char *Dvar) = (bool(__cdecl * )(char * ))0x8229EF58;
I created a .def file to export the functions while assigning their ordinals:
LIBRARY testdll
EXPORTS
SV_GameSendServerCommand #1
Dvar_GetBool #2
I built the system dll and placed the resulting testdll.lib in the folder where my application's source code was. I then placed the following in stdafx.h of that application:
#pragma comment(lib, "testdll.lib")
I prototyped the functions to be imported and used a function called resolveFunct to get the addresses of the imported functions.
void (__cdecl *SV_GameSendServerCommand)(int Client, int Type, char *Command);
bool (__cdecl *Dvar_GetBool)(char *Dvar);
UINT32 resolveFunct(char* modname, UINT32 ord)
{
UINT32 ret=0, ptr2=0;
HANDLE ptr32 = 0;
ret = XexGetModuleHandle(modname, &ptr32);
if(ret == 0)
{
ret = XexGetProcedureAddress(ptr32, ord, &ptr2);
if(ptr2 != 0)
return ptr2;
}
return 0; // function not found
}
When I tried printing the address of the function, it was successful and read 0x91F8BF54. I did this twice, and it printed both times. The proceeding line of code caused my application to crash.
DWORD WINAPI Start(LPVOID)
{
for(;;)
{
if(!LoadedUp)
{
printf("0x%p\n", resolveFunct("testdll.xex",2));
if(Dvar_GetBool == NULL)
{
printf("0x%p\n", resolveFunct("testdll.xex",2));
Dvar_GetBool = (bool(__cdecl*)(char*))resolveFunct("testdll.xex",2);
I don't understand why this line of code causes my program to crash, though. Any answers/suggestions are appreciated. Thanks!
I'd like to locally hook my WindowProc function. First I was thinking of SetWindowsHookEx, but I wouldn't like to have an external DLL only for this hook. I'd like to make it internally and locally (I don't want a global hook).
That's why I came across with SetWindowsLong. I'm trying to change the WindowProc with the GWL_WNDPROC option, however I always get error: Access Denied and I've got no idea why. Here's my very simple example which is sadly not working:
#include <windows.h>
#include <stdio.h>
WNDPROC pOrigProc;
LRESULT CALLBACK HookWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
printf("Message arrived!\n");
return CallWindowProc(pOrigProc, hwnd, uMsg, wParam, lParam);
}
int main()
{
HWND handle = FindWindow("ConsoleWindowClass", 0);
if(!handle)
{
printf("HWND get error!\n");
}
else
{
DWORD dwProcId;
GetWindowThreadProcessId(handle, &dwProcId);
if( dwProcId != GetCurrentProcessId())
{
printf("Corrupted Handle!\n");
}
else
{
printf("Window handle belongs to my process!\n");
}
}
pOrigProc = (WNDPROC)SetWindowLong(handle, GWL_WNDPROC, (LONG)HookWndProc);
if(!pOrigProc)
{
printf("SWL Error: %d\n", GetLastError());
}
else
{
printf("Successfully hooked the Window Callback!\n");
}
MSG message; // Let's start imitating the prescence of a Win32GUI
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
Of course FindWindow is not going to be the best solution in my main project, but I think it's good enough in this small example. As you can see I'm making sure that the found HWND is my own, so it shouldn't be the problem.
In my case it's returning "Window handle belongs to my process!" and SWL Error: 5
Error 5 is (according to msdn) ACCESS DENIED.
I hope someone can see that possible small stupid mistake which I can't find. Thank you!
MSDN says "You cannot change this attribute if the window does not belong to the same process as the calling thread". From your example is visible that your app is console, not GUI. And probably the ConsoleWindowClass is not defined by your app but globally by Windows. Try similar but with GUI project.
OK so here is my source code this is from a tutorial i found online in creating your first DX window. so i copied it by typing it out to try and remember better. Anyways the problem i am having is that I cannot get the program to build in VS, I have tried changing the Linker subsystem to windows, didnt work.
ERROR Recieved
1>MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function ___tmainCRTStartup
1>e:\documents\visual studio 2013\Projects\Project1\Debug\Project1.exe : fatal error LNK1120: 1 unresolved externals
Heres external link to code https://gist.github.com/bANNji/24ebedaf5a72f2003d29
//include the basic windows header files and the Direct3dD Header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
// Include the DIrect3D library file
#pragma comment (lib, "d3d9.lib")
// global declarations
LPDIRECT3D9 d3d; // The pointer to our Direct3D Interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
// functiuon prototypes
void initD3D(HWND hWnd); // Sets up and initializes Direct3D
void render_frame(void); // Renders a single frame
void cleanD3D(void); // Closes Direct3D and releases memory
// The window proc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// this function initializes and prepares direct3d for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION); // Create the Direct3D Interface
D3DPRESENT_PARAMETERS d3dpp; // create a stuct to hold verious device information
ZeroMemory(&d3dpp, sizeof(d3dpp)); //Clear out the stuct for usee
d3dpp.Windowed = TRUE; // Program windowed not full screen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Discard old frames
d3dpp.hDeviceWindow = hWnd; // Set the window to be used by Direct3D
// Create a deviced calss using this information and information from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
}
// THE FUN STUFF
// this is the function used to render a single frame
void render_frame(void)
{
// clear the window to a deep blue
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
d3ddev->BeginScene(); // this begins the 3D Scene
// do 3D Rendering on the back buffer here...
d3ddev->EndScene(); // ends the 3D Scene
d3ddev->Present(NULL, NULL, NULL, NULL); // This displays the created frame
}
// THis is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
d3ddev->Release(); // close and release the 3D Device
d3d->Release(); //Close and release Direct3D
}
The error means exactly what it says: You don't have a WinMain. I would strongly suggest you first learn how to wield the Win32 API to create and manipulate windows by themselves before you try to use them with Direct3D. It is heavily documented on MSDN and pretty easy to grasp. Here's a quick jumble of sample code (incomplete, obviously) to help give you a reference point to get started:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HRESULT hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
WNDCLASSEX wndClass;
ZeroMemory(&wndClass,sizeof(wndClass));
wndClass.cbSize = sizeof(wndClass);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hbrBackground = NULL;
wndClass.hCursor = LoadCursor(hInstance,LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon = LoadIcon(hInstance,LoadIcon(NULL,IDI_APPLICATION);
wndClass.hIconSm = LoadIcon(hInstance,LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpszMenuName = NULL;
wndClass.lpfnWndProc = winProc;
wndClass.lpszClassName = "derp";
wndClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wndClass);
RECT win = {0,0,width,height};
AdjustWindowRectEx(&win,flags,FALSE,WS_EX_APPWINDOW);
int winWidth = win.right - win.left;
int winHeight = win.bottom - win.top;
hWnd = CreateWindowEx( WS_EX_APPWINDOW,
"derp",
"derpderp",
flags | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
GetSystemMetrics(SM_CXSCREEN)/2 - width/2,
GetSystemMetrics(SM_CYSCREEN)/2 - height/2,
winWidth,
winHeight,
HWND_DESKTOP,
NULL,
hInstance,
NULL
);
SetWindowPos( hWnd,
HWND_NOTOPMOST,
(GetSystemMetrics(SM_CXSCREEN)/2) - (winWidth/2),
(GetSystemMetrics(SM_CYSCREEN)/2) - (winHeight/2),
winWidth,
winHeight,
SWP_SHOWWINDOW
);
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
/* Do your other stuff here */
return 0;
}
And the winproc definition:
LRESULT CALLBACK App::WinProc( HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam )
{
switch(uMsg)
{
// NOTE: Obviously you'd need only those that matter to you, and you'd need to fill them in
case WM_KEYUP:
case WM_KEYDOWN:
case WM_CHAR:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
case WM_SYSKEYDOWN:
case WM_MOUSEWHEEL:
case WM_ACTIVATE:
case WM_SYSKEYUP:
case WM_SYSCOMMAND:
case WM_CREATE:
case WM_CLOSE:
case WM_DESTROY:
App::GetInstance()->Shutdown();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return 0;
}
21st July: Updated, see bottom
In VC++ 2005 I have 2 projects. Firstly, a MFC DLL project (not an extension DLL) which has a simple dialog:
TestDlg.h
#pragma once
#include "afxwin.h"
#include "resource.h"
// CTestDlg dialog
namespace Dialogs
{
class __declspec(dllexport) CTestDlg : public CDialog
{
DECLARE_DYNAMIC(CTestDlg )
public:
CTestDlg (CWnd* pParent = NULL); // standard constructor
virtual ~CTestDlg ();
// Dialog Data
enum { IDD = IDD_TEST_DLG };
}
}
Then I have a Win32 console app, with MFC libraries, that does:
TestApp.cpp
#include "stdafx.h"
#include "TestApp.h"
#include <TestDlg.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
Dialogs::CTestDlg dlg;
dlg.DoModal();
}
return nRetCode;
}
It builds and runs up, but no dialog appears. Stepping into DoModal()...
dlgcore.cpp
INT_PTR CDialog::DoModal()
{
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
m_lpDialogTemplate != NULL);
// load resource as necessary
LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
HGLOBAL hDialogTemplate = m_hDialogTemplate;
HINSTANCE hInst = AfxGetResourceHandle();
if (m_lpszTemplateName != NULL)
{
hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
hDialogTemplate = LoadResource(hInst, hResource);
}
if (hDialogTemplate != NULL)
lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
// return -1 in case of failure to load the dialog template resource
if (lpDialogTemplate == NULL)
return -1;
... more stuff
For whatever reason it seems it can't load the resource, returning -1 at the end of the copied section. I've looked at a few articles on CodeGuru, etc, and not seen anything obvious. Is my class not being exported/imported right? Or is it a resource problem? Or is the problem that I'm trying to display it from a console (MFC) app?
21st July Update
I created an overridden DoModal as so:
INT_PTR CTestDlg::DoModal()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
return CDialog::DoModal();
}
This seems to work although should I be overriding a different method to get the functionality more generic?
As you've noted, the problem is that MFC is not finding the resource, since the module context is set to your main EXE rather than the DLL containing the dialog resource.
Manually calling AFX_MANAGE_STATE to ensure the DLL context is established is one way to work this, but it's not transparent. The ideal way is to compile your DLL as an extension DLL, so that MFC can take care of loading the resource from a list of extension DLLs and managing memory between the DLLs.
You may be able to short-cut creating the extension DLL and simply create your own CDynLinkLibrary instance, which adds your DLL to the main resource list. I have not tried this, preferring instead to take the extension dll _AFXDLL route, so this may or may not work.
The MSDN article on Extension DLLs may help you determine if they are suitable in your case, and what advantages/drawbacks they bring.
Explictly load you *.lib
Hinstance = Loadlibray("*.lib");
AfxSetResourceHandle(Hinstance);
// this way you can load the resource in you dll not the current app's resource.
then destination you code:
CTestDlg dlg;
dlg.DoModal();
I'm not sure if this construction can actually work. If possible, export just a function which opens the dialog inside the DLL.
But perhaps the use of the AFX_MANAGE_STATE-macro can help you.
AFX_MANAGE_STATE did not work for me. In my case, the exe was calling a dialog from another dll which was calling another dialog from 3rd dll. AFX_MANAGE_STATE was returning context of 2nd dll instead of 3rd one. To fix this, I am overriding DoModel and doing the context switching there.
INT_PTR YourDialog::DoModal()
{
HINSTANCE _hInstance = AfxGetResourceHandle();
__try
{
HMODULE dllModule = ::GetModuleHandle("<Your_DlgSourceDll>.dll");
AfxSetResourceHandle(dllModule);
return CDialog::DoModal();
}
__finally
{
AfxSetResourceHandle(_hInstance);
}
}
I am using vc++(2010). I am trying to create a class for server side socket. Here is the header file
#include<winsock.h>
#include<string>
#include<iostream>
using namespace std;
class AcceptSocket
{
// static SOCKET s;
protected:
SOCKET acceptSocket;
public:
AcceptSocket(){};
void setSocket(SOCKET socket);
static void EstablishConnection(int portNo,string&);
static void closeConnection();
static void StartAccepting();
virtual void threadDeal();
static DWORD WINAPI MyThreadFunction(LPVOID lpParam);
};
SOCKET AcceptSocket::s;
and the corresponding source file
#include<NetWorking.h>
#include<string>
void AcceptSocket::setSocket(SOCKET s)
{
acceptSocket=s;
}
void AcceptSocket::EstablishConnection(int portno,string &failure)
{
WSAData w;
int error = WSAStartup(0x0202,&w);
if(error)
failure=failure+"\nWSAStartupFailure";
if(w.wVersion != 0x0202)
{
WSACleanup();
failure=failure+"\nVersion is different";
}
SOCKADDR_IN addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(portno);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
AcceptSocket::s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(AcceptSocket::s == INVALID_SOCKET)
failure=failure+"\nsocket creating error";
if(bind(AcceptSocket::s,(LPSOCKADDR) &addr,sizeof(addr)) == SOCKET_ERROR)
failure=failure+"\nbinding error";
listen(AcceptSocket::s,SOMAXCONN);
}
void AcceptSocket::closeConnection()
{
if(AcceptSocket::s)
closesocket(AcceptSocket::s);
WSACleanup();
}
void AcceptSocket::StartAccepting()
{
sockaddr_in addrNew;
int size=sizeof(addrNew);
while(1)
{
SOCKET temp=accept(AcceptSocket::s,(sockaddr *)&addrNew,&size);
AcceptSocket * tempAcceptSocket=new AcceptSocket();
tempAcceptSocket->setSocket(temp);
DWORD threadId;
HANDLE thread=CreateThread(NULL,0,MyThreadFunction,(LPVOID)tempAcceptSocket,0,&threadId);
}
}
DWORD WINAPI AcceptSocket::MyThreadFunction(LPVOID lpParam)
{
AcceptSocket * acceptsocket=(AcceptSocket *) lpParam;
acceptsocket->threadDeal();
return 1;
}
void AcceptSocket::threadDeal()
{
"You didn't define threadDeal in the derived class";
}
Now the main.cpp is
#include<Networking.h>
int main()
{
}
When I am compiling the error I got is
Error 1 error LNK2005: "private: static unsigned int AcceptSocket::s" (?s#AcceptSocket##0IA) already defined in NetWorking.obj C:\Documents and Settings\prabhakaran\Desktop\check\check\main.obj check
Error 2 error LNK1169: one or more multiply defined symbols found C:\Documents and Settings\prabhakaran\Desktop\check\Debug\check.exe 1 1 check
What might cause this and how do I solve it?
Put this in your .cpp file instead of in your .h file:
SOCKET AcceptSocket::s;
It is being included in many .cpp files if you have it in your .h file. And hence when you link it doesn't know which one to use.
Maybe a #pragma once at the very beginning of your header file will solve the problem.
The error message tells you that the linker finds multiple definitions of your class, obviously because you are including the header more than once.
That is fine in general, but then you should always add some so called inclusion guards in your header file to prevent this error.
EDIT:
Just saw that Brian R. Bondys answer is the correct one.
I'd like to elaborate on what Frank said. It's a common assumption that include guards might solve these kind of errors. Since the explanation got a bit lengthy, I've made a blog-post about it to explain the details:
http://daniel-albuschat.blogspot.com/2010/08/what-include-guards-in-c-are-and-what.html
Hope this is useful.