Здравствуйте! Постараюсь подробно описать всю суть проблема:
Под Win8 есть два пользователя, user1 (администратор) и user2(простой пользователь). Есть служба, работающая от user1. Что она делает? Она принимает через сокеты некоторые данные и запускает другую программу (proga.exe) от имени user2 с параметрами, полученными из сокетов. Далее, proga.exe создает в определенной директории файл со скриптом SHELL и запускает его. Что делает скрипт: создает несколько файлов txt (это выполняется успешно) и добавляет некоторые данные в БД Access через odbc (это не выполняется).
Причем записи в бд не пишутся только если proga.exe запущена из службы. Если готовый скрипт запустить из под user2, то данные записываются.
Из службы запускаю proga.exe процедурой RunAs, описание ниже
procedure StrResetLength(var S: AnsiString);
begin
SetLength(S, StrLen(PChar(S)));
end;
function GetUserObjectName(hUserObject: THandle): string;
var
Count: DWORD;
begin
// have the the API function determine the required string length
GetUserObjectInformation(hUserObject, UOI_NAME, PChar(Result), 0, Count);
SetLength(Result, Count + 1);
if GetUserObjectInformation(hUserObject, UOI_NAME, PChar(Result), Count, Count) then
StrResetLength(Result)
else
Result := '';
end;
function SetUserObjectFullAccess(hUserObject: THandle): Boolean;
var
Sd: PSecurity_Descriptor;
Si: Security_Information;
begin
Sd := PSecurity_Descriptor(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
InitializeSecurityDescriptor(Sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(Sd, True, nil, False);
Si := DACL_SECURITY_INFORMATION;
Result := SetUserObjectSecurity(hUserObject, Si, Sd);
LocalFree(HLOCAL(Sd));
end;
procedure RunAs(var UserDomain, UserName, Password, CommandLine: string);
const
Environment: PChar=nil;
// default values for window stations and desktops
CreateProcDEFWINSTATION = 'WinSta0';
CreateProcDEFDESKTOP = 'Default';
CreateProcDOMUSERSEP = '\';
var
ConsoleTitle: string;
Help: string;
WinStaName: string;
DesktopName: string;
hUserToken: THandle;
hWindowStation: HWINSTA;
hDesktop: HDESK;
StartUpInfo: TStartUpInfo;
ProcInfo: TProcessInformation;
Runned: boolean;
begin
// Step 2: logon as the specified user
if not LogonUser(PChar(UserName), PChar(UserDomain), PChar(Password),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hUserToken) then
log('ERROR LogonUser');
// Step 3: give the new user access to the current WindowStation and Desktop
hWindowStation:= GetProcessWindowStation;
WinStaName := GetUserObjectName(hWindowStation);
if WinStaName = '' then
WinStaName := CreateProcDEFWINSTATION;
if not SetUserObjectFullAccess(hWindowStation) then begin
CloseHandle(hUserToken);
// raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcSetStationSecurityError, [WinStaName]);
log('ERROR SetUserObjectFullAccess(hWindowStation');
end;
hDesktop := GetThreadDesktop(GetCurrentThreadId);
DesktopName := GetUserObjectName(hDesktop);
if DesktopName = '' then
DesktopName := CreateProcDEFDESKTOP;
if not SetUserObjectFullAccess(hDesktop) then begin
CloseHandle(hUserToken);
// raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcSetDesktopSecurityError, [DesktopName]);
log('ERROR SetUserObjectFullAccess(hDesktop)');
end;
// Step 4: set the startup info for the new process
ConsoleTitle := UserDomain + UserName;
FillChar(StartUpInfo, SizeOf(StartUpInfo), #0);
with StartUpInfo do begin
cb:= SizeOf(StartUpInfo);
lpTitle:= PChar(ConsoleTitle);
Help := WinStaName + '\' + DeskTopName;
lpDesktop:= PChar(Help);
end;
// Step 5: create the child process
Runned := CreateProcessAsUser(hUserToken, nil, PChar(CommandLine),
nil, nil, False, CREATE_NEW_CONSOLE or CREATE_NEW_PROCESS_GROUP,
Environment, nil, StartUpInfo, ProcInfo);
if(not(Runned)) then begin
case GetLastError of
ERROR_PRIVILEGE_NOT_HELD:
{raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcPrivilegesMissing,
[GetPrivilegeDisplayName(SE_ASSIGNPRIMARYTOKEN_NAME), SE_ASSIGNPRIMARYTOKEN_NAME,
GetPrivilegeDisplayName(SE_INCREASE_QUOTA_NAME), SE_INCREASE_QUOTA_NAME]); }
log('ERROR_PRIVILEGE_NOT_HELD :: ' + IntToStr(GetLastError));
ERROR_FILE_NOT_FOUND:
//raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcCommandNotFound, [CommandLine]);
log('ERROR_FILE_NOT_FOUND :: ' + IntToStr(GetLastError));
else
//raise EJclCreateProcessError.CreateResRec(@RsCreateProcFailed);
log('ERROR NUM :: ' + IntToStr(GetLastError));
end;
end;
// clean up
CloseWindowStation(hWindowStation);
CloseDesktop(hDesktop);
CloseHandle(hUserToken);
if Runned then begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;
Собственно, как сделать так, что бы запущенная из под службы proga.exe отработала нормально?
Уже много перепробовал, не понимаю, где еще искать ошибку.
Было подозрение, что у user1 не хватает каких то прав в "локальных политиках безопасности", пробовал давать ему самые различные права, ничего не помогло.