在 C++ 中使用 _tprintf 打印问号

Issue in c++ with _tprintf printing question marks

我在使用C++时遇到了一些问题,不要经常使用这种语言!

我正在尝试处理 NTFS 目录中的 ACL,以便输出目录中存在的所有允许和拒绝权限的完整列表。

我已经从目录中获得了 ACL,而且对于大多数记录,我已经获得了 Domain\Account 名称。然而,在某些情况下,输出这只会给我 ????????\??????????.

我已经确定了 2 个原因。

1) 用户帐户已从计算机中删除,因此 SID 是孤立的。我可以用 GetLastError() = 1332 来确定。

2) 它是一个 'Well-known SID' 即某种内置 SID,因此没有要映射到的用户名 - 此时 LookupAccountSid 不报告错误。如果不将所有众所周知的 SID 映射到一个文件并进行交叉引用(缓慢),我无法(据我所知)识别这些情况。我想要做的只是输出 SID 而不是 ????????。 LPTSTR myTrusteeName 是从 LookupAccountSid() 返回的字符串,呈现为 ????????。我不知道它的实际值是多少,如果我知道我可以轻松地执行 IF 语句来打印 SID。

        //this is part of a loop.
        if (IsValidSid(mySid)){
            //cout << "SID supplied is valid\n";
            //cout << GetLengthSid(mySid) << "\n";

            LPWSTR mySidName = NULL;
            ConvertSidToStringSid((PSID)mySid, &mySidName);




            //Make an initial lookup to find out how big the names are
            LookupAccountSid(
                NULL
                , (PSID) mySid
                , myTrusteeName
                , (LPDWORD)&myDwordNameLength
                , myDomainName
                , (LPDWORD)&myDwordDomLength
                , &myNameUse
                ); //at this point error 122 is thrown as the length of myTrusteeName is too short.

            //alter the size of these variables rather than just getting the 1st letter and some gibberish
            myTrusteeName = (LPTSTR)GlobalAlloc(GMEM_FIXED, myDwordNameLength);
            myDomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, myDwordDomLength);

            //do the lookup again this time with genuine sizes
            LookupAccountSid(
                NULL
                , (PSID)mySid
                , myTrusteeName
                , (LPDWORD)&myDwordNameLength
                , myDomainName
                , (LPDWORD)&myDwordDomLength
                , &myNameUse
                );

            wcout << GetLastError() << "\n"; //this will output "122" even when successful because of the first attempt.

            _tprintf(TEXT("%s\n"), myTrusteeName); //when there is no name this outputs ????????

            wcout << myTrusteeName << "\n"; //when there is no name this completely screws myTrusteeName so that it fails to print for the rest of the loop


            //if we only have ???? then it's wrong
            if (myTrusteeName == NULL){ /// WHAT IN HELL DO I PUT IN THIS COMPARISON TO IDENTIFY myTrusteeName VALUES THAT PRINT ????????
                wcout << "we are changing trustee because it's blank\n";
                myTrusteeName = _T("");//maybe change this to the value of mySidName
                wcout << "length of trustee is now " << _tcslen(myTrusteeName) << "\n";
            }
            wcout << "\n";



        }

现在...在写这篇文章时我意识到有一个函数叫做 IsWellKnownSid() facepalm

这从 WELL_KNOWN_SID_TYPE 枚举中输出一个项目

我应该可以使用它....我不确定如何获得众所周知的 sid 类型(即 "Users")的字符串表示形式,就像您在 ACL 编辑器中看到的那样到目前为止....如果有人对此有任何建议,我将不胜感激。

我还没有完成这个小项目,所以我想我会 post 无论如何,以防将来它对其他人有用!

我也很好奇——如果没有 IsWellKnownSid() 函数,我将如何在尝试打印之前检测拒绝打印的字符串值?

非常感谢您的阅读和最诚挚的问候 本

您应该检查 ConvertSidToStringSidLookupAccountSid return 是否正确。如果他们这样做,那么 LookupAccountSid 将向 myTrusteeName 写入一个字符串。如果 LookupAccountSid return 为 FALSE,则 LookupAccountSid 不会更改 myTrusteeName 的内容,因此它将像 GlobalAlloc return 编辑它一样未初始化。