转自:http://hi.baidu.com/robinwjbgui/blog/item/7ab0a213b2b2bf866438db10.html
以服务权限,即SYSTEM帐户启动的程序是无法取得用户的profile的,比如startup文件夹的路径。
首先,Shell函数是不行的:
SHGetSpecialFolderPath取得的是C:/Windows/system32/config/systemprofile/
其次,环境变量也得不到。
GetEnvironmentVariable返回203( ERROR_ENVVAR_NOT_FOUND)
注:从服务应用程序可以拿到全局的环境变量,诸如ALLUSERS等等,但是各个用户的就搞不定了。
虽说从服务来访问用户的profile是一种非常不好的设计,但是如果有一些特殊需求的话,,
可以使用下面的方法。
BOOL
bRes
=
FALSE;
char lpPath [ MAX_PATH ];
DWORD RetVal = 0;
DWORD ErrCode = 0;
DWORD ConsoleSessionId = 0;
// 函数的句柄
HMODULE hInstKernel32 = NULL;
HMODULE hInstWtsapi32 = NULL;
// Token的句柄
HANDLE hTokenUser = NULL;
HANDLE hTokenThisProcess = NULL;
HANDLE hTokenThis = NULL;
// WTSGetActiveConsoleSessionId 函数,得到当前登录用户的会话ID
// 这里的代码用的是VC6,新版的SDK已经包括此函数,无需LoadLibrary了。
typedef DWORD ( WINAPI * WTSGetActiveConsoleSessionIdPROC)();
WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
hInstKernel32 = LoadLibrary( "Kernel32.dll");
if ( ! hInstKernel32)
{
return FALSE;
}
WTSGetActiveConsoleSessionId = ( WTSGetActiveConsoleSessionIdPROC) GetProcAddress( hInstKernel32 , "WTSGetActiveConsoleSessionId");
if ( ! WTSGetActiveConsoleSessionId)
{
return FALSE;
}
// WTSQueryUserToken 函数,通过会话ID得到令牌
typedef BOOL ( WINAPI * WTSQueryUserTokenPROC)( ULONG SessionId , PHANDLE phToken );
WTSQueryUserTokenPROC WTSQueryUserToken = NULL;
hInstWtsapi32 = LoadLibrary( "Wtsapi32.dll");
if ( ! hInstWtsapi32)
{
return FALSE;
}
WTSQueryUserToken = ( WTSQueryUserTokenPROC) GetProcAddress( hInstWtsapi32 , "WTSQueryUserToken");
if ( ! WTSQueryUserToken)
{
return FALSE;
}
// 得到当前激活用户的会话ID
ConsoleSessionId = WTSGetActiveConsoleSessionId();
// 得到当前登录用户的令牌
bRes = WTSQueryUserToken( ConsoleSessionId , & hTokenUser);
if ( ! bRes)
{
return FALSE;
}
// 模仿成当前登录用户
bRes = ImpersonateLoggedOnUser( hTokenUser);
if ( ! bRes)
{
return FALSE;
}
// 取得当前用户的Startup文件夹路径
bRes = SHGetSpecialFolderPath( NULL , lpPath , CSIDL_STARTUP , TRUE);
if ( ! bRes)
{
return FALSE;
}
else
{
MessageBox( NULL , lpPath , "Startup" , MB_OK);
}
// 终止模拟,返回
RevertToSelf();
char lpPath [ MAX_PATH ];
DWORD RetVal = 0;
DWORD ErrCode = 0;
DWORD ConsoleSessionId = 0;
// 函数的句柄
HMODULE hInstKernel32 = NULL;
HMODULE hInstWtsapi32 = NULL;
// Token的句柄
HANDLE hTokenUser = NULL;
HANDLE hTokenThisProcess = NULL;
HANDLE hTokenThis = NULL;
// WTSGetActiveConsoleSessionId 函数,得到当前登录用户的会话ID
// 这里的代码用的是VC6,新版的SDK已经包括此函数,无需LoadLibrary了。
typedef DWORD ( WINAPI * WTSGetActiveConsoleSessionIdPROC)();
WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
hInstKernel32 = LoadLibrary( "Kernel32.dll");
if ( ! hInstKernel32)
{
return FALSE;
}
WTSGetActiveConsoleSessionId = ( WTSGetActiveConsoleSessionIdPROC) GetProcAddress( hInstKernel32 , "WTSGetActiveConsoleSessionId");
if ( ! WTSGetActiveConsoleSessionId)
{
return FALSE;
}
// WTSQueryUserToken 函数,通过会话ID得到令牌
typedef BOOL ( WINAPI * WTSQueryUserTokenPROC)( ULONG SessionId , PHANDLE phToken );
WTSQueryUserTokenPROC WTSQueryUserToken = NULL;
hInstWtsapi32 = LoadLibrary( "Wtsapi32.dll");
if ( ! hInstWtsapi32)
{
return FALSE;
}
WTSQueryUserToken = ( WTSQueryUserTokenPROC) GetProcAddress( hInstWtsapi32 , "WTSQueryUserToken");
if ( ! WTSQueryUserToken)
{
return FALSE;
}
// 得到当前激活用户的会话ID
ConsoleSessionId = WTSGetActiveConsoleSessionId();
// 得到当前登录用户的令牌
bRes = WTSQueryUserToken( ConsoleSessionId , & hTokenUser);
if ( ! bRes)
{
return FALSE;
}
// 模仿成当前登录用户
bRes = ImpersonateLoggedOnUser( hTokenUser);
if ( ! bRes)
{
return FALSE;
}
// 取得当前用户的Startup文件夹路径
bRes = SHGetSpecialFolderPath( NULL , lpPath , CSIDL_STARTUP , TRUE);
if ( ! bRes)
{
return FALSE;
}
else
{
MessageBox( NULL , lpPath , "Startup" , MB_OK);
}
// 终止模拟,返回
RevertToSelf();