有人有使用 GetAppContainerNamedObjectPath 的经验吗?
Anyone has experience on using GetAppContainerNamedObjectPath?
最近我遇到了一个叫 GetAppContainerNamedObjectPath
的 Windows API。但是我不知道如何使用它。
我找到了这个 api (https://docs.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath) 的 msdn 页面。但是没有正确的例子和注释,参数写得不好。
最后出现 ERROR_INVALID_PARAMETER(87)
错误,这告诉我输入的参数有问题。这是我试过的。
#define TokenIsAppContainer 29
#define TokenAppContainerSid 31
#define TokenAppContainerNumber 32
typedef struct _TOKEN_APPCONTAINER_INFORMATION {
PSID TokenAppContainer;
} TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;
void GetAppContainerProcessInfo(CString & procName)
{
DWORD dwSize = 0;
DWORD dwResult;
HANDLE hToken;
PTOKEN_APPCONTAINER_INFORMATION pAppCoInfo;
WCHAR wcsDebug[1024] = {0,};
WCHAR * pwSID = NULL;
typedef BOOL (WINAPI *_LPGETAPPCONTAINERNAMEOBJECTPATH)(HANDLE, PSID, ULONG, LPWSTR, PULONG);
static _LPGETAPPCONTAINERNAMEOBJECTPATH lpGetAppContainerNamedObjectPath = NULL;
if (0 == lpGetAppContainerNamedObjectPath)
{
HMODULE hKernel32 = LoadLibraryExW(L"kernel32.dll", NULL, 0);
if (hKernel32)
{
lpGetAppContainerNamedObjectPath = reinterpret_cast<_LPGETAPPCONTAINERNAMEOBJECTPATH>(GetProcAddress(hKernel32, "GetAppContainerNamedObjectPath"));
}
}
if (lpGetAppContainerNamedObjectPath)
{
DWORD processId = (DWORD)_ttoi((LPCTSTR)procName);
//HANDLE hProcess = GetProcessHandleByProcessName(procName);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if(!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"OpenProcessToken Error(%u) PID(%d)\n", dwResult, processId );
AfxMessageBox(wcsDebug);
return;
}
if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, NULL, dwSize, &dwSize))
{
dwResult = GetLastError();
if( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
return;
}
}
pAppCoInfo = (PTOKEN_APPCONTAINER_INFORMATION) GlobalAlloc( GPTR, dwSize );
if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, pAppCoInfo, dwSize, &dwSize))
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
return;
}
WCHAR wcsNamedObjectPath[MAX_PATH];
ULONG ulRetlen = 0;
BOOL bRet = lpGetAppContainerNamedObjectPath(hToken, pAppCoInfo->TokenAppContainer, _countof(wcsNamedObjectPath), wcsNamedObjectPath, &ulRetlen );
if (bRet)
{
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Path(%s)\n", wcsNamedObjectPath );
AfxMessageBox(wcsDebug);
}
else
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
}
if (pwSID)
LocalFree(pwSID);
CloseHandle(hToken)
CloseHandle(hProcess);
}
}
作为旁注,我尝试使用 wchar_t *
并通过调用 GetAppContainerNamedObjectPath
两次来动态分配内存缓冲区。但是还是没有机会。 Return 长度不是 return 有意义的值。
如果你在 GetAppContainerNamedObjectPath
之后调用 RtlGetLastNtStatus();
而不是 GetLastError();
你会得到
STATUS_INVALID_PARAMETER_MIX
- 指定了无效的参数组合。
这为您提供了更多信息,比较了简单的无效参数。
然后寻找函数签名
BOOL
WINAPI
GetAppContainerNamedObjectPath(
_In_opt_ HANDLE Token,
_In_opt_ PSID AppContainerSid,
_In_ ULONG ObjectPathLength,
_Out_writes_opt_(ObjectPathLength) LPWSTR ObjectPath,
_Out_ PULONG ReturnLength
);
用In_opt声明的Token和AppContainerSid——这意味着该参数是可选的,您可以传递 0 代替其中之一。然后问问你自己 - 你查询 TokenAppContainerSid 的令牌是什么?如果您将此令牌传递给 api ,系统是否无法为您执行此操作?明显可以。所以你不需要自己做。你真的需要将 Token 传递给 api,在这种情况下 AppContainerSid 必须为 0。或者你可以传递 AppContainerSid 到 api 并且在这种情况下 Token 必须为 0。当 AppContainerSid 和 Token 不为零 - 你得到了 STATUS_INVALID_PARAMETER_MIX
另请注意 - 如果您需要获取令牌,则不需要使用 PROCESS_ALL_ACCESS
打开进程。 PROCESS_QUERY_LIMITED_INFORMATION
就够了
真的api不会做大魔法。它 return 给你
AppContainerNamedObjects\<Sid>
路径,其中应用程序容器 sid 的字符串形式。(有些像 S-1-15-2-...)
最近我遇到了一个叫 GetAppContainerNamedObjectPath
的 Windows API。但是我不知道如何使用它。
我找到了这个 api (https://docs.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath) 的 msdn 页面。但是没有正确的例子和注释,参数写得不好。
最后出现 ERROR_INVALID_PARAMETER(87)
错误,这告诉我输入的参数有问题。这是我试过的。
#define TokenIsAppContainer 29
#define TokenAppContainerSid 31
#define TokenAppContainerNumber 32
typedef struct _TOKEN_APPCONTAINER_INFORMATION {
PSID TokenAppContainer;
} TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION;
void GetAppContainerProcessInfo(CString & procName)
{
DWORD dwSize = 0;
DWORD dwResult;
HANDLE hToken;
PTOKEN_APPCONTAINER_INFORMATION pAppCoInfo;
WCHAR wcsDebug[1024] = {0,};
WCHAR * pwSID = NULL;
typedef BOOL (WINAPI *_LPGETAPPCONTAINERNAMEOBJECTPATH)(HANDLE, PSID, ULONG, LPWSTR, PULONG);
static _LPGETAPPCONTAINERNAMEOBJECTPATH lpGetAppContainerNamedObjectPath = NULL;
if (0 == lpGetAppContainerNamedObjectPath)
{
HMODULE hKernel32 = LoadLibraryExW(L"kernel32.dll", NULL, 0);
if (hKernel32)
{
lpGetAppContainerNamedObjectPath = reinterpret_cast<_LPGETAPPCONTAINERNAMEOBJECTPATH>(GetProcAddress(hKernel32, "GetAppContainerNamedObjectPath"));
}
}
if (lpGetAppContainerNamedObjectPath)
{
DWORD processId = (DWORD)_ttoi((LPCTSTR)procName);
//HANDLE hProcess = GetProcessHandleByProcessName(procName);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if(!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"OpenProcessToken Error(%u) PID(%d)\n", dwResult, processId );
AfxMessageBox(wcsDebug);
return;
}
if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, NULL, dwSize, &dwSize))
{
dwResult = GetLastError();
if( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
return;
}
}
pAppCoInfo = (PTOKEN_APPCONTAINER_INFORMATION) GlobalAlloc( GPTR, dwSize );
if (!GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS) TokenAppContainerSid, pAppCoInfo, dwSize, &dwSize))
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetTokenInformation Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
return;
}
WCHAR wcsNamedObjectPath[MAX_PATH];
ULONG ulRetlen = 0;
BOOL bRet = lpGetAppContainerNamedObjectPath(hToken, pAppCoInfo->TokenAppContainer, _countof(wcsNamedObjectPath), wcsNamedObjectPath, &ulRetlen );
if (bRet)
{
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Path(%s)\n", wcsNamedObjectPath );
AfxMessageBox(wcsDebug);
}
else
{
dwResult = GetLastError();
swprintf_s( wcsDebug, _countof(wcsDebug), L"GetAppContainerNamedObjectPath Error %u\n", dwResult );
AfxMessageBox(wcsDebug);
}
if (pwSID)
LocalFree(pwSID);
CloseHandle(hToken)
CloseHandle(hProcess);
}
}
作为旁注,我尝试使用 wchar_t *
并通过调用 GetAppContainerNamedObjectPath
两次来动态分配内存缓冲区。但是还是没有机会。 Return 长度不是 return 有意义的值。
如果你在 GetAppContainerNamedObjectPath
之后调用 RtlGetLastNtStatus();
而不是 GetLastError();
你会得到
STATUS_INVALID_PARAMETER_MIX
- 指定了无效的参数组合。
这为您提供了更多信息,比较了简单的无效参数。
然后寻找函数签名
BOOL
WINAPI
GetAppContainerNamedObjectPath(
_In_opt_ HANDLE Token,
_In_opt_ PSID AppContainerSid,
_In_ ULONG ObjectPathLength,
_Out_writes_opt_(ObjectPathLength) LPWSTR ObjectPath,
_Out_ PULONG ReturnLength
);
用In_opt声明的Token和AppContainerSid——这意味着该参数是可选的,您可以传递 0 代替其中之一。然后问问你自己 - 你查询 TokenAppContainerSid 的令牌是什么?如果您将此令牌传递给 api ,系统是否无法为您执行此操作?明显可以。所以你不需要自己做。你真的需要将 Token 传递给 api,在这种情况下 AppContainerSid 必须为 0。或者你可以传递 AppContainerSid 到 api 并且在这种情况下 Token 必须为 0。当 AppContainerSid 和 Token 不为零 - 你得到了 STATUS_INVALID_PARAMETER_MIX
另请注意 - 如果您需要获取令牌,则不需要使用 PROCESS_ALL_ACCESS
打开进程。 PROCESS_QUERY_LIMITED_INFORMATION
就够了
真的api不会做大魔法。它 return 给你
AppContainerNamedObjects\<Sid>
路径,其中应用程序容器 sid 的字符串形式。(有些像 S-1-15-2-...)