views:

688

answers:

6

I need to replace all WinAPI calls of the

  • CreateFile,
  • ReadFile,
  • SetFilePointer,
  • CloseHandle

with my own implementation (which use low-level file reading via Bluetooth). The code, where functions will be replaced, is Video File Player and it already works with the regular hdd files. It is also needed, that Video Player still can play files from HDD, if the file in the VideoPlayer input is a regular hdd file.

What is the best practice for such task?

A: 

I don't think this is best practice but it should work if you put it in an include file that's included everywhere the function you want to change is called:

#define CreateFile MyCreateFile

HRESULT MyCreateFile(whatever the params are);

Implementation of MyCreateFile looks something like this:

#undef CreateFile
HRESULT MyCreateFile(NobodyCanRememberParamListsLikeThat params)
{
    if (InputIsNormalFile())
        CreateFile(params);
    else
        // do your thing
}

You basically make every CreateFile call a MyCreateFile call where you can decide if you want need to use your own implementation or the orginal one.

Disclaimer: I think doing this is ugly and I wouldn't do it. I'd rather search and replace all occurences or something.

Maximilian
Thanks! Do you think, that it will be better to write some class, where will be defined the MyCreateFile() method, and then Ctrl-H All CreateFile calls in the code?
Omega
Yes, I would suggest you do that.
Maximilian
Basically just do what ChrisN suggested.
Maximilian
Actually, you may benefit by writing such a class, particularly if your functions need to maintain any additional state/data while reading or writing the file.
ChrisN
+1  A: 

If you're trying to intercept calls to these APIs from another application, consider Detours.

dpp
Thanks, I need to change the code, not binary.
Omega
+1  A: 

If you can edit the code, you should just re-write it to use a custom API that does what you want. Failing that, use Maximilian's technique, but be warned that it is a maintenance horror.

If you cannot edit the code, you can patch the import tables to redirect calls to your own code. A description of this technique can be found in this article - search for the section titled "Spying by altering of the Import Address Table".

This is dangerous, but if you're careful you can make it work. Also check out Microsoft Detours, which does the same sort of thing but doesn't require you to mess around with the actual patching.

Shog9
yes, it is all about changing the code, not hacking import tables :) thanks.
Omega
+5  A: 

I suggest that you follow these steps:

  1. Write a set of wrapper functions, e.g MyCreateFile, MyReadFile, etc, that initially just call the corresponding API and pass the same arguments along, unmodified.
  2. Use your text editor to search for all calls to the original APIs, and replace these with calls to your new wrapper functions.
  3. Test that the application still functions correctly.
  4. Modify the wrapper functions to suit your own purposes.

Note that CreateFile is a macro which expands to either CreateFileW or CreateFileA, depending on whether UNICODE is defined. Consider using LPCTSTR and the TCHAR functions so that your application can be built as either ANSI or Unicode.

Please don't use #define, as suggested in other responses here, as this will just lead to maintenance problems, and as Maximilian correctly points out, it's not a best-practice.

ChrisN
+2  A: 

You could just write your new functions in a custom namespace. e.g.

namespace Bluetooth
{
  void CreateFile(/*params*/);
  void etc...
}

Then in your code, the only thing you would have to change is:

if (::CreateFile(...))
{
}

to

if (Bluetooth::CreateFile(...))
{
}

Easy! :)

Mark Ingram
+1  A: 

If you really want to hijack the API, look at syringe.dll (L-GPL).

titanae