【问题标题】:Wrong behaviour when passing string from c# to c dll将字符串从 c# 传递到 c dll 时的错误行为
【发布时间】:2019-06-01 22:21:26
【问题描述】:

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

但他们都无法帮助我。我更愿意以任何方式问我的问题:


简要说明:
我的c 函数在c# 中正常工作,就在我从以下位置交换GetProcessIntegrityLevel 参数(在c dll 和c# import-dll 中)时:

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

到这个:

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

在第一种状态下,我的程序正常工作并更改了LPSTR szIntegrityLevel 但在第二种状态下,它不起作用,LPSTR szIntegrityLevel 总是为空,带有任何 pid。


我创建了一个c dll 库,我在其中声明了以下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;
}

所以,我从c# 中的c dll 导入GetProcessIntegrityLevel(),如下所示:

// 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,但对于任何pid,消息框中的integrityLevel 始终为空!!!!

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

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

这对我来说很奇怪。我也尝试了MarshalAs(UnmanagedType.LPStr)],但结果相同。

【问题讨论】:

    标签: c# c winapi dllimport


    【解决方案1】:

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

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

    【讨论】:

    • 我对其他函数有这个问题,它们几乎都有DWORD 类型,我应该测试它们。无论如何谢谢你。
    猜你喜欢
    • 2012-02-12
    • 2014-02-24
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多