I noticed a weird behaviour when trying to detour SHGetKnownFolderPath, and investigaed a bit. So I worte a tiny program, and then loaded it in IDA.
The program:
#include "stdafx.h"
#include "windows.h"
#include "FileAPI.h"
#include "Shlobj.h"
int main()
{
HANDLE hFile = CreateFileA(NULL, 0, 0, NULL, 0, 0, NULL);
SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, NULL, NULL);
return 0;
}
Looking in IDA, I see for CreateFileA:
call ds:__imp__CreateFileA@28 ; CreateFileA(x,x,x,x,x,x,x)
Which takes me to:
.idata:0041B000 ; HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
.idata:0041B000 extrn __imp__CreateFileA@28:dword ; CODE XREF: _main+2Ep
.idata:0041B000 ; DATA XREF: _main+2Er ...
On the other hand, for SHGetKnownFolderPath I see:
call j__SHGetKnownFolderPath@16 ; SHGetKnownFolderPath(x,x,x,x)
Which redirect to:
; __stdcall SHGetKnownFolderPath(x, x, x, x)
j__SHGetKnownFolderPath@16 proc near
jmp _SHGetKnownFolderPath@16 ; SHGetKnownFolderPath(x,x,x,x)
j__SHGetKnownFolderPath@16 endp
Which redirect to:
; __stdcall SHGetKnownFolderPath(x, x, x, x)
_SHGetKnownFolderPath@16 proc near
jmp ds:__imp__SHGetKnownFolderPath@16 ; SHGetKnownFolderPath(x,x,x,x)
_SHGetKnownFolderPath@16 endp
Which redirect to:
.idata:0041B09C ; __declspec(dllimport) __stdcall SHGetKnownFolderPath(x, x, x, x)
.idata:0041B09C extrn __imp__SHGetKnownFolderPath@16:dword
.idata:0041B09C ; DATA XREF: SHGetKnownFolderPath(x,x,x,x)r
So SHGetKnownFolderPath have two more jumps then CreateFileA. I did nothing to the project to make it do it. so why?
Update:
Removing Incremental Linking removed j__SHGetKnownFolderPath@16, but left _SHGetKnownFolderPath@16.
From the VS /INCREMENTAL documentation:
- May contain jump thunks to handle relocation of functions to new addresses
So we have half a solution, and another question: why does this setting effect only this DLL, and not other DLLs? (especially other system DLLs)
Update 2: Solved.
Found out that SHGetKnownFolderPath does not have a __declspec(dllimport) in the definition. Adding it made it be called identical to CreateFileA.
Without it, the compiler created a stub, the linker add a stub of its own for the incremental linking, and only then connected it to the DLL.