Como substituir chamadas de funções WinAPI no projeto MS VC++ por minha própria implementação (o nome e os parâmetros definidos são iguais)?
-
09-06-2019 - |
Pergunta
Preciso substituir todas as chamadas WinAPI do
- CriarArquivo,
- Ler arquivo,
- DefinirFilePointer,
- FecharHandle
com minha própria implementação (que usa leitura de arquivos de baixo nível via Bluetooth).O código, onde as funções serão substituídas, é o Video File Player e já funciona com os arquivos normais do disco rígido.Também é necessário que o Video Player ainda possa reproduzir arquivos do HDD, se o arquivo na entrada do VideoPlayer for um arquivo HDD normal.
Qual é a melhor prática para tal tarefa?
Solução
Sugiro que você siga estes passos:
- Escreva um conjunto de funções wrapper, por exemplo, MyCreateFile, MyReadFile, etc, que inicialmente apenas chamam a API correspondente e passam os mesmos argumentos, sem modificações.
- Use seu editor de texto para pesquisar todas as chamadas para as APIs originais e substitua-as por chamadas para suas novas funções de wrapper.
- Teste se o aplicativo ainda funciona corretamente.
- Modifique as funções do wrapper para atender aos seus próprios propósitos.
Observe que CreateFile é uma macro que se expande para CreateFileW ou CreateFileA, dependendo se UNICODE está definido.Considere usar LPCTSTR e o Funções TCHAR para que seu aplicativo possa ser criado como ANSI ou Unicode.
Por favor, não use #define, como sugerido em outras respostas aqui, pois isso apenas levará a problemas de manutenção e, como Maximilian aponta corretamente, não é uma prática recomendada.
Outras dicas
Você poderia simplesmente escrever suas novas funções em um namespace personalizado.por exemplo.
namespace Bluetooth
{
void CreateFile(/*params*/);
void etc...
}
Então, no seu código, a única coisa que você teria que mudar é:
if (::CreateFile(...))
{
}
para
if (Bluetooth::CreateFile(...))
{
}
Fácil!:)
Se você estiver tentando interceptar chamadas para essas APIs de outro aplicativo, considere Desvios.
Se você puder editar o código, basta reescrevê-lo para usar uma API personalizada que faça o que você deseja.Caso contrário, use a técnica de Maximilian, mas esteja avisado que é um horror de manutenção.
Se não for possível editar o código, você poderá corrigir as tabelas de importação para redirecionar as chamadas para seu próprio código.Uma descrição desta técnica pode ser encontrada em Este artigo - procure a seção intitulada "Espionagem por alteração da Tabela de Endereços de Importação".
Isso é perigoso, mas se você tiver cuidado, poderá fazer funcionar.Confira também Desvios da Microsoft, que faz o mesmo tipo de coisa, mas não exige que você mexa na correção real.
Se você realmente deseja sequestrar a API, dê uma olhada seringa.dll (L-GPL).
Não acho que seja uma prática recomendada, mas deve funcionar se você colocá-lo em um arquivo de inclusão incluído em todos os lugares em que a função que você deseja alterar é chamada:
#define CreateFile MyCreateFile
HRESULT MyCreateFile(whatever the params are);
A implementação de MyCreateFile é mais ou menos assim:
#undef CreateFile
HRESULT MyCreateFile(NobodyCanRememberParamListsLikeThat params)
{
if (InputIsNormalFile())
CreateFile(params);
else
// do your thing
}
Você basicamente faz com que cada chamada CreateFile seja uma chamada MyCreateFile, onde você pode decidir se deseja usar sua própria implementação ou a original.
Isenção de responsabilidade:Acho que fazer isso é feio e eu não faria isso.Prefiro pesquisar e substituir todas as ocorrências ou algo assim.