I am trying to accomplish much the same thing as is being done here http://www.vbforums.com/showthread.php?t=449171
However using C#, instead of VB. What is snagging me the most is the C++ portion of the code. I have little to no experience with C++, and I have tried time and time again to make this ‘.dll’ being spoken of, but it won’t compile right without changing things (I have to change the GetModuleHandle section to have Text(“”) in it, and such)
Then when I mount it up in C#, I get an error that ‘No suitable entry point could be found for GetAddr(), even though I follow the same P/Invoke signature as explained (in C# syntax instead of VB).
Can anyone help me? I cannot get this C++ .dll made correctly. I don’t even know the appropriate way to make the right kind of project to do this. The C++ code in question is listed below, and I am using Visual Studio 2010.
#include "stdafx.h"
#pragma data_seg(".shared")
char sharedStr[255] = "a";
char sharedRichTextBoxString[255] = "a";
int addr = 0;
HMODULE module = 0;
int flag = 0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if(flag == 0)
{
module = GetModuleHandle("C:\\Program Files\\Microsoft Visual Studio\\MyProjects\\EditStreamCallBack\\Debug\\EditStreamCallBack.dll");
addr = (int)GetProcAddress(module, (LPCSTR)"EditStreamCallBack");
flag = 1;
}
return TRUE;
}
__declspec(dllexport) void _stdcall SetText(char * str)
{
int sz = strlen(str);
memcpy(sharedStr, str, sz);
}
__declspec(dllexport) HMODULE _stdcall GetModuleH()
{
return module;
}
__declspec(dllexport) int _stdcall GetAddr()
{
return addr;
}
__declspec(dllexport) char * _stdcall GetRichTextBoxString()
{
return sharedRichTextBoxString;
}
__declspec(dllexport) int CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE buf, DWORD numByte, DWORD* cb)
{
if(dwCookie==1) //if 1, then we want it to work for EM_STREAMIN
{
memcpy(buf, sharedStr, strlen(sharedStr));
*cb = strlen(sharedStr);
}
else if(dwCookie==2) //if 2, then we want it to work for EM_STREAMOUT
{
memcpy(sharedRichTextBoxString, buf, numByte);
}
return 0;
}
I find the code example which you use not the best one, it is really dirty written. Nevertheless because you wrote that your main current problem is the C/C++ code I suggest you following:
GetModuleHandletoGetModuleHandleAin the C/C++ code. You can aslo to change settings of the project to avoid usage of “Use Unicode Character Set” setting.EditStreamCallBack.def(in contex menu of the “Source Files” use “Add”/”New Item” and choose “Module-Definition File (.def)”). As the contain of the def file you should use following textLIBRARY "EditStreamCallBack"The usage of
EditStreamCallBack.defwill solve your current problem with the error: ‘No suitable entry point could be found for GetAddr()’.Because your C/C++ code don’t use Unicode, you should don’t forget to use
CharSet.Ansiin the Interop declaration of theSetTextandGetRichTextBoxStringfunctions of theEditStreamCallBack.dll. It is also important to useSendMessageAand notSendMessageWfor sending of the messageEM_STREAMOUT.One more remark. The usage of full filename for the dll in
GetModuleHandleis allowed, but mostly not really needed. So If you don’t load two different version of the same dll with the same file name but with different pathes I’ll recommend you to remove full path of the DLL from the code of the C++ program.UPDATED: I posted under http://www.ok-soft-gmbh.com/ForStackOverflow/EditStreamCallBack1.zip tree projects: EditStreamCallBack (with the EditStreamCallBack.sln inside) which create the DLL, CSharpTest with the simple C# test to load DLL from C# and CSharpTestFull. The CSharpTestFull project contain mostly the code which you posted.
To be able to test the CSharpTestFull project contains DLL Injection you should start Visual Studio 2010 “as Administrator”.
What I modified in your code is:
GetWindowThreadProcessIdandOpenProcessdeclaration with the last parameter asint dwProcessId.app.manifestwhich contains<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />. This is needed to start .NET application under administrative rights which is require to be able to open another process with full access (PROCESS_ALL_ACCESS). At least the rightsPROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITEare really required.For the tests I used WordPad.exe. Because currently in your code you use only DLL Injection and call of
GetAddrfunction and other application with a windows would be OK. The program produced the output like followingWith respect of Process Explorer (starter also as administrator) I could verify that the DLL are really loaded in WordPad.exe process under the address 0x511A0000. So the current code which you posted me work.
How I wrote before, the whole code can be seen only as the code for the proof of concept.