Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ LNK2019未解析的外部符号文件_C++_Winapi_Visual C++_Linker Errors - Fatal编程技术网

C++ LNK2019未解析的外部符号文件

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

我的代码遇到链接器错误。我正在尝试使用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个未解析的外部

我的代码的简化版本如下:

   #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()
。。。还有更多,包括一个讨论NT4和Nebbett的书之前。但是Nebbett的书曾经围绕原生API展开宣传,就像Hoglund的书围绕Windows rootkits展开宣传一样。不是关于本机API主题的参考,但仍然很好:

  • 窗户内部构件,Mark Russinovich等人
查看此网站,了解大量“记录”的本机API函数:

因此请记住:使用这些函数的固有风险是它们在未来的Windows版本中消失,或者它们的语义在未事先通知的情况下发生更改。所以当你使用它们时要小心,如果你使用它们的话

走向荣耀

如何调用本机API函数 实际上有两种方法可以调用这些函数。在几年前的一次反垄断诉讼中,微软被迫披露了一些本机API函数。这些被塞进SDK的
winternl.h
。微软这样表示:

提供
NtOpenFile
文档是为了完整的API 覆盖范围
NtOpenFile
相当于
ZwOpenFile
函数 记录在DDK中。有关
ZwOpenFile
和 相关功能,请转至。在 在左侧窗格中,单击Windows开发,然后单击驱动程序 开发工具包

但是,SDK中没有附带的
ntdll.lib
文件。Microsoft建议您动态链接这些函数(下面的第二个选项)

您有几个选择:

  • 最常见的是像你那样做。但是
    ntdll.lib
    导入库只是WDK的一部分,而不是DDK
  • 使用
    GetProcAddress
    查找函数指针并调用它
    GetModuleHandle
    对于Win32子系统来说已经足够了,因为每个Win32程序都保证加载了
    ntdll.dll
  • 方法1:
    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");