⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 服务程序如何获取映射驱动器名.txt

📁 本人是在写一个服务程序时遇到了无法获取映射驱动器的问题,通过解决该问题有一些体会. 关键词:服务,当前用户,映射驱动,令牌器,CreateService,ChangeServiceConfig2,
💻 TXT
字号:
服务程序如何获取映射驱动器名?
(原创)
	writed by xubing in 2005.12.16

    本人是在写一个服务程序时遇到了无法获取映射驱动器的问题,通过解决该问题有一些体会,小结如下:

1.CreateService中最后两个参数如果传递NULL,则以系统帐号运行。

“如果一个进程正在一个用户帐号下执行,那么这个进程就同时拥有这个用户所能拥有的一切访问权限,不论是在本机还是网络。系统帐号则是一个特殊的账号,它用来标识系统本身,而且运行在这个帐号下的任何进程都拥有系统上的所有访问权限,但是系统帐号不能在域上使用,无法访问网络资源…

  服务也是Win32可执行程序,它也需要执行在一个context,通常服务都是在系统账号下运行,但是也可以根据情况选择让它运行在一个用户账号下,也就会因此获得相应的访问资源的权限。”
--摘自《Windows服务编写原理及探讨》

修改成相应用户即可:

示例:(只说明CreateService最后两个参数)

本机 - _T(".\\user1"), _T("123456") 
域(域名为abc.local) - _T("abc.local\\user2"), _T("123456")

2.可以用ChangeServiceConfig2动态修改服务的帐号

3.但是有一个问题,实际中我设置了正确的用户,但只能在安装或启动服务时能够访问
映射驱动器,运行时无法访问。原因是运行时服务是以另一个线程运行的,需要设置该线程的
权限。可以调用ImpersonateLoggedOnUser,该函数需要传递用户的令牌,至于如何得到当前
用户的令牌,则是另一个问题了,可以参考msdn.这里给出一个不需要用户输入而直接获取
explorer.exe的用户令牌的函数,也是从网上找来的,至于如何得到explorer.exe的进程ID
就不用我说了吧。该方法的缺点是必须当前机器中有explorer.exe。

//得到当前登录用户的Token
HANDLE GetCurUserToken()
{
	HANDLE hProc  = NULL;
	HANDLE hToken = NULL;

	//通过得到explorer.exe的Token间接得到当前用户的Token
	DWORD dwID = GetProcessID(_T("explorer.exe")) ;	
	if (dwID != -1)	
	{
		hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwID);
		if (hProc != NULL)
		{
			//dwDesiredAccess不设为TOKEN_ALL_ACCESS是为了更准确的确定OpenProcessToken失败的原因
			DWORD dwDesiredAccess = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE;
			BOOL bRet = OpenProcessToken(hProc, dwDesiredAccess, &hToken);//TOKEN_ALL_ACCESS 
			::CloseHandle(hProc);
			if (bRet)
			{
				return hToken ;//成功
			}			
			else
				WriteDebug("CUSPServerMonitor - Open process token of explorer.exe failed") ;
		}
		else
			WriteDebug("CUSPServerMonitor - Open process of explorer.exe failed") ;
	}
	else
	{
		WriteDebug("CUSPServerMonitor - Get process id of explorer.exe is -1") ;
	}

	return NULL ;
}

4.如何使用ImpersonateLoggedOnUser呢,以下仅供参考。
在服务运行的函数中这样写:

//	启动服务时被系统调用
void CTestService::Run(DWORD dwArgc, LPTSTR * ppszArgv)
{
	ReportStatus(SERVICE_START_PENDING);
	//...
	
	// TODO:  在此添加您的专用代码

	HANDLE hToken = GetCurUserToken() ;//得到当前用户的令牌
	if (::ImpersonateLoggedOnUser(hToken))//让当前线程模拟该用户的security-context 
	{
		WriteDebug("CTestService::Run() - ImpersonateLoggedOnUser ok");
	}
	else
	{
		WriteDebug("CTestService::Run() - ImpersonateLoggedOnUser failed - %s", GetLastErrorText());
	}

	//...

	// report SERVICE_RUNNING immediately before you enter the main-loop
	// DON'T FORGET THIS!
	ReportStatus(SERVICE_RUNNING);

	//...
}



欢迎交流!
email:	xubing728@yahoo.com.cn

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -