c# - 将字符串从 c# 传递到 c dll 时的错误行为

标签 c# c winapi dllimport

我对我的问题进行了很多研究,发现了许多与[如何从c#传递字符串]相关的问题。至c dll]:

但是他们都帮不了我。我喜欢以任何方式提出问题:

<小时/>

简要说明:
我的c功能在 c# 中正常工作就在我交换GetProcessIntegrityLevel时参数(在 c dll 和 c# import-dll 中)来自:

  1. BOOL GetProcessIntegrityLevel(DWORD dwPID, LPSTR szIntegrityLevel);

对于这个:

  • BOOL GetProcessIntegrityLevel(LPSTR szIntegrityLevel, DWORD dwPID);
  • 在第一种状态下,我的程序正常工作并更改了 LPSTR szIntegrityLevel但在第二,它不起作用并且 LPSTR szIntegrityLevel对于任何 pid 都始终为空。

    <小时/>

    我创建了一个 c我在其中声明了以下内容 c获取 Integrity Level 的函数 通过 pid 的进程:

    #define         MAX_INTEGRITY_LEVEL_LENGTH                  30
    extern "C"
    {
        __declspec(dllexport) BOOL GetProcessIntegrityLevel(DWORD dwPID, LPSTR szIntegrityLevel);
    }
    

    C 函数实现:

    BOOL GetProcessIntegrityLevel(DWORD dwPID, LPSTR szIntegrityLevel)
    {
        BOOL    bFlag = FALSE;                      // Return flag
        HANDLE  hToken = INVALID_HANDLE_VALUE;      // Token handle
        HANDLE  hProcess = NULL;                    // Process handle
        BOOL    bProcToken = FALSE;                 // OpenProcessToken() result
        BOOL    bTokenInfo = FALSE;                 // GetTokenInformation() result
        DWORD   dwLengthNeeded = 0;                 // Token information length
        DWORD   dwError = ERROR_SUCCESS;            // GetTokenInformation() last error
        DWORD   dwIntegrityLevel = 0;               // Integrity level
    
        PTOKEN_MANDATORY_LABEL pTIL = NULL;         // Use as token information
    
        // Open the process
        hProcess = OpenProcess(MAXIMUM_ALLOWED | PROCESS_QUERY_LIMITED_INFORMATION,
            FALSE, dwPID);
        if (hProcess != NULL)
        {
            // Open process token
            bProcToken = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
            if (bProcToken == TRUE)
            {
                // Get token information
                bTokenInfo = GetTokenInformation(hToken, TokenIntegrityLevel,
                    NULL, 0, &dwLengthNeeded);
                if (bTokenInfo == FALSE)
                {
                    dwError = GetLastError();
                    if (dwError == ERROR_INSUFFICIENT_BUFFER)
                    {
                        pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwLengthNeeded);
                        if (pTIL != NULL)
                        {
                            // Get token information
                            bTokenInfo = GetTokenInformation(hToken, TokenIntegrityLevel,
                                pTIL, dwLengthNeeded, &dwLengthNeeded);
                            if (bTokenInfo == TRUE)
                            {
                                // Get integrity level
                                dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid,
                                    (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1));
    
                                if (dwIntegrityLevel <= SECURITY_MANDATORY_LOW_RID)
                                {
                                    // Low Integrity
                                    StrCpyA(szIntegrityLevel, "Low");
                                }
                                else if ((dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID) &&
                                    (dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID))
                                {
                                    // Medium Integrity
                                    StrCpyA(szIntegrityLevel, "Medium");
                                }
                                else if ((dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) &&
                                    (dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID))
                                {
                                    // High Integrity
                                    StrCpyA(szIntegrityLevel, "High");
                                }
                                else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID)
                                {
                                    // System Integrity
                                    StrCpyA(szIntegrityLevel, "System");
                                }
                                else if (dwIntegrityLevel == SECURITY_MANDATORY_UNTRUSTED_RID)
                                {
                                    // Untrusted integrity
                                    StrCpyA(szIntegrityLevel, "Untrusted");
                                }
                                else
                                {
                                    StrCpyA(szIntegrityLevel, "UnKnown");
                                }
    
                                bFlag = TRUE;
                            }
    
                            LocalFree(pTIL);
                        }
                    }
                }
    
                // Close token handle
                CloseHandle(hToken);
            }
    
            // Close the process handle
            CloseHandle(hProcess);
        }
    
        return bFlag;
    }
    

    所以,我导入 GetProcessIntegrityLevel()来 self 的c dll 在 c#如下:

    // Define function pointers for using of c dll functions
    [DllImport("ProcessesPropDll.dll",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.Bool)]
    // Get integrity level
    static extern bool GetProcessIntegrityLevel(ulong dwPID, StringBuilder szIntegrityLevel);
    

    并调用c#中的函数像这样:

    // Integrity level
    StringBuilder integrityLevel = new StringBuilder(200);
    
    if(GetProcessIntegrityLevel(11684, integrityLevel) == true)
    {
          MessageBox.Show(integrityLevel.ToString());
    }
    

    在这种状态下,当我运行程序时,GetProcessIntegrityLevel()返回true但是integrityLevel对于任何pid,消息框中始终为空!!!

    ‌令人惊讶的是,当我交换 c 中的参数时函数,也在c#中,它确实有效:

    __declspec(dllexport) BOOL GetProcessIntegrityLevel(LPSTR szIntegrityLevel, DWORD dwPID);
    

    这对我来说很奇怪。我还尝试过 MarshalAs(UnmanagedType.LPStr)]但给我相同的结果。

    最佳答案

    在 C# 中,ulong 是 64 位类型。 PID 参数是 DWORD,它是一个 32 位参数。

    将 C# 参数声明从 ulong 更改为 uint 以解决问题。

    关于c# - 将字符串从 c# 传递到 c dll 时的错误行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54071231/

    相关文章:

    c++ - 非阻塞套接字和 send()

    c++ - 如何使用 winapi 在 listview 子项中创建超链接

    Windows 8 关机过程与 Vista 不同?

    c# - 运行 xUnit.net 测试时的运行时文件夹结构

    c - 在C中使用sys/sem.h,如何获取信号量值?

    c# - sql 的索引零问题

    并发:使用 pthread_mutex 原子化增量操作

    c - 如何中断 gdb 中的多个 clang/ubsan 警告?

    c# - 来自 TickCount 的日期时间?

    c# - 如何在 .NET Core 应用程序中创建和实现授权过滤器