2013-10-08 8 views
0

내 응용 프로그램이 서비스로 실행되며 어느 시점에 시스템의 기존 사용자 계정을 모두 순환해야합니다 (이 작업은 NetUserEnum()과 함께 수행 할 수 있습니다) 발견 된 각 사용자의 % APPDATA % 경로 아래에 파일이 있습니다. 문제는 그 사용자 특정 경로 (% APPDATA %)를 얻는 방법을 모른다는 것입니다.Windows 서비스 : 각 사용자의 % APPDATA % 변수 가져 오기

응용 프로그램이 서비스 (SYSTEM)로 실행되므로 환경 또는 SHGetFolderPath()을 사용할 수 없습니다. 처음에는 LogonUser()을 사용할 수 있다고 생각했지만 사용자, 관리자 또는 시스템에서 응용 프로그램 테스트 코드를 실행하더라도 항상 오류 1326이 나옵니다. (테스트 플랫폼으로 winxp). 사용자 로그인 핸들을 얻을 수있는 방법이 있다면 SHGetFolderPath() 또는 ExpandEnvironmentStringsForUser() API에서 사용할 수 있습니다. 맞습니까?

그래서, LogonUser (함께 지금까지 시도 코드)는 다음에 관한 것입니다 (예, 사용자 이름이 올바른지) : 아마 비밀번호를 원하지만 내가 아는 방법이 없습니다

LogonUser(
    pw->usri1_name, 
    L".", 
    NULL, 
    LOGON32_LOGON_BATCH, 
    LOGON32_PROVIDER_DEFAULT, 
    &authtoken 
) 

해당 고객에 기계. 빠른 검색에서 찾은 모든 API는 LogonUser()에서 HANDLE에 의존합니다. 나는 분명히 가질 수 없습니다 ...

모든 까다 롭고 까다로운 아이디어를 환영합니다!

+0

% appdata %는 다양한 시스템 출시와 아마도 언어에서도 다를 수 있습니다. 테스트 할 수 없으므로 간단히 말할 수 없습니다. 나는 할 수있다, 그러나 적어도 나는 그것이 내려 오지 않기를 바란다?/facepalm/ – einclude

+0

오류 1326은'ERROR_LOGON_FAILURE' (로그온 실패 : 알 수없는 사용자 이름 또는 잘못된 암호)입니다. 예를 들어 암호를 제공하지 않습니다. –

답변

0

지금까지의 결론과 결론.

LogonUser()을 올바르게 사용할 수 없습니다.

  • SHGetFolderPath(CSIDL_APPDATA)
  • :

    는 대신, 옵션은 다음 중 하나를 기반으로, (NetUserEnum() 제안 내, 그래도 여전히 선호하는 방법을 통해 획득) bruteforcing의 사용자 홈 디렉토리 후 경로에 와서

  • 등록 키 HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders

다른 방법을 알고 있다면 의견을 말하십시오."로컬 시스템"으로

-1

WTSEnumerateSessions()WTSQueryUserToken()을 사용하여 각 로그인 세션의 토큰을 검색 할 수 있습니다.

또한 특정 사용자의 HKEY_CURRENT_USER 키에 액세스하는 서비스에 필요한 LoadUserProfile()을 확인하십시오. 필요한 사용자 토큰을 얻으려면 대화식 또는 프로그래밍 방식으로 로그인하거나 가장해야합니다.

또 다른 옵션은 사용자 계정의 SID를 검색하기 위해 HKEY_USERS 키를 열거하고 LookupAccountSid()을 사용하여 사용자 이름을 검색 한 다음 OS 버전을 기반으로 AppData 경로를 수동으로 포맷합니다. 유연하지는 않지만 사용자 별 레지스트리 데이터에 덜 의존적입니다.

그렇지 않으면 서비스에서 사용자 별 폴더에 쓰는 것을 잊어 버리십시오. 대신 일반적인 공유 폴더에 쓰기 (예 : CSIDL_COMMON_APPDATAFOLDERID_ProgramData).

+0

RDP 로그인 한 사용자 만 로그인 할 수 있습니다. 기존 사용자의 % APPDATA %를 모두 수집해야이 접근 방식이 작동하지 않습니다. LoadUserProfile()은 내가 가지고 있지 않은 핸들을 요청합니다. – einclude

+0

해당 사용자의 레지스트리 데이터에 액세스하려면 사용자 프로필을로드해야합니다. 해당 사용자의 프로필을로드하기 위해 해당 사용자의 토큰을 얻으려면 사용자가 로그인하거나 가장해야합니다. 이것이 LoadUserProfile()이 기대하는 핸들입니다. –

+0

로그인하지 않은 사용자의 프로필을로드하는 방법에 대한 더 많은 힌트가 있습니까? 서비스이기 때문에 모든 사용자가 시스템에 로그인하는 것보다 일찍 시작될 수 있으므로 사용 가능한 세션이 없습니다. – einclude

0

서비스 또는 응용 프로그램 실행 특수 폴더

우리가 가 CSIDL_DESKTOPDIRECTORY, XP에서 잘 작동 얻을이 예를, WIN7를 얻을 수 있습니다 (32, 64)

DWORD ServiceGetDesktopDirectory(LPWSTR lpUserName, LPWSTR lpPassword, 
    LPWSTR lpDomain, LPWSTR lpBuffer) 
{ 

HANDLE hToken; 
BOOL bRet; 
bRet = LogonUserW(lpUserName, 
       lpDomain, 
       lpPassword, 
       LOGON32_LOGON_INTERACTIVE, 
       LOGON32_PROVIDER_DEFAULT, 
       &hToken); 
if (!bRet) { 
    error("LogonUser failed, gle = %lu", GetLastError()); 
    return FILE_ERR_INVALID_USERNAME_OR_PASSWORD; 
} 


NET_API_STATUS ntStatus; 
USER_INFO_4 *pUserInfo; 
ntStatus = NetUserGetInfo((LPCWSTR)lpDomain, 
          (LPCWSTR)lpUserName, 
          4, 
          (BYTE**)&pUserInfo); 
if (ntStatus != NERR_Success) { 
    error("NetUserGetInfo failed, ntStatus 0X%x", ntStatus); 
    CloseHandle(hToken); 
    return FILE_ERR_SYSTEM_ERROR; 
} 

PROFILEINFOW profile; 
memset(&profile, 0, sizeof(PROFILEINFOW)); 
profile.dwSize = sizeof(PROFILEINFOW); 
profile.lpUserName = lpUserName; 
profile.lpProfilePath = pUserInfo->usri4_profile; 
bRet = LoadUserProfileW(hToken, &profile); 
if (!bRet) { 
    error("LoadUserProfile failed, gle = %lu", GetLastError()); 
    CloseHandle(hToken); 
    NetApiBufferFree(pUserInfo); 
    return FILE_ERR_SYSTEM_ERROR; 
} 


HRESULT hr; 
hr = SHGetFolderPathW(NULL, 
       CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, 
       hToken, 
       0, 
       lpBuffer); 
if (FAILED(hr)) { 
    error("SHGetFolderPath failed, hr 0X%x", hr); 
    NetApiBufferFree(pUserInfo); 
    UnloadUserProfile(hToken, profile.hProfile); 
    CloseHandle(hToken); 
    return FILE_ERR_SYSTEM_ERROR; 
} 

NetApiBufferFree(pUserInfo); 
UnloadUserProfile(hToken, profile.hProfile); 
CloseHandle(hToken); 
return FILE_ERR_OK; 
}