|
Hi Richard,
Richard Andrew x64 wrote: How do we determine the base address of a loaded DLL?
The HMODULE that you get from the GetModuleHandle function[^] is the same as the base address. If you are writing MFC applications... this will be the same address returned from AfxGetResourceHandle [^]. The AfxGetInstanceHandle[^] function is actually returning the base address of the main application image.
If you are using a Microsoft compiler then you also have access to an extern variable __ImageBase which can be used to access the these base addresses. Because it is equal to an HMODULE you can also use this variable for loading resources[^].
Now that we have the base address we can read the PE image headers [^]and check for a size:
DWORD GetSizeOfImage(HMODULE hModule)
{
DWORD dwSize = 0;
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((PBYTE)hModule + pDOSHeader->e_lfanew);
if(IMAGE_NT_SIGNATURE == pNTHeader->Signature)
{
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)((PBYTE)&pNTHeader->FileHeader);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((PBYTE)&pNTHeader->OptionalHeader);
if(IMAGE_NT_OPTIONAL_HDR32_MAGIC == pNTHeader->OptionalHeader.Magic)
{
dwSize = pNTHeader->OptionalHeader.SizeOfImage;
}
}
return dwSize;
}
Richard Andrew x64 wrote: Also, is there some way to tell the system to load a DLL at a base address that I specify, regardless of the image's preferred base address?
Maybe... check out the /FIXED (Fixed Base Address)[^] linker option.
I consider fixed base addresses to be an insecure option... I highly recommend that all software engineers support a dynamic base address.
PE images with support for ASLR[^] will have the IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE bit set in the PE image characteristics. These modules are essentially saying 'put me anywhere you want... I don't care' and the kernel pseudo-randomly chooses an address to map the image.
PE images without support for ASLR... the NT kernel will make an attempt to load the image at its preferred address at pNTHeader->OptionalHeader.ImageBase . If the address is already allocated the kernel will make an attempt to map the image at another address and apply its fixups.
Best Wishes,
-David Delaune
|
|
|
|
|
Thanks for a terrific reply. I certainly appreciate the info!
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Hey,
Your very welcome. I just happened to be researching ASLR very recently while developing a device driver for extending the NEMET security application[^].
In case I did not answer your second question very clearly... no you cannot make the NT loader map a module to an arbitrary address other than the preferred address... it will choose the address itself. You *could* however manually map the module yourself using a technique similar to what was described ages ago... by Joachim Bauch.
Best Wishes,
-David Delaune
|
|
|
|
|
Hello guys,
I met a trouble when i try to modify a hardware's property via API.
It's a USB2COM which is able to perform high-baudrate serial communication. Cause i hope it could update data within 1ms, i have to modify the its update property(latency-timer) from 16ms(default) to 1ms.
Of course i could do that with
[My computer -> System property -> Hardware -> Device Manager ... ], just like the steps described in the following setting manual.
Here is a setting manual, USB2COM Setting Manual. There is the detail description about latency-timer setting, @ Page16 3.3.2.1 .
But i want to know if there is may be another more elegant method via API in shell32.dll or user32.dll?
Control_RunDLL in shell32.dll brings me little help, cause it could do nothing more than shell("Control.exe sysdm.cpl ,2"). What i want is a methed can just modify the number from 16 to 1...
USB2COM's drivers couldnt help me, either, cause no documentation or interface is given.
Could someone give me some advice? I'll be very appreciated.
Thanks.
|
|
|
|
|
Unless you are comfortable working with EIA / RS232 / COM hardware , this can get scarry.
What you need is to get to <b>DCB - data communication block</b> and than you can manipulate most, and I stress most, of the COM paramaters. There are articles about COM in here, but they usually do not explain what is happening in hardware when it comes to working with COM.
|
|
|
|
|
Thanks a lot. Vaclav_Sal
My problem has been solved.
I found the setting interface(in ftd2xx.dll) from FTDI knowledge base.
|
|
|
|
|
I am looking for a way to have a dynamic ( run time) array of afx_msg functions.
I have tried this with some success.
CPtrArray pArray;
pArray.Add((void*) OnFunctionkeysCallsate());
pArray.Add((void*) OnWindowNewlogview());
int iTest = pArray.GetSize();
iTest = pArray.GetUpperBound();
void * pElement = pArray.GetAt(0);
void * pElement_1 = pArray.GetAt(1);
Here are my problems
1. The GetSize returns 2 but GetAt(0) and GetAt (1) return same pointer. Why?
2. The Add method adds the function to the pointer array just fine but also runs it. I can live with that but like to know why it does that.
3. I have no clue what GetAt actually returns and how to use it.
4. I realize this approach still does not provide for dynamic add of a function. Working on that – I guess passing function as variable documentation should help.
5. Is it really “legal” to change the afx_msg function from void to void * as I did?
Thanks for your help. It is really appreciated.
Have a great 2012.
Vaclav
|
|
|
|
|
pArray.Add((void*) OnFunctionkeysCallsate());
Calls the OnFunctionkeysCallsate() function and stores the result of that call into pArray . If I understand you correctly, this is not what you want. Instead, you want the address of the function, not the result of invoking the function. Remove the "()".
|
|
|
|
|
Thanks, pretty stupid mistake on my part as far as caling the function.
Now I need to really figure out how to pass the function as void pointer. Or maybe I need to change the CPtrArray?
I'll work on that.
-- modified 2-Jan-12 22:54pm.
|
|
|
|
|
Chuck O'Toole wrote: pArray.Add((void*) OnFunctionkeysCallsate());
partially agree, however i believe you missed & before function name at time of addition to ptrarray collection
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
Sorry, I don't see any '&' in the original post and it does not appear to be edited. Which '&' are you talking about?
|
|
|
|
|
Chuck O'Toole wrote: Sorry, I don't see any '&' in the original post and it does not appear to be edited. Which '&' are you talking about?
Actually I meant to say, you need to store the address of function to the CPtrArray, if you try to compile as you mentioned in your post, you will see compiler error as mentioned by actual poster in same thread!
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
OK gurus, I need some serious help here. I am over my head with this one, really.
How do I pass afx_msg function to the CPtrArray?
I understand that CPtrArray wants void* pointer, but the compiler still complains and I really do not understand the error codes.
Here is the code and the compiler errors. The first afx_msg function still retruns void*, just FYI, if it makes any difference now.
Thanks for your help.
pArray.Add((void*) (OnFunctionkeysCallsate));
pArray.Add((void) (OnWindowNewlogview));
MainFrm.cpp
E:\0 OpenLog\V1\TCC\MainFrm.cpp(683) : error C2440: 'type cast' : cannot convert from 'void *(__thiscall CMainFrame::*)(void)' to 'void *'
There is no context in which this conversion is possible
E:\0 OpenLog\V1\TCC\MainFrm.cpp(684) : error C2664: 'Add' : cannot convert parameter 1 from 'void' to 'void *'
Expressions of type void cannot be converted to other types
Error executing cl.exe.
|
|
|
|
|
if your customer allow you to use stl and function OnFunctionkeysCallsate and OnWindowNewlogview have same signature, you can use this piece of code to achieve same:-
void Function1(int i)
{
cout<<"Hello in Function 1 Number " <<i;
}
void function2(int i)
{
cout<<"Hello in Function 2 Number " <<i;
}
typedef void (*MySingleArgFunction) (int);
vector<MySingleArgFunction> vecFuncPtr;
vector<MySingleArgFunction>::iterator it;
vecFuncPtr.push_back(&Function1);
vecFuncPtr.push_back(&function2);
it=vecFuncPtr.begin();
while(it!=vecFuncPtr.end())
{
(*it)(20);
it++;
}
and if still insist on CPtrArray, so here is the pointer to solve above problem :-
you missed a & in
Vaclav_Sal wrote: pArray.Add((void*) (OnFunctionkeysCallsate)); pArray.Add((void) (OnWindowNewlogview));
which should be written as
pArray.Add((void*) &OnFunctionkeysCallsate);
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
Thanks for your reply.
I have already tried adding &. The compiler does not like it.
pArray.Add((void*)&OnFunctionkeysCallsate);
And here is the error message
E:\0 OpenLog\V1\TCC\MainFrm.cpp(683) : error C2276: '&' : illegal operation on bound member function expression
I'll take a look at the vector method.
I am also looking at MFC CMenu.
Vaclav
|
|
|
|
|
Vaclav_Sal wrote: have already tried adding &. The compiler does not like it. pArray.Add((void*)&OnFunctionkeysCallsate); And here is the error message
ahh i understand, i believe OnFunctionkeysCallsate is the function defined in the class, if yes then you have to put the code like this:-
pArray.Add((void*)&YouClassNameWhereFunctionISDefines::OnFunctionkeysCallsate);
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
Sorry, still no go
Here is the compiler error message:
MainFrm.cpp
E:\0 OpenLog\V1\TCC\MainFrm.cpp(685) : error C2589: '&' : illegal token on right side of '::'
E:\0 OpenLog\V1\TCC\MainFrm.cpp(685) : error C2059: syntax error : '::'
It seems that this should work. BTW it is all in MainFrm.cpp
pArray.Add((void*)CMainFrame::&OnFunctionkeysCallsate);
Unless you are just curious why it does not, you can just drop it. I am still looking at the CMenu , maybe that will work.
I basically need an array of function pointers I can execute in desired sequence.
Thanks for all your help.
Vaclav
|
|
|
|
|
I'm working on a class array, but I thought it would structure my data different.
I'm working with this code below. I was hoping it would create a single object, with 2 internal members of [0] and [1] creating a single object uaListBoxPtrArray with 2 members [0] Tim and [1] John, Tim and John being inside uaListBoxPtrArray.
But it looks like it creates separate objects
uaListBoxPtrArray[0] which is Tim
uaListBoxPtrArray[1] which is John
and I would have to pass uaListBoxPtrArray[0], uaListBoxPtrArray[1] to a function.
I want to be able to pass the single object to a function in the future, and not separate objects. pass uaListBoxPtrArray by itself, with Time and John inside it.
Q: Is my result or implementation correct?, and that this is the correct result format for the method below?. Or do I now need to work on the constructor, to form a single object of records.
DWORD dwCount;
DB_UserAccount dbUA;
dwCount = dbUA._get_UserAccount_Listbox_Count();
UA_Listbox **uaListBoxPtrArray;
uaListBoxPtrArray = new UA_Listbox*[dwCount];
uaListBoxPtrArray[0] = new UA_Listbox;
uaListBoxPtrArray[0]->iUserID = 47;
uaListBoxPtrArray[0]->szFirstName = L"Tim";
uaListBoxPtrArray[0]->szLastName = L"Parker";
uaListBoxPtrArray[0]->szAccountName = L"tparker";
uaListBoxPtrArray[1] = new UA_Listbox;
uaListBoxPtrArray[1]->iUserID = 48;
uaListBoxPtrArray[1]->szFirstName = L"Joe";
uaListBoxPtrArray[1]->szLastName = L"Smoe";
uaListBoxPtrArray[1]->szAccountName = L"jsmoe";
|
|
|
|
|
jkirkerx wrote: I was hoping it would create a single object
But the lines:
uaListBoxPtrArray = new UA_Listbox*[dwCount];
uaListBoxPtrArray[0] = new UA_Listbox;
...
uaListBoxPtrArray[1] = new UA_Listbox;
specifically say: create an array of object pointers and create two new objects which can be referenced by the pointers in the array. If you want a single object to hold both names then you need a different class definition.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Thanks Richard
I just want to make sure that I understood your thoughts correctly first.
Richard MacCutchan wrote: create an array of object pointers
uaListBoxPtrArray = new UA_Listbox*[dwCount];
Richard MacCutchan wrote: create two new objects which can be referenced by the pointers in the array
uaListBoxPtrArray[0] = new UA_Listbox;
uaListBoxPtrArray[1] = new UA_Listbox;
|
|
|
|
|
That's correct, if you break things down to their constituent parts you get:
UA_Listbox UA_Listbox* UA_Listbox*[dwCount] uaListBoxPtrArray
So the statement
uaListBoxPtrArray = new UA_Listbox*[dwCount];
initialises an array variable by creating the array of pointers (via the new operator). Each array element can then be initialised with a pointer to an object of the type previously defined.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Thanks again Richard.
Well my class array worked. I was able to pass the array to the function and get the values back. But after implementing it, changing the design and format several times, I determined that it will never work in the way I wanted it to.
After studying how they work in principle, the source which is a ODBC function creates pointers to buffers in the heap, in which the SQL Handle maintains, and once the handle is freed, the pointers are lost.
So I brought the GUI (hWnd) to the ODBC, populated the listbox, and exited.
No one wonder I was confused, but overall in the end, I learned alot about pointers. Oh Well.
|
|
|
|
|
Why not this way?
UA_Listbox *uaListBoxArray;
uaListBoxArray = new UA_Listbox[dwCount];
uaListBoxArray[0].iUserID = 47;
uaListBoxArray[0].szFirstName = L"Tim";
uaListBoxArray[0].szLastName = L"Parker";
uaListBoxArray[0].szAccountName = L"tparker";
uaListBoxArray[1].iUserID = 48;
uaListBoxArray[1].szFirstName = L"Joe";
uaListBoxArray[1].szLastName = L"Smoe";
uaListBoxArray[1].szAccountName = L"jsmoe";
delete [] uaListBoxArray;
|
|
|
|
|
That's a question to a question, in which I cannot answer at the moment.
|
|
|
|
|
You asked how to define a single object containing two UA_ListBox objects and I gave you a definition: Rather than define an array of two pointers, I defined an array of two UA_ListBox objects. If that is not what you want, then sorry, I don't understand the question. (Besides, even your own definition of an array of two pointers to objects in a way satisfies your request: it is a single object representing two objects. Why is this not sufficient for your purposes?)
|
|
|
|