C++ LNK2019未解析的外部符号文件
我的代码遇到链接器错误。我正在尝试使用Win-7 X64位m/c中的Visual Studio命令提示符(2010)进行编译。 我看到的错误如下 灰尘2.obj dust2.obj:错误LNK2019:未解析的外部符号\u NtOpenFile@24被引用 在主功能中 dust2.obj:错误LNK2019:未解析的外部符号\u RTLANSISTRINGTOUNICODEST ing@12在函数_main中引用 dust2.obj:错误LNK2019:未解析的外部符号\u rtlinitanSisting@8请参阅 函数中的enced _main dust2.exe:致命错误LNK1120:3个未解析的外部 我的代码的简化版本如下:C++ LNK2019未解析的外部符号文件,c++,winapi,visual-c++,linker-errors,C++,Winapi,Visual C++,Linker Errors,我的代码遇到链接器错误。我正在尝试使用Win-7 X64位m/c中的Visual Studio命令提示符(2010)进行编译。 我看到的错误如下 灰尘2.obj dust2.obj:错误LNK2019:未解析的外部符号\u NtOpenFile@24被引用 在主功能中 dust2.obj:错误LNK2019:未解析的外部符号\u RTLANSISTRINGTOUNICODEST ing@12在函数_main中引用 dust2.obj:错误LNK2019:未解析的外部符号\u rtlinitanS
#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;
}
但在编译时,我看到另一个错误是“LINK:fatal error LNK1104:无法打开文件‘ntdll.lib’”
我将非常感谢你帮助解决这个问题。谢谢..这些函数不能直接调用,因为它们属于内部API,不通过任何库公开。您需要使用GetProcAddress获取这些函数的地址
有关更多信息,请查看。不能让这个问题像这样无人回答。因为尽管Mladen的评论在很大程度上适用于这个特定的本机API,但整个主题值得深入讨论 初步注意事项 首先,我应该注意到,在许多情况下,情况的确如此。然而,在某些情况下,Win32 API不提供查询信息甚至操作数据等的方法。其中一种情况是可供选择的若干信息类 一个很好的例子是枚举文件和目录上的备用数据流,这可以使用Win32 API完成,特别是使用备份API,但在这种情况下需要特殊权限。如果您使用本机API,则情况并非如此。在引入Win32 API的Windows 2000之前,硬链接也是如此。尽管在这种特殊情况下,如果您知道自己的方式,您可以使用
MOVEFILE\u CREATE\u HARDLINK
(尽管在撰写本文时,Microsoft仍将其标记为保留供将来使用…meh)
关于本机API的规范书籍有以下两本:
- Windows NT/2000本机API参考,Gary Nebbett
- 未记录的Windows 2000秘密:程序员的食谱,Sven B.Schreiber()
- 窗户内部构件,Mark Russinovich等人
winternl.h
。微软这样表示:
提供NtOpenFile
文档是为了完整的API
覆盖范围NtOpenFile
相当于ZwOpenFile
函数
记录在DDK中。有关ZwOpenFile
和
相关功能,请转至。在
在左侧窗格中,单击Windows开发,然后单击驱动程序
开发工具包
但是,SDK中没有附带的ntdll.lib
文件。Microsoft建议您动态链接这些函数(下面的第二个选项)
您有几个选择:
ntdll.lib
导入库只是WDK的一部分,而不是DDKGetProcAddress
查找函数指针并调用它GetModuleHandle
对于Win32子系统来说已经足够了,因为每个Win32程序都保证加载了ntdll.dll
ntdll.lib
如果您有DDK/WDK-分别用于驱动程序开发工具包和-您已经获得了一整套ntdll.lib
文件。在我的系统(Windows 7 WDK 7600.16385.1)上:
创建自己的临时ntdll.lib
否则,您必须从dumpbin
的输出(或通过允许解析DLL导出的其他方式)自己生成ntdll.lib
,然后将其输出到模块定义文件中,从中可以构建导出.lib
。听起来很复杂?没那么多,让我想想;)
使用Ero Carrera,我们可以做到:
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]))
然后,我们运行最后一行给出的命令。当然,最好给出/machine:
参数。这是留给读者的“练习”(*咳嗽**咳嗽*)。VS 2012的输出将为:
> 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
祝贺你。现在,您可以使用Microsoft自己的lib.exe
创建的ntdll.lib
从ntdll.dll
静态导入,即使系统上没有“真实”(原始).lib
根据您的需要和喜好调整路径和文件名
使用MinGW时
在一篇评论中指出,MinGW包含的工具链包含一个工具gendef
,可以完成上述Python脚本的工作,并且可以将输出提供给dlltool
问题
上述方法在针对x64(64位)时非常有效,但对于x86(32位),我有时会遇到链接器错误
问题一
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]))
> 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
> 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
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
);
TFNNtOpenFile pfnNtOpenFile = (TFNNtOpenFile)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenFile");
status = pfnNtOpenFile(...); // can't be bothered to type out all parameters ;)
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");