在 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() 函数,我将如何在尝试打印之前检测拒绝打印的字符串值?
非常感谢您的阅读和最诚挚的问候
本
您应该检查 ConvertSidToStringSid
和 LookupAccountSid
return 是否正确。如果他们这样做,那么 LookupAccountSid 将向 myTrusteeName
写入一个字符串。如果 LookupAccountSid return 为 FALSE,则 LookupAccountSid 不会更改 myTrusteeName
的内容,因此它将像 GlobalAlloc
return 编辑它一样未初始化。
我在使用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() 函数,我将如何在尝试打印之前检测拒绝打印的字符串值?
非常感谢您的阅读和最诚挚的问候 本
您应该检查 ConvertSidToStringSid
和 LookupAccountSid
return 是否正确。如果他们这样做,那么 LookupAccountSid 将向 myTrusteeName
写入一个字符串。如果 LookupAccountSid return 为 FALSE,则 LookupAccountSid 不会更改 myTrusteeName
的内容,因此它将像 GlobalAlloc
return 编辑它一样未初始化。