LNK2019 unresolved external symbol NtOpenFile - c++

I am facing linker error with my code. I am trying to compile with Visual Studio command Prompt (2010) in Win-7 X64 bit m/c.
The error which i see are as below.
dust2.obj
dust2.obj : error LNK2019: unresolved external symbol _NtOpenFile#24 referenced
in function _main
dust2.obj : error LNK2019: unresolved external symbol _RtlAnsiStringToUnicodeStr
ing#12 referenced in function _main
dust2.obj : error LNK2019: unresolved external symbol _RtlInitAnsiString#8 refer
enced in function _main
dust2.exe : fatal error LNK1120: 3 unresolved externals
The simplified version of my code is like this:
#include <windows.h>
#include <iostream>
#include <Winternl.h>
using namespace std;
int main()
{
NTSTATUS Status;
OBJECT_ATTRIBUTES Obja;
HANDLE SourceFile;
PUNICODE_STRING PathName=0;
PANSI_STRING p_path=0;
const char* ccp_path = "D:\\txt.txt";
RtlInitAnsiString( p_path,ccp_path );
RtlAnsiStringToUnicodeString( PathName, p_path, true );
IO_STATUS_BLOCK IoStatusBlock;
wprintf(L"%s", PathName->Buffer);
InitializeObjectAttributes(
&Obja,
PathName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenFile(
&SourceFile,
FILE_LIST_DIRECTORY | FILE_READ_EA | FILE_READ_ATTRIBUTES,
&Obja,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
);
if(SourceFile == INVALID_HANDLE_VALUE){
printf("\nError: Could not open file\n");
return 0;
}
cout<<endl<<endl;
system("pause");
return 0;
}
In another post in this forum the solution of these kind of problem was mention to include a #pragma.
I tried this solution by adding #pragma like this
#pragma comment(lib, "ntdll")
but on compilation i see another error that says "LINK : fatal error LNK1104: cannot open file 'ntdll.lib'".
I will much appreciate your help to resolve this problem. Thanks..

Can't let this question go unanswered like this. Because although the remark by Mladen is largely right for this particular native API, the whole topic deserves an in-depth discussion.
Preliminary cautionary note
Up front I should note that in many many cases it is neither desirable nor necessary to use one of the native API functions on Windows. However, there are a few cases where the Win32 API doesn't provide the means to query information or even manipulate data and so on. One such case would be several of the information classes available for NtQueryInformationFile/ZwQueryInformationFile.
One good example is the enumeration of alternate data streams on files and directories, which can be done using the Win32 API, in particular by using the backup APIs, but will require special privileges in that case. Not so if you resort to the native API. The same used to be true for hard links until Windows 2000, which introduced CreateHardLink to the Win32 API. Although in this particular case if you knew your way around you could have used MoveFileEx with MOVEFILE_CREATE_HARDLINK ever since it got introduced (although Microsoft still as of this writing marks it as Reserved for future use ... meh).
The canonical books about the native API are these two:
Windows NT/2000 Native API Reference, Gary Nebbett
Undocumented Windows 2000 Secrets: A Programmer's Cookbook, Sven B. Schreiber (free version from the author's website here)
... there are more, including one that discusses NT 4 and preceded Nebbett's book. But Nebbett's book used to start the hype around the native API, much like Hoglund's book started the hype around Windows rootkits. Not a reference regarding the Native API topic but still good:
Windows Internals, Mark Russinovich et. al.
Check out this website for a huge number of native API functions "documented":
http://undocumented.ntinternals.net/
So remember: the inherent risk when using these functions is that they go away in a future Windows version or their semantics change without prior notice. So be careful when you use them, if you use them.
On to glory ...
How to call native API functions
Actually there are two ways to call these functions. Microsoft was forced to disclose some of the native API functions in one of the antitrust law suits some years ago. These were shoved into winternl.h of the SDK. Microsoft expresses it thus:
The NtOpenFile documentation is provided for the sake of full API
coverage. NtOpenFile is equivalent to the ZwOpenFile function
documented in the DDK. For more information on the ZwOpenFile and
related functions, go to http://msdn.microsoft.com/library. In the
left-hand pane, click Windows Development, then click Driver
Development Kit.
However, there is no accompanying ntdll.lib file in the SDK. Microsoft suggests you link those functions dynamically (second option below).
You have several options:
The most common is to do as you did. But the ntdll.lib import library is only part of the WDKs, not the DDKs.
Use GetProcAddress to find the function pointer and call it. GetModuleHandle is sufficient for the Win32 subsystem since every Win32 program is guaranteed to have loaded ntdll.dll.
Method 1: ntdll.lib
If you have the DDK/WDK - for Driver Development Kit and Windows Driver Kit respectively - you get a full set of ntdll.lib files already. On my system (Windows 7 WDK 7600.16385.1):
C:\WINDDK\7600.16385.1\lib\win7\amd64\ntdll.lib
C:\WINDDK\7600.16385.1\lib\win7\i386\ntdll.lib
C:\WINDDK\7600.16385.1\lib\win7\ia64\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wlh\amd64\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wlh\i386\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wlh\ia64\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wnet\amd64\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wnet\i386\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wnet\ia64\ntdll.lib
C:\WINDDK\7600.16385.1\lib\wxp\i386\ntdll.lib
Create your own makeshift ntdll.lib
Otherwise you have to generate ntdll.lib yourself from the output of dumpbin (or by other means that allow to parse the exports of the DLL) which you can then output into a module definition file from which you can build an export .lib. Sounds convoluted? Not so much, let's see ;)
Using Ero Carrera's pefile Python module, we can do this:
import os, re, sys
from os.path import basename, dirname, join, realpath
try:
import pefile
except ImportError:
try:
sys.path.append(join(realpath(dirname(__file__)), "pefile"))
import pefile
except:
raise
def main(pename):
from pefile import PE
print "Parsing %s" % pename
pe = PE(pename)
if not getattr(pe, "DIRECTORY_ENTRY_EXPORT", None):
return "ERROR: given file has no exports."
modname = basename(pename)
libname = re.sub(r"(?i)^.*?([^\\/]+)\.(?:dll|exe|sys|ocx)$", r"\1.lib", modname)
defname = libname.replace(".lib", ".def")
print "Writing module definition file %s for %s" % (defname, modname)
with open(defname, "w") as f: # want it to throw, no sophisticated error handling here
print >>f, "LIBRARY %s\n" % (modname)
print >>f, "EXPORTS"
numexp = 0
for exp in [x for x in pe.DIRECTORY_ENTRY_EXPORT.symbols if x.name]:
numexp += 1
print >>f, "\t%s" % (exp.name)
print "Wrote %s with %d exports" % (defname, numexp)
print "\n\nUse this to create the export lib:\n\tlib /def:%s /out:%s" % (defname, libname)
if __name__ == '__main__':
if len(sys.argv) != 2:
sys.exit("ERROR:\n\tSyntax: fakelib <dllfile>\n")
sys.exit(main(sys.argv[1]))
A sample output of running this script (when named fakelib.py) would be:
> fakelib.py ntdll.dll
Parsing ntdll.dll
Writing module definition file ntdll.def for ntdll.dll
Wrote ntdll.def with 1984 exports
Use this to create the export lib:
lib /def:ntdll.def /out:ntdll.lib
Then we run the command as given on the last line. It is even better to give the /machine: parameter, of course. This is left as an "exercise" (*cough* *cough*) to the reader. The output with VS 2012 will be:
> lib /def:ntdll.def /out:ntdll.lib
Microsoft (R) Library Manager Version 11.00.51106.1
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : warning LNK4068: /MACHINE not specified; defaulting to X86
Creating library ntdll.lib and object ntdll.exp
Congratulations. You can now use the ntdll.lib created by Microsoft's own lib.exe to statically import from ntdll.dll, even without having the "real" (original) .lib on your system.
Adjust the path and file names to your needs and tastes.
When using MinGW
Damon pointed out in a comment that the toolchain included with MinGW contains a tool gendef that can do the job of above Python script and that the output can be fed to dlltool.
Issues
The above method works perfectly when targeting x64 (64-bit), but for x86 (32-bit) I have encountered linker errors at times.
The issue is that the name decoration for __stdcall differs between x64 and x86. The former doesn't really use the same __stdcall as x86 and therefore just prepends an underscore. However, the latter also appends a the number of arguments times sizeof(void*) (i.e. 4). So for one argument the decorated function name for a function int __stdcall foo(int); becomes _foo#4.
This KB article from Microsoft outlines a way to get around the issue.
Method 2: dynamically imported, using GetProcAddress
Documentation in MSDN states (for NtOpenFile):
Note that the DDK header file Ntdef.h is necessary for many constant
definitions as well as the InitializeObjectAttributes macro. The
associated import library, Ntdll.lib is also available in the DDK. You
can also use the LoadLibrary and GetProcAddress functions to
dynamically link to Ntdll.dll.
Declare a function type, e.g. here we declare the type TFNNtOpenFile suitable in your case:
typedef NTSTATUS (NTAPI *TFNNtOpenFile)(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
);
... and then retrieve the function pointer and call it:
TFNNtOpenFile pfnNtOpenFile = (TFNNtOpenFile)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenFile");
status = pfnNtOpenFile(...); // can't be bothered to type out all parameters ;)
an alternative way of retrieving the function pointer could be this one:
static NTSTATUS (NTAPI *NtOpenFile)(
OUT PHANDLE,
IN ACCESS_MASK,
IN POBJECT_ATTRIBUTES,
OUT PIO_STATUS_BLOCK,
IN ULONG,
IN ULONG
);
(FARPROC)&NtOpenFile = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenFile");
which could be condensed even further by using the preprocessor stringification operator (#). The choice is yours.

These functions cannot be called directly because they belong to internal API and are not exposed through any of the libraries. You need to obtain addresses of these function using GetProcAddress.
For more information look here.

Related

Loading DLL fails on Windows

As a Xcode developer I have to use my written code on windows, too. I think I have successful master all cross platform issues but now I have a real problem understanding the DLL hell on Windows.
I used my code with Xcode and Gcc (Ubuntu) successful. On Windows I get a error message:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
I read much about this uses but I have my problems to understand the issue.
Normally on windows I have something like
#define MYLIB_API __declspec(dllimport)
I cannot find this inside the header of the Bass Library (bass.h). There is only one line
#define BASSDEF(f) WINAPI f
Now, I try to dynamic load the DLL functions in my code. You can see the dynamic loading header as link on bottom. To much to copy here. This dynamic loading is working for .dylib and .so libs well, not for .dll
My target is to load the DLL dynamic and not static with an additional lib.
In my code I use the bass.h and the bassdecode.h. In my code I call as sample:
bool returnVar = _BASS_SetConfig(BASS_CONFIG_DEV_DEFAULT,1);
And here I get the calling convention message.
What I have to do in my header file to successful import DLL functions on Windows?
You can download the files at: header files to download
Ok, for all who run into the same problem, the solution is the Answer from Hans Passant. I cannot mark this answer as solution so I want to give him the reputation.
My original typedef of the function:
typedef BOOL (*BASS_SetConfig_Type)(DWORD option, DWORD value);
Was searched in DLL
_BASS_SetConfig = (BASS_SetConfig_Type)DllFindSym(m_hMod, "BASS_SetConfig")
Where DLLFindSym is defined as:
#define DllFindSym(handle,name) (GetProcAddress(handle,name))
Now changed the typedef to
typedef BOOL (__stdcall *BASS_SetConfig_Type)(DWORD option, DWORD value);
Now everything works like a charm in Windows. Many thanks to the quick hint from Hans Passant.

C++ windows code links in 64bit but not in 32bit

I have code written in C++ on windows.
My code compiles and links when I compile it as x64 but not when I change the build configuration to x86.
The failure is a linking error.
I'm using the function RtlIsNameInExpression from ntdll.
When I compile it in 32bit mode I get a linkage error (LNK2019) of unresolved external.
Any ideas why this might happen?
10x
first of all - how you declare function and which symbol can not found linker ?
declaration must be
extern "C" NTSYSAPI BOOLEAN NTAPI RtlIsNameInExpression(
_In_ PCUNICODE_STRING Expression,
_In_ PCUNICODE_STRING Name,
_In_ BOOLEAN IgnoreCase,
_In_opt_ PWCH UpcaseTable
);
i can guess that you miss NTAPI i.e __stdacall keyword if you copy-paste from here. for x64 exist only one calling convention, but for x86 exist different between __stdcall and __cdecl for example. this can explain why this found in x64 but not found in x86
what error give you linker (not compiler !) ? unresolved external symbol __imp__RtlIsNameInExpression ? (if yes you really forget __stdcall set) or __imp__RtlIsNameInExpression#16 ? in this case you declare function correct, but your ntdll.lib not containing this symbol. (may be you use old ntdll.lib
for xp ? ) simply search __imp__RtlIsNameInExpression#16 string as is in ntdll[p].lib - are it found ? if not you have old (xp) version of ntdll i guess.
The answer is in the online documentation for that function:
This function has no associated header file. The associated import library, Ntdll.lib, is available in the Microsoft Windows Driver Kit (WDK). You can also call this function using the LoadLibrary and GetProcAddress functions to dynamically link to Ntdll.dll.
If you can't add the ntdll.lib file from the WDK to your link command, then you need to use the LoadLibrary-GetProcAddress approach.
Also from the same section of documentation:
The functions and structures in Winternl.h are internal to the operating system and subject to change from one release of Windows to the next, and possibly even between service packs for each release. To maintain the compatibility of your application, you should use the equivalent public functions instead. Further information is available in the header file, Winternl.h, and the documentation for each function.

How to shrink the size of a WTL application?

WTL applications are quite small already. However, using VS 2005 a statically linked application with WTL 9.10 weighs in at 136 kB (139,264 Bytes) for the Win32 configuration.
Looking at the executable I noticed a static import of oleaut32.dll. A cursory look with dumpbin shows one import via ordinal.
OLEAUT32.dll
4181C0 Import Address Table
41C9B8 Import Name Table
0 time date stamp
0 Index of first forwarder reference
Ordinal 277
Inspecting oleaut32.dll one finds that the export is named VarUI4FromStr.
Digging a little with IDA, I found that VarUI4FromStr was used by ATL::CRegParser::AddValue. Following the dependents from there, showed two calls in ATL::CRegParser::RegisterSubkeys.
Cross-referencing the ATL code of my Visual Studio installation with the findings, I found that the culprit was ATL::CAtlComModule. It does a lot of TypeLib registration stuff that is simply not needed for my use case.
However, the linker seems to leave all of that in, because it cannot reasonably decide to throw it out.
How can I get rid of this seemingly superfluous import?
Alas, since WTL::CAppModule derives directly from ATL::CComModule, including the atlbase.h header while having _ATL_NO_COMMODULE defined leads to an error:
Error 1 fatal error C1189: #error : WTL requires that _ATL_NO_COMMODULE is not defined $(ProjectDir)\wtl\Include\atlapp.h 33
The actual culprit that ultimately pulls in ATL::CComModule is, however, ATL::CAtlComModule. So our goal is to get rid of both of them.
We'll try to trick atlbase.h into excluding all the TypeLib registration code by defining _ATL_NO_COMMODULE anyway, but undefining it right after we're done including it. This way atlapp.h and other WTL headers won't "notice".
#define _ATL_NO_COMMODULE
#include <atlbase.h>
#undef _ATL_NO_COMMODULE
#include <atlapp.h>
Obviously that gets us into some trouble:
1>atlapp.h(1515) : error C2039: 'CComModule' : is not a member of 'ATL'
1>atlapp.h(1515) : error C2504: 'CComModule' : base class undefined
1>atlapp.h(1524) : error C2653: 'CComModule' : is not a class or namespace name
1>atlapp.h(1543) : error C2653: 'CComModule' : is not a class or namespace name
1>atlapp.h(1625) : error C3861: 'GetModuleInstance': identifier not found
1>atlapp.h(1784) : error C2653: 'CComModule' : is not a class or namespace name
1>atlapp.h(1806) : error C2065: 'm_nLockCnt' : undeclared identifier
However, it looks like we should be able to fix this handful of errors quickly.
First of all let's check where ATL::CComModule comes from: it's declared and defined in atlbase.h. We can surely declare our own class and squeeze it in between #include <atlbase.h> and #include <atlapp.h> (see above).
Let's start with the basics, based on what can be found in atlbase.h:
namespace ATL
{
class CComModule : public CAtlModuleT<CComModule>
{
public:
CComModule() {}
};
};
Now we get a different set of errors:
1>atlapp.h(1524) : error C2039: 'Init' : is not a member of 'ATL::CComModule'
1> stdafx.h(31) : see declaration of 'ATL::CComModule'
1>atlapp.h(1625) : error C3861: 'GetModuleInstance': identifier not found
Excellent, so we're in fact only missing two more class functions: GetModuleInstance and Init. Let's pull those in as well. For good measure we'll also add GetResourceInstance:
namespace ATL
{
class CComModule : public CAtlModuleT<CComModule>
{
public:
CComModule() {}
HINSTANCE GetModuleInstance() throw() { return _AtlBaseModule.m_hInst; }
HINSTANCE GetResourceInstance() throw() { return _AtlBaseModule.m_hInstResource; }
HRESULT Init(_ATL_OBJMAP_ENTRY*, HINSTANCE, const GUID*) throw() { return S_OK; }
};
};
A short test proves that this is working fine. And the oleaut32.dll import is gone along with three more imports from ole32.dll. Great success!
And as a result we have saved 12 kB on the executable size.
Do you know other cool tricks to shrink WTL application size?
IMPORTANT
Note that depending on the features of ATL::CComModule which your code uses, you may have to fall back to using the original. The only other alternative is to extend the above mock version of ATL::CComModule to fix any compilation errors you may run into.
CAUTIONARY NOTE
I have not tested this extensively yet and I'll report back (by editing this answer) if I run into any trouble. However, from looking at it in both the ATL and WTL code as well as in the IDA database prior to my changes, I think this is a safe change.
Bonus trick
You may also use the 6001.18002 standalone WDK (for Vista SP1), which supports to target Windows 2000 (SP4) and newer. It includes ATL 7.0 and is therefore suited to build ATL+WTL applications.
To do that you just need to add the following two lines to your sources file:
USE_STATIC_ATL=1
ATL_VER=70
Thanks to the WDK, which uses msvcrt.dll, a system DLL, as its default (multithreaded dynamically linked) C runtime, you can then shrink the executable size further by linking dynamically to the C runtime. And in this case, since that particular C runtime is a system DLL (starting with Windows 2000), you can rest assured that it will work.
All of that taken into account you can build standard Windows applications (GUI or console) and DLLs that are really small.
Here is an example sources file which you can use as a template:
# Name of the program
TARGETNAME=progname
# Prefix used for the intermediate/output paths (e.g. objfre_w2k_x86)
TARGETPATH=obj
# A program, not a driver or DLL or static lib
TARGETTYPE=PROGRAM
# windows == GUI, console == Console, native == no subsystem ...
UMTYPE=windows
# Use Unicode ("wide char") instead of ANSI
UNICODE=1
# By default the WDK build treats warnings as errors - this turns it off
BUILD_ALLOW_ALL_WARNINGS=1
# Link dynamically to msvcrt.dll
USE_MSVCRT=1
# Don't link against any of the ATL DLLs
USE_STATIC_ATL=1
# In the 7600.16385.1 WDK you can use 70 as well, which translates to 71
ATL_VER=70
USE_NATIVE_EH=1
# RTTI is required for some ATL/WTL features
USE_RTTI=1
# GUI programs require these entry points
!IF defined(UNICODE) && $(UNICODE)
UMENTRY=wwinmain
C_DEFINES=$(C_DEFINES) /DUNICODE /D_UNICODE
!ELSE
UMENTRY=winmain
C_DEFINES=$(C_DEFINES) /DMBCS /D_MBCS
!ENDIF
# Include folders
INCLUDES=$(DDK_INC_PATH);$(CRT_INC_PATH);$(SDK_INC_PATH);wtl\Include
# Libraries to link to, not just import libraries
TARGETLIBS=\
$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\user32.lib \
$(SDK_LIB_PATH)\Comctl32.lib \
# Give source files (also resources and .mc) in the current or parent directory
SOURCES=...
The 7600.16385.1 standalone WDK also works for this. The WDKs starting from the Windows 8 WDK now require a Visual C++ into which they can be integrated. This also leads to the binaries requiring the respective C runtime version instead of the msvcrt.dll from prior WDK versions.

How to declare and link to RoInitialize,RoUninitialize,RoGetActivationFactory and HSTRING Functions in Mingw Gcc

UPDATED: Added what RoInitialize looks like in roapi.h
I am in the process of writing a pure C++11 WinRT library. I do not use WRL or C++/CX (Obviously if I want pure C++11).
I got my code to compile and run on MSVC, but I want to see if I can get the code to compile and run on Mingw Gcc. Specifically, I am using GCC 4.7.2 obtained from nuwen.net.
What I need at this point is a way to call the Windows API Functions RoInitialize, RoUnitialize, RoGetActivationFactory and the HSTRING Functions WindowsCreateString, WindowsDuplicateString, WindowsDeleteString.
I tried compiling this program in G++ but got the error
extern "C"{
__declspec(dllimport)int __stdcall RoInitialize(int);
}
int main(){
RoInitialize(1);
}
I tried to compile but got:
c:\Users\jrb\Desktop>g++ gccwinrt.cpp
C:\Users\jrb\AppData\Local\Temp\ccy7y1V9.o:gccwinrt.cpp:(.text+0x1e): undefined
reference to `_imp__RoInitialize#4'
collect2.exe: error: ld returned 1 exit status
If anybody can point me in the right direction on how to declare these functions and what libraries I need to link to, I would appreciate it. Even if it requires LoadLibrary/GetProcAddress I would still be ok with that
Update: Here is what RoInitialize looks like in the header roapi.h
ROAPI
_Check_return_
HRESULT
WINAPI
RoInitialize(
_In_ RO_INIT_TYPE initType
);
ROAPI is just a define for __declspec(dllimport)
_Check_return_ is part of SAL (Secure Annotations Language?)
HRESULT maps to int32
WINAPI is a define for __stdcall
RO_INIT_TYPE is an enumeration so int should cover it
The import library for these functions is runtimeobject.lib (which the MSDN documentation fails to mention). It can be found in the Windows SDK for Windows 8.
The library you need to link against is windowsapp.lib (and only this lib, remove all others).
This topic lists the Win32 APIs that are part of the Universal Windows Platform (UWP) and that are implemented by all Windows 10 devices. For convenience, an umbrella library named WindowsApp.lib is provided in the Microsoft Windows Software Development Kit (SDK), which provides the exports for this set of Win32 APIs. Link your app with WindowsApp.lib (and no other libraries) to access these APIs.
APIs present on all Windows 10 devices - Microsoft Docs
See that page for a complete list of functions that implements; it includes RoInitialize, RoUnitialize, RoGetActivationFactory and WindowsCreateString, WindowsDuplicateString, & WindowsDeleteString (among many, many others). If you need other functions, you may need to link extension APIs also.
Similar guidance was originally on
https://msdn.microsoft.com/en-gb/windows/uwp/get-started/universal-application-platform-guide#writing-code but is no longer present:
Windowsapp.lib is an "umbrella" lib that provides the exports for the UWP APIs. Linking to Windowsapp.lib will add to your app dependencies on dlls that are present on all Windows 10 device families.
For delay loading, you will need to load api-ms-win-core-winrt-l1-1-0.dll, which is an API set, a collection of APIs that Windows can load regardless of where the actual DLLs are. This specific set is listed as a Windows 8.1 API set, however if you check the documentation for RoInitialize it says the minimum supported client is Windows 8. Assuming you use LoadLibrary and GetProcAddress, it shouldn't matter.
The actual DLL that the method is implemented in is combase.dll, but they use these API set DLLs as a level of indirection so that they are free to change or update that original DLL in the future.
For future reference, the API sets for Windows 10 (UWP) are listed on a separate page to the API sets for Windows 8 (and 8.1). The stub DLL (for delay loading) is the same. https://msdn.microsoft.com/library/windows/desktop/mt186421
Many other APIs also list their corresponding API set in their own documentation. For example, MSDN gives AllowSetForeground as an example.
If you don't have the import lib that contains RoInitialize, you'll need to use LoadLibrary/GetProcAddress to resolve the types.
Run-time link it like this:
#include <roapi.h>
namespace
{
FARPROC LoadComBaseFunction(const char* function_name)
{
static HMODULE const handle = ::LoadLibraryA("combase.dll");
return handle ? ::GetProcAddress(handle, function_name) : nullptr;
}
decltype(&::RoInitialize) GetRoInitializeFunction()
{
static decltype(&::RoInitialize) const function = reinterpret_cast<decltype(&::RoInitialize)>(LoadComBaseFunction("RoInitialize"));
return function;
}
}
HRESULT RoInitialize(RO_INIT_TYPE init_type)
{
auto ro_initialize_func = GetRoInitializeFunction();
if (!ro_initialize_func)
return E_FAIL;
return ro_initialize_func(init_type);
}
Source

Getting "error LNK2001: unresolved external symbol _gnutls_free" when using GnuTLS 3.1.6 from Visual Studio 2012

I am attempting to build a project in Visual Studio 2012 that uses GnuTLS. I downloaded the latest official Windows build from the website, and created a link library by running lib /def:libgnutls-28.def in the bin directory form a Visual Studio command prompt.
After adding a typedef long ssize_t, the code compiles fine, but linking fails with the following error:
source_file.obj : error LNK2001: unresolved external symbol _gnutls_free
C:\Path\to\executable.exe : fatal error LNK1120: 1 unresolved externals
I am calling gnutls_free to free some memory allocated and returned by the library. If I remove the call to gnutls_free, the project links successfully. Given that gnutls_free is just a global variable (containing a function pointer) exported by the library, I'm not sure why accessing it results in an unresolved reference to a different symbol. I have verified that gnutls_free is not #defineed to anything.
As a test, I tried doing gnutls_free_function test = gnutls_free; which also resulting in the link error. Running grep -w -r _gnutls_free . on the GnuTLS source code returns nothing, so I am at a loss.
Any ideas for getting this working would be greatly appreciated.
EDIT:
Adding __declspec(dllimport) to the declaration of gnutls_free in gnutls.h allows the link to succeed. Is there any way to accomplish this without maintaining a custom version of the header file?
There doesn't seem to be a way to have the linker or import library automatically dereference the IAT's pointer to the data item the same way that is done for functions (via a small trampoline function that is statically linked into the module importing the function). The __declspec(dllimport) attribute tells that compiler that this dereferencing needs to be done so it can insert code to perform the dereferencing of the IAT pointer implicitly. This allows exported data to be accessed and for functions allows the compiler to call the imported function via an indirect call through the IAT pointer rather than by calling the trampoline function.
See a couple of Raymond Chen's articles about dllimport for a good explanation of what goes on for function calls (he didn't discuss importing data, unfortunately):
Calling an imported function, the naive way
How a less naive compiler calls an imported function
The MS linker or import library doesn't have a mechanism to help the compiler get imported data in a 'naive' way - the compiler needs the the __delcspec(dllimport) hint that an extra dereference through the IAT is needed. Anyway, the point of all this is that it seems there's no way to import data except by using the __declspec(dllimport) attribute.
If you want to avoid modifying the gnutls distribution (which I can understand), here's one rather imperfect workaround:
You can create a small object file that contains nothing but a simple wrapper for gnutls_free(); since gnutls_free() has an interface with no real dependencies, you can have the necessary declarations 'hardcoded' instead of including gnutls.h:
typedef void (*gnutls_free_function) (void *);
__declspec(dllimport) extern gnutls_free_function gnutls_free;
void xgnutls_free(void* p)
{
gnutls_free(p);
}
Have your code call xgnutls_free() instead of gnutls_free().
Not a great solution - it requires your code to call a wrapper (so it's particularly not great if you'll be incorporating 3rd party code that might depend on gnutls_free()), but it might be good enough.