हाल ही में मुझे GetAppContainerNamedObjectPath नाम का एक विंडोज़ एपीआई मिला। लेकिन मुझे नहीं पता कि मैं इसका इस्तेमाल कैसे कर सकता हूं।

मुझे इस एपीआई के लिए एक एमएसडीएन पेज मिला (https ://docs.microsoft.com/en-us/windows/win32/api/securityappcontainer/nf-securityappcontainer-getappcontainernamedobjectpath)। लेकिन इसका एक सही उदाहरण और टिप्पणी नहीं है, पैरामीटर खराब तरीके से लिखे गए हैं।

मुझे अंत में 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 को दो बार कॉल करके गतिशील रूप से मेमोरी बफर आवंटित किया है। लेकिन फिर भी मौका नहीं मिला। वापसी की लंबाई एक सार्थक मूल्य नहीं लौटाती है।

1
vaska11 18 सितंबर 2020, 05:11

1 उत्तर

सबसे बढ़िया उत्तर

यदि आप 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
    );

टोकन और AppContainerSid को In_opt के साथ घोषित किया गया है -- इसका मतलब है कि यह पैरामीटर वैकल्पिक है, और आप इसमें से किसी एक के स्थान पर 0 पास कर सकते हैं। फिर अपने आप से पूछें - आप TokenAppContainerSid के लिए टोकन के लिए क्या क्वेरी करते हैं? यदि आप इस टोकन को एपीआई में पास करते हैं तो क्या सिस्टम आपके लिए ऐसा नहीं कर सकता है? स्पष्ट कर सकते हैं। इसलिए आपको इसे स्वयं करने की आवश्यकता नहीं है। वास्तव में आपको एपीआई को टोकन पास करने की आवश्यकता है और इस मामले में AppContainerSid 0 होना चाहिए। या आप AppContainerSid को एपीआई और इस मामले में पास कर सकते हैं टोकन 0 होना चाहिए। जब ​​AppContainerSid और टोकन दोनों शून्य न हों - तो आपको STATUS_INVALID_PARAMETER_MIX

साइड नोट के रूप में भी - यदि आपको टोकन प्राप्त करने की आवश्यकता है तो आपको PROCESS_ALL_ACCESS के साथ खुली प्रक्रिया की आवश्यकता नहीं है। PROCESS_QUERY_LIMITED_INFORMATION काफी है


वास्तव में एपीआई बड़ा जादू नहीं करते हैं। यह आपके पास लौटता है

AppContainerNamedObjects\<Sid>

पथ, जहां ऐप कंटेनर सिड का स्ट्रिंग रूप है। (कुछ जैसे S-1-15-2-...)

3
RbMm 18 सितंबर 2020, 11:29