Accessing Windows Services

Windows Q&A
January 22, 2005


Accessing Windows Services

How can I programmatically determine the user account of a service?

(Part 1 of 2) Windows Services (also known as “NT Services” because they first appeared in the Windows NT operating system) are an extremely handy way to package an executable that needs to [1] run automatically at system startup, [2] run in the background, and [3] run under a specific user account. Although it’s possible to partially simulate each of these behaviors by adding an application to the Startup folder and using the RUNAS.EXE application to run under an alternative account (except for the slight problem of the inability to specify a password on the command-line for security reasons), it’s a lot more straightforward to use a service. Although the topic of Windows Services could easily run to book-length, we’ll take a closer look at determining the user account in this column.

At first glance, determining the user account of a running process (actually, by the code in that process) would seem to be one of those single API calls you make into the dark recesses of the Windows operating system. Unfortunately (and known only to Microsoft), this is one of those areas where you have to make a series of cascading calls into various functions, but also be aware of some gotchas that may not be apparent. Interestingly enough, the newer Microsoft .NET framework that provides a more modern abstraction of the Windows SDK still requires knowledge of dependencies between calls and various situations that can trip up an intrepid programmer. Basically, this is one of those areas that you code, debug, test, and put away into your toolchest.

The first step is to determine who we are at the process level. Let’s look at some code:

	DWORD processId = GetCurrentProcessId();

	HANDLE processHandle = 
OpenProcess( PROCESS_QUERY_INFORMATION, FALSE,
processId);

We fetch our process ID and they query Windows for a handle to this process. This sets us up to ask more detailed information about the process:

	HANDLE tokenHandle = NULL;
	::OpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle);

The function OpenProcessToken is one of those massively over-designed functions scattered around the Win32 SDK—depending upon the value of the second parameter (in this case, TOKEN_QUERY), we receive a handle to a block of information that can be further queried. However, first we need to determine the size of the buffer that will receive the information. We do this by calling GetTokenInformation with a null buffer, which tells the function we only want the size that is needed:

	DWORD tokenUserLength = 0;
	DWORD returnLength = 0;

	::GetTokenInformation( tokenHandle, TokenUser, NULL, tokenUserLength, 
				&returnLength);

Now that we have the proper size, we can allocate some memory for the buffer and request that the information be copied into it:

	TOKEN_USER* pUserToken = 
static_cast<TOKEN_USER*>(new char[returnLength]);
	tokenUserLength = returnLength;
	::GetTokenInformation( tokenHandle, TokenUser, pUserToken,
 tokenUserLength, &returnLength);

OK, so at this point we have a pointer to a TOKEN_USER structure, which contains information we need to call yet another function to get the actual user account for this process.

We抣l continue in the next column with the final steps to move from this information to the actual account name and some potential gotchas. Everyone loves a cliffhanger, right?


Mark M. Baker is the Chief of Research & Development at BNA Software located in Washington, D.C.
Do you have a Windows development question? Send it to markbaker-winqa8364@mailblocks.com.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值