如何获取SYSTEM用户%APPDATA%文件夹的路径?

时间:2018-10-19 08:07:52

标签: winapi

SHGetFolderPath返回运行该程序的用户的%APPDATA%,即使已使用SYSTEM用户令牌对其进行了调用。

1 个答案:

答案 0 :(得分:0)

如果运行提升,此代码对我有用:

// Compile with –DPSAPI_VERSION=1
#pragma comment(lib, "userenv.lib")
#pragma comment(lib, "Psapi.lib")

#include <windows.h>
#include <sddl.h>
#include <UserEnv.h>
#include <psapi.h>
#include <shlobj.h>
#include <vector>

bool EnablePrivilege(WCHAR *szPrivName, bool enable)
{
  TOKEN_PRIVILEGES tp;
  LUID  id;
  HANDLE    token;
  if (!LookupPrivilegeValue(0, szPrivName, &id))
    return false;
  if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
    return false;
  tp.PrivilegeCount = 1;
  tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
  tp.Privileges[0].Luid.LowPart = id.LowPart;
  tp.Privileges[0].Luid.HighPart = id.HighPart;
  AdjustTokenPrivileges(token, FALSE, &tp, sizeof(tp), 0, 0);
  CloseHandle(token);
  return (GetLastError() == ERROR_SUCCESS);
}

bool IsTokenSystem(HANDLE tokenHandle)
{
  bool result = false;
  DWORD retLen = 0;
  DWORD tokenLen = 1024;
  std::vector<WCHAR> buf(tokenLen);
  TOKEN_USER *token = (TOKEN_USER*)&buf.front();
  if (GetTokenInformation(tokenHandle, TokenUser, token, tokenLen, &retLen)) {
    WCHAR *stringSid = 0;
    if (ConvertSidToStringSid(token->User.Sid, &stringSid))
      if (wcscmp(stringSid, L"S-1-5-18") == 0) // SYSTEM user SID
        result = true;
    LocalFree(stringSid);
    }
  return result;
}

HANDLE GetSystemProcessToken()
{
  if (!EnablePrivilege(SE_DEBUG_NAME, true))
    printf("Enable SeDebugPrivilege error: %d\n", GetLastError());
  DWORD pids[10000] = { 0 };
  DWORD needed = 0;
  if (!EnumProcesses(pids, sizeof(pids), &needed)) {
    return 0;
  }
  for (DWORD i = 0; i < needed / sizeof(DWORD); ++i) {
    HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pids[i]);
    if (!processHandle)
      continue;
    HANDLE tokenHandle = 0;
    DWORD access = TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_EXECUTE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_READ;
    if (OpenProcessToken(processHandle, access, &tokenHandle)) {
      if (IsTokenSystem(tokenHandle)) {
        CloseHandle(processHandle);
        return tokenHandle;
      }
    }
    CloseHandle(tokenHandle);
    CloseHandle(processHandle);
  }
  return 0;
}

int wmain(int argc, WCHAR * argv[])
{
  HANDLE systemToken = GetSystemProcessToken();
  if (systemToken == 0)
    printf("Can't get systemToken\n");
  WCHAR path[MAX_PATH];
  if (SHGetFolderPath(0, CSIDL_APPDATA, systemToken, SHGFP_TYPE_CURRENT, &path[0]) == S_OK) {
    printf("AppData folder: %ls\n", &path[0]);
  } else {
    printf("SHGetFolderPath error: %d\n", GetLastError());
  }
  return 0;
}