在写服务程序的过程,由于很多权限涉及到“域”,所以服务程序需要用“用户名”登录。
然后在WINDOWS的策略设置中,
“本地计算机”策略 - 计算机配置 - Windows 设置 - 安全设置 - 本地策略 - 用户权限
其中有这样一个策略设置“作为服务登录”。顾名思义,这里就是需要进行修改的地方。如果没有设置用户名,即使通过代码实现了服务程序安装,也无法成功启动服务程序。
以下是通过WIN32来实现的解决方案。
Code
#DEFINE _SERVICE_USERNAME _T("work\\pc8888")
//用于初始化字符串的函数
void InitLsaString(PLSA_UNICODE_STRING LsaString,LPWSTR String)
{
USHORT StringLength;
if (String == NULL){
LsaString->Buffer = NULL;
LsaString->Length = 0;
LsaString->MaximumLength = 0;
return;
}
StringLength = wcslen(String);
LsaString->Buffer = String;
LsaString->Length = StringLength * sizeof(WCHAR);
LsaString->MaximumLength = (StringLength + 1) * sizeof(WCHAR);
}
//主要函数
ULONG SetAcountRights()
{
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
DWORD dwSize = MAX_PATH;
WCHAR SystemName[MAX_PATH]; //系统名
ZeroMemory(SystemName,MAX_PATH);
GetComputerNameW(SystemName,&dwSize);//先获得计算机名
LSA_UNICODE_STRING lusSystemName;
NTSTATUS ntsResult;
LSA_HANDLE lsahPolicyHandle;
//初始化变量
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
InitLsaString(&lusSystemName,SystemName);
//打开LAS策略
ntsResult = LsaOpenPolicy(
&lusSystemName,
&ObjectAttributes,
POLICY_ALL_ACCESS,
&lsahPolicyHandle
);
if (ntsResult != STATUS_SUCCESS)
{
return LsaNtStatusToWinError(ntsResult);
}
//打开需要添加到“作为服务登录”的用户帐号所属SID
char szDomain[256];
DWORD dwcbName = 0,
dwcbDomain = sizeof(szDomain);
SID_NAME_USE SNU;
PSID pSid;
//第一次打开只是为了获得数据长度
if (! LookupAccountName(NULL, _SERVICE_USERNAME, NULL, &dwcbName, szDomain,
&dwcbDomain, &SNU))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return GetLastError();
}
pSid = new BYTE[dwcbName];
if (! LookupAccountName(NULL, _SERVICE_USERNAME, pSid, &dwcbName, szDomain,
&dwcbDomain, &SNU))
{
return GetLastError();
}
}
else
{
return GetLastError();
}
//初始化需要添加的权限
LSA_UNICODE_STRING lus[1];
InitLsaString(&lus[0],L"SeServiceLogonRight");
//执行权限添加
ntsResult =LsaAddAccountRights(
lsahPolicyHandle,
pSid,
lus,
1);
if (ntsResult != STATUS_SUCCESS)
{
return LsaNtStatusToWinError(ntsResult);
}
else
{
return ERROR_SUCCESS;
}
}