|
igor1960 wrote:
Check your Project Settings: specifically Debugging/Debugger Type -- set to Native or Mixed or whatever...
This helped
Thanks a lot
Rainer
|
|
|
|
|
I hate variable length argument functions in C++, but for what I'm doing, I have no choice using it .
I'm trying to insert a DLL Hook for a DLL that contains a function that has a variable length argument list (it has ... as a parameter). I want to do some processing with what they pass in, and then forward the call to the original function (the one in the DLL that was hooked). My question is how can I forward this function call? How do I dynamically create the parameters for this function call?
To help with my explantaion, imagine I'm hooking wsprintf. This function takes two parameters and then a variable number of arguments after this. I know how to read the arguments they've passed in (obviously the first 2 are easy, and then you have to pull out the variable length remaining parameters). Once I have this information, how do I then create a new call with the first two parameters as normal, and then tag on the variable length arguments after them? If I want to hook wsprintf in this example, do some processing on that function, and then pass it thru to the original, I've got to be able to do this.
Anyone have any ideas? Please let me know if you don't understand my problem too.
Thanks,
Kentamanos
|
|
|
|
|
Maybe I'm missing something but if you know what the parameters are going to be, you should just be able to call the original function, and pass in the parameters that you've already extracted. Something like:
int _wsprintf( LPTSTR lpOut, LPCTSTR lpFmt, ... )
{
return (wsprintf(lpOut, lpFmt, var1, var2, etc));
}
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
The problem is the var1, var2, etc. part .
If they pass in just 2 parameters, I need to call wsprintf one way. If they pass 3, another way, and so on.
I could potentially create a huge if statement with a call to the original function for each number of parameters. In that case, I assume you'd treat all the arguments as void *, but you'd have to put a limit on how many actual parameters you wanted to support. You could cover up to 10 parameters for instance, but the instant they pass 11, your function won't call the original correctly.
I'd like to find the correct way to do this by dynamically creating the argument list with the arguments they passed in. I've seen built in functions that look like they would work on gcc, but I don't know what the VC++ equivalent would really be.
|
|
|
|
|
Using wsprintf() as an example is kind of awkward since the format specifier governs the count/type of the arguments passed to the function. In any case, you're going to need to parse the format specifier and extract each argument appropriately. Once you have all of them, a call to wsprintf() can be made.
I used to have the code for printf() but that was ages ago, so the closest I can come to now is the code for MFC's CString::Format() function. It's a rather long example of how to handle format specifiers. For each '%' found, you'll extract the appropriate type argument from the variable list, and store it in a variable. When the variable list has been exhausted, you can then call wsprintf() . So, if someone called wsprintf() like:
wsprintf(szBuffer, "%c %d\n", 'c', 97);
you'd end up with a char variable and an int variable. At the end of your hook function, you'd have something like:
return wsprintf(lpOut, lpFmt, somechar, someint);
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
wsprintf vs. printf vs. CString::Format doesn't make too big of a difference in regard to this problem. Just to be clear, I could rewrite any of the above functions. The challenge lies in forwarding these function calls to their originals in a completely generic manner (no matter how many parameters are passed in).
It's not a problem if I know the number of arguments they're going to pass every time. It's pretty trivial then to pull these arguments out (using the format specifiers in this case to pull them out based upon type) and make a call to wsprintf. It's also not a problem if I don't know how many arguments they're passing, but I don't need to forward the call and therefore I don't have to dynamically create a variable length argument list.
The problem is they're passing me an unspecified number of arguments, and I have to forward that call regardless of the number. I'm trying to wrap a function (it's not actually wsprintf, it's just an example) with variable arguments, and I have no idea what the typical calling usage is.
Think of the problem this way: Your mission is to write a replacement function for wsprintf, printf, or CString::Format (I don't really care which one we talk about). This function should write some debug info and forward the call to the original function no matter how the user calls the original function (in other words, no matter how many parameters they actually end up passing).
|
|
|
|
|
Ok, how about:
int _wsprintf( LPTSTR lpOut, LPCTSTR lpFmt, ... )
{
va_list list;
int nReturn;
va_start(list, lpFmt);
nReturn = wsprintf(lpOut, lpFmt, list);
va_end(list);
return nReturn;
}
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
I created a Win32 Console App to test this approach, and it created garbage for me. Did you get this method to work? Here is the code I used:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int MyWsprintf( LPTSTR lpOut, LPCTSTR lpFmt, ...)
{
va_list list;
int nReturn;
va_start(list, lpFmt);
nReturn = wsprintf(lpOut, lpFmt, list);
va_end(list);
return nReturn;
}
int _tmain(int argc, _TCHAR* argv[])
{
char buf[1024];
MyWsprintf(buf, "%s %s %s", "test1", "test2", "test3");
printf(buf);
}
</code>
If I change the call of MyWsprintf to the real wsprintf, it works great, indicating the problem is in the rewrite.
|
|
|
|
|
That was a bad suggestion on my part (at least I thought it would work based on this code snippet). I guess the address that va_start() sets list to is not the same as the stack address that wsprintf() is popping arguments from.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
A simple approach might be to read the original parameters into a vector and then pass the vector to the function that will be responsible for reconstructing the parameter list. Doing something like this wouldn't affect the number of parameters present in the "wsprintf" function.
If the original "wsprintf" function contains two parameters, then two parameters are what the vector will contain, but if it turns out that the "wsprintf" contains 3, or 4, or 5, (etc.) parameters, then that's the number of parameters the vector will contain. Afterwards, you simply pass the vector itself as a parameter to the function that will be responsible for reconstructing the new parameter list you will need.
William
Fortes in fide et opere!
|
|
|
|
|
This wouldn't work in this situation since I eventually need to pass the arguments to the original wsprintf function (in this example). Creating the vector would be easy. Taking that vector and reading out each argument would be easy. Calling wsprintf appropriately with these arguments would NOT be easy (perhaps impossible?). That's the problem in general. Create a variable length argument list on the fly.
Since I'm doing a DLL Hook on a function, I get called exactly like the original function. I then want to do a bit of processing and then call the original function. There's no reason for me to put in an intermediate function that uses vectors to pass the variable length arguments since I still have to put a variable length argument list together (the whole problem to begin with).
|
|
|
|
|
While the vector approach (I previously mentioned) would work, I agree, it could be a pain to go that route.
Perhaps a simpler approach might be to just pass the address of "wsprintf" itself as a parameter, and then activate its address (which would be activating wsprintf itself). IOW, handle wsprintf as a pointer to a function.
The address of "wsprintf" is the name itself. Include the name as an extra parameter in the DLL Hook function that gets called, and at the appropriate time simply use it as you would at any other time. For example:
void DLLHookFunc(etc., wsprintf);
wsprintf(parameter1, ...);
William
Fortes in fide et opere!
|
|
|
|
|
Based upon a post on microsoft.public.vc.language I just made and got a response on, I think the best bet would be to make my function not affect the stack at all (declspec naked), possibly do some inline assembly to get the parameters passed in without affecting the stack (no pops), and then doing an assembly JMP to the original function.
That would insure the parameters are on the stack just like they were passed in, and it would allow me not to worry about recreating the variable length argument list. It's going to be a pain to pull off with my assembly skills though .
|
|
|
|
|
Good luck to you on whichever way you choose.
I still think passing 'wsprintf' as a pointer parameter in the DLL Hook function and then later use it as you normally would, is the simplest way.
William
Fortes in fide et opere!
|
|
|
|
|
I'm not quite sure what you mean by that. For simplicity sake, don't worry about the DLL Hook portion of this problem. Attempt to write a function that generically wraps printf for instance that you can call exactly like printf.
|
|
|
|
|
I keep returning to the days when I only programed in 'C'. The following should help, it is out of my old dos windowing library and is still valid even in 'C++' (MS).
int w_printf(
int r,
int c,
int color,
unsigned flags,
const char *format,
)
{
int n=-1;
char *buf=NULL;
size_t size=0;
va_list ap;
va_start( ap,format );
while( n == -1 ) {
size += 128;
if( buf ) free(buf);
buf = (char *)malloc(size);
if( !buf ) n = 0;
else n = _vsnprintf(buf,size,format,ap);
}
va_end(ap);
if( buf ) {
n = w_pfmt( r,c,color,flags,buf );
free(buf);
}
return n;
}
INTP
|
|
|
|
|
This perhaps will require some creativity (then again, maybe not).
I am looking for a way to store multiple different class names and their addresses in an array or a vector (it doesn't matter). Right now, because the classes are of different types, the array (or vector) cannot be of one type, and the closest thing which comes to doing what I'm trying to accomplish, is by creating an array of type "void" and then re-cast the objects back to their original type.
While that may work, it seems a little on the awkward side, and was wondering whether anybody might have a better idea of coming up with a different way.
Thanks for any insight.
William
Fortes in fide et opere!
|
|
|
|
|
Remember that the address of an object (an instance of a class) is just a 32-bit value. Those can be stored and cast accordingly.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
First of all, let me take a shot at answering your little quiz (at the end of your post) about those birds sitting on a fence. How many are left? The answer is FIVE!! because three only decided to fly off. They actually didn't do it.
With regards to my question, your answer is pretty much the same as storing the addresses as type "void" and then re-cast them back to their original type. That is exactly what I had noted (but held back from using that approach because of something better I believe can be achieved).
Specifically, I'm thinking along the line of templates and some ingenuity.
Thanks anyway for your reply.
William
Fortes in fide et opere!
|
|
|
|
|
Templates, boost and STL can provide a type safe solution, but it still isn't perfect.
std::vector< boost::any >
may be what you're looking for. Boost::any uses three classes.
1/ Wrapper class, which stores a pointer to a 2
2/ Abstract implementation class
3/ Concrete template class which extends 2
You still need to use any_cast to retrieve your data, but it effectively only a static_cast, much better than using void*'s
It's worth looking into the theory behind boost::any because you may be able to avoid the use of the any_cast / static_cast if you roll your own with careful modifications to all of the classes.
I've spent a fair bit of time looking at exactly this type of problem and come up with no really satisfying solution. My context was with regards to data pipelining arbitrary data types between 'transforms'. I was trying to provide a generic system easy to use by the less experienced. The real problem when I dug down further was that relationships between our classes (cohesion / coupling) were causing delays in development because of long compile times. My advice? Consider your requirements very carefully - Why are you trying to write this code? What other tools or alternatives do you have - since then we've started looking at weakly typed scripting for rapid development.
If you can keep you head when all about you
Are losing theirs and blaming it on you;
If you can dream - and not make dreams your master;
If you can think - and not make thoughts you aim;
Yours is the Earth and everything that's in it.
Rudyard Kipling
|
|
|
|
|
Even if the individual classes where dirived from the same virtual base class you would still probably needed to eventualy re-cast any object object with aditional functionality
to the original type.
According to what you have written I would write a function to handle each of the possible individule class types stored in the array and cast the pointer base on the class id, or in your case class name, and pass it to the function designed to handle it.
If all the classes are related in some fundiment way then you should should create a base class common to all of them. For example: If your array is just used to draw a GUI object then you could use multiple inheritance (or not) with one of the base classes only containing a Draw() function that must be difine in all inherited casses, then you will not have to re-cast any of the pointers to retrieved from the array.
But if none of the classes has any thing in common then why would they be in the same array. That would not make since and you would have no choice but to re-cast them.
INTP
|
|
|
|
|
Thanks for your reply.
This is what I've come up with so far, and it pretty much gives an idea of the direction in which I'm heading.
template<typename T1>
struct MyStruct
{
typedef pair<string, T1<big>&</big>> CLASSINFO;
string className;
static CLASSINFO make_pair <string clsName, const T1<big>&</big> clsRef>
};
typedef int (*PF)(MyStruct<big>&</big> mySt); The compiler complained about, "use of class template requires template argument list". What is it that I'm missing?
typedef int (*PF)(MyStruct<T1><big>&</big> mySt); The proper "#include" statements are present.
Thanks.
William
Fortes in fide et opere!
|
|
|
|
|
How do i get folder path with CFiledialog? I know if I call the GetPathName()
It will return the Full path to specific folder. but in order to close the CFileDialog i have to click on either Save or Open.
Thanks
Shin
|
|
|
|
|
sdfdsfa wrote:
but in order to close the CFileDialog i have to click on either Save or Open.
Which is the whole reason for using CFileDialog in the first place. It sounds like you want to use SHBrowseForFolder() instead.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
Thanks David,
I downloaded the sample program for SHBrowserForFolder() from codeproject.
That was it.
Thank you very much.
Shin
|
|
|
|
|