Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сервис не ShutDownит сервер с выданными привилегиями. [D6, NT4, Win2k, WinXP]


Страницы:   1 2

Kacnep ©   (2006-08-25 07:45:00) 

Ув. мастера! Сервис по приходу некой команды из сети должен выполнить *.cmd файл. Вот что например
c:\adm\ss.cmd
shutdown /s /f >c:\adm\log.txt
т.е. выключить сервер, но этого не происходит.
Сам командник запускается! Файл log.txt появляется.
Привелегии необходимые вроде бы выдал - не уверен что в том месте программы.
Сервис запускается как Local System.
Может кто нить что подсказать (сервера 2000 и 2003).
Я рассматривал пример
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1147525423&n=5 Вот куски кода...

....

procedure AdjTokenPrivelegs(mmName: string);
var
 gler: DWord;
begin
 AdjustPriviliges(mmName);
 gler:=GetLastError;
 if (glerERROR_SUCCESS) then begin
   WriteLog(Format('%s: [FAILED] ', [mmName]));
{$IFDEF _DEV_}
   ShowError(gler);
{$ENDIF}
   exit;
 end;
 WriteLog(Format('%s: [OK] ', [mmName]));
end;

procedure Tf_Main.ServiceStart(Sender: TService; var Started: Boolean); //эта штука при старте сервера - тут и выдаю привилегии
var
 sl_Tmp:TStringList;
 s:string;
 i:integer;
begin
 Started:=FALSE;
 AdjTokenPrivelegs(SE_SHUTDOWN_NAME); //выдаем ЭТУ ТОЧНО ПРИВИЛЕГИЮ!!!
 AdjTokenPrivelegs(SE_DEBUG_NAME);
 WriteLog('Service is starting... ');

 if not StartServer then
   WriteLog('Error starting server')
 else WriteLog('Server started successfully!');
 WriteLog('Service is started.');

 Started:=TRUE;
end;

....

procedure Tf_Main.id_SrvCommandHandlers0Command(ASender: TIdCommand); //это по приходу команды из сети использую компонент инди
var
 PMSI:TStartupInfo;
 PMPI:TProcessInformation;
begin
 WriteLog(ASender.Context.Connection.Socket.Binding.PeerIP+' -> Shutdown');
 if (FIP.Count>0) and (FIP.IndexOf(ASender.Context.Connection.Socket.Binding.PeerIP)>-1) then begin
   WriteLog('Execute Shutdown! '+FScript);
   FillChar(PMSI,sizeof(PMSI),0);
   PMSI.cb:=sizeof(PMSI);
   FillChar(PMPI,sizeof(PMPI),0);
   try
     try      //Win32Check(
       if not CreateProcess(nil,PChar(FScript),nil,nil,true,0,{false,normal_priority_class,}ni l,nil,PMSI,PMPI) then RaiseLastWin32Error;
     except
       WriteLog('Error: '+SysErrorMessage(GetLastError));
     end;
   finally
     CloseHandle(PMPI.hProcess);
     CloseHandle(PMPI.hThread);
   end;
 end;//if
end;


Kacnep   (2006-09-01 10:15:00) [1]

Проблема до сих пор не снята. :(
Например выполняю команду в скрипте c:\windows\system32\shutdown.exe /? >c:\log.txt
Делаю логофф.
По шедулеру отрабатывает нормально. В лог.тхт хелп есть.
С помощью сервиса - длина файла лог.тхт =0 :( т.е. инфы в нем никакой нет.
Вывод - почему то не работает корректно процедура создания процесса :(
Полностью код всего проекта выложен выше.
Может кто нить сможет помочь? :(


Kacnep   (2006-08-29 10:54:00) [2]

Установлена :((
НИКАКОЙ щатдаун если незалогинен не работает! :(
НИКАК!
Кажеться BiN ©   (28.08.06 12:44) [29]  прав.
На 2003 надо ставить какой то ХОТФИКС а на 2000?
Но главное выяснил - в процедуре выдачи прав - все верно. Значит приджется искать шатдаунитель нормальный %((.


umbra   (2006-08-28 20:10:00) [3]


>
> Если незалогинен то шедулер запускает скрипт но ТОЛЬКО НЕ
> ШАТДАУН!!!
>

Это настройка безопасности. Запустите из командной строки gpedit.mscи сделайте Enabledопцию Local computer policy\Computer Configuration\Security Settings\Local Policies\Security Options\Shutdown: Allow the system to be shut down without having to log on(Вин2003Сервер). По умолчанию запрещено гасить компьютер, если нет интерактивных сессий.


BiN   (2006-08-28 12:44:00) [4]


> Если незалогинен то шедулер запускает скрипт но ТОЛЬКО НЕ
> ШАТДАУН!!!
> Все остальное отрабатывает...:(((


Ты по ссылке в BiN ©   (25.08.06 12:19) [14] ходил?


Kacnep   (2006-08-28 12:38:00) [5]

2 Ketmar
На всех серверах разные пароли и вшивать в прогу и каждый раз перекомпилить - не выход :(( В отдельном файле держать в незашифрованом виде нельзя :(.
Т.е. ЛОГОН кажеться никак применить тут нельзя... :(

2 BiN
Фантастика
Если я залогинен на сервер
то такой скрипт выполняеться
@echo time /t >c:\adm\start.log
ping 172.31.32.100 >c:\adm\ping.log
@echo time /t >c:\adm\stop.log
shutdown /r /f >c:\adm\s.log


Если незалогинен то шедулер запускает скрипт но ТОЛЬКО НЕ ШАТДАУН!!!
Все остальное отрабатывает...:(((


BiN   (2006-08-28 12:18:00) [6]


> Ketmar ©   (28.08.06 12:05) [26]

Сусанин, блин.
-)


Ketmar   (2006-08-28 12:05:00) [7]

> [25] BiN ©   (28.08.06 12:02)
ну не мешай, а? я тут так подло толкаю в сторону дебрей логина, а ты весь кайф ломаешь... %-)


BiN   (2006-08-28 12:02:00) [8]


> Kacnep ©   (28.08.06 11:54) [23]


Попробуй запустить скрипт шедулером. Если не вызывается, то проблема в скрипте или в ошибке системы. В этом случае нужно копать мс-овский технет.

Кстати, думаю, shutdown самостоятельно включает нужные привилегии.


Ketmar   (2006-08-28 11:58:00) [9]

цитата:
The LogonUser function attempts to perform a user logon operation. You specify the user with a user name and domain, and authenticate the user with a clear-text password. If the function succeeds, you receive a handle to a token that represents the logged-on user. You can then use this token handle to impersonate the specified user, or in most cases, to create a process running in the context of the specified user.
логинься себе под админом и запускай под ним всё, что угодно.


Kacnep   (2006-08-28 11:54:00) [10]

:((
к сожалению не хочу...
Мне ВАЖНОчтоб ЛЮБАЯпрограмма прописаная в файле  "скрипта" нормально выполнялась. И ВОЗМОЖНО! потом шатдаун! Я например на критичных серваках просто остановлю и корректно завершу работу баз. Бэкапов и прочее. Это все я в скрипте пропишу! Вот для чего он нужен. А потом могу и шатдаунить спокойно. НО ЭТОТ ПРОЦЕСС!! будь он неладен :( не хочет ДАЖЕ шатдаун выполнить по всем рекомендациям Мастеров и хелпам инета. :(.
Сейчас работает примитивно - в скрипте запускает тупо утилитку psshutdown - она пробивает любую операционку (на 2000 shutdownа нет :( ).
Но я хочу добить - понятьпочему то, что по всем понятиям ДОЛЖНО работать - не работает :((.
Куча рассматриваемых вопросов в инете как зашатдаунить тачку в НТ. ВСЕ! копия моего (вернее наоборот) у них только после запуска процесса стоит дельфийская команда шатдауна :(. И видимо все работает - почему мой скрипт выполняющий стандартную команду шатдауна НА НЕЗАЛОГИНЕНОМ сервере не выполняется :(.


BiN   (2006-08-28 11:41:00) [11]

А без вызова shutdown.exe обойтись не хочешь? Например вызвать ExitWindowsEx или InitiateSystemShutdown(Ex)


Kacnep   (2006-08-28 11:19:00) [12]

ДА! Все работает! И мало того скажем если я в файле ss.cmd (запускаемый сервисом скрипт) например пишу ping 127.0.0.1 >c:\adm\log.txt -в логе нормано вижу что команда пинг отработала. Сервис работает!!! Но когда на тачке никто не залогинен команда shutdown -r не работает! :((. Уже бесит этот кусок. :(
За замечания спасибо. Просто еще в коде много лишней отладочной инфы которая пишется в лог только для проверки.
Вот что например сейчас в ЛОГе
[28.08.2006 12:09:38] Service is stoping...
[28.08.2006 12:09:38] Server stoped [OK]
[28.08.2006 12:09:38] Service stoped [OK]
[28.08.2006 12:09:38] Service uninstall [OK]
[28.08.2006 12:09:53] Service is starting...
[28.08.2006 12:09:53] Server starting...
[28.08.2006 12:09:53] Server started [OK]
[28.08.2006 12:09:53] Service started [OK]
[28.08.2006 12:10:22] 172.31.39.233 -> Shutdown
[28.08.2006 12:10:22] Execute Shutdown! C:\ADM\ss.cmd
[28.08.2006 12:10:22] Create suspend process [OK]
[28.08.2006 12:10:22] SetProcessTokenPrivilege: The operation completed successfully
[28.08.2006 12:10:22] ResumeThread: The operation completed successfully


BiN   (2006-08-28 11:12:00) [13]


> Kacnep ©   (28.08.06 10:57) [19]

А можно узнать, что требуется ещеот сообщества? Код что ли с нуля написать?

PS
GetLastError имеет смысл проверять только при неудачном выполнении функции (это я про вызов SetProcessTokenPrivilege)
PPS
"Простой" процесс, который только и делает, что пишет о себе в лог, создавать пробовал?


Kacnep   (2006-08-28 10:57:00) [14]

:) Утром добрым... :)
Нет народ - это для облегчения моего гемороя :).
Если я доделаю этот сервис - то его скопировать и запустить на все серваки а их ооочень много :) не составит большого труда. А ЕСЛИ НЕТ... Придется официальный софт от производителся ставить и настраивать на каждой машине... ЭЭтого я вынести не смогу! :(((

А код - просто вставляеться в соответствующие файлы и компилиться -получаем готовый проект. Который уже можно просматривать. Вернее кажеться собака зарыта только в ф-ии создания процесса. Так сказать "код в студию".

Сейчас лазию по инету ищу примеры написания РАБОТАЮЩИХ сервисов.
Но все же основная надежда на Мастеров...


Ketmar   (2006-08-28 10:10:00) [15]

* Кэтмар у утреннем настроении *
нет, я, конечно, всё понимаю, но ему за это, небось, денег платят, а мы тут так, забесплатно должны кучу кода читать...


Kacnep   (2006-08-28 08:23:00) [16]

u_Main5.pas

unit u_Main5;

interface

uses
 Windows,
 Messages,
 SysUtils,
 Classes,
 SvcMgr,
 IniFiles,
 IdCmdTCPServer,IdCommandHandlers, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer;

type
 Tf_Main = class(TService)
   id_Srv: TIdCmdTCPServer;
   procedure id_SrvCommandHandlers0Command(ASender: TIdCommand);
   procedure ServiceStart(Sender: TService; var Started: Boolean);
   procedure ServiceStop(Sender: TService; var Stopped: Boolean);
   procedure ServiceCreate(Sender: TObject);
   procedure ServiceDestroy(Sender: TObject);
 private
   FIP:TStringList;
   FScript:string;
   function StartServer: Boolean;
   function StopServer: Boolean;
   { Private declarations }
 public
   function GetServiceController: TServiceController; override;
   { Public declarations }
 end;

const
 c_Log='Service.log';
 c_Ini='settings.ini';

var
 f_Main: Tf_Main;

implementation

{$R *.DFM}

uses
 ShellAPI;

var
 CreateOptScan: LongWord;
 Log,Ini:TFileName;
 hLog: THandle;

 function WriteLog(Status: string): DWord; forward;

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
 f_Main.Controller(CtrlCode);
end;

function Tf_Main.GetServiceController: TServiceController;
begin
 Result := ServiceController;
end;

function SetTokenPrivilege(hToken: THandle; const PrivilegeName:string; NewState: DWORD; PreState: PDWORD=nil): Boolean;
var
 LUID : TLargeInteger;
 Privilege, PrevPrivilege: TTokenPrivileges;
 cbPrevPriv:DWORD;
begin
 Result:= False;
 if LookupPrivilegeValue (nil,PChar(PrivilegeName),LUID) then begin
   Privilege.PrivilegeCount:=1;
   Privilege.Privileges[0].Luid:=LUID;
   Privilege.Privileges[0].Attributes:=NewState;
   cbPrevPriv:=SizeOf(PrevPrivilege);
   Result:=AdjustTokenPrivileges(hToken, False, Privilege, cbPrevPriv, Privilege, cbPrevPriv);
   if (Result and Assigned(PreState)) then PreState^:=PrevPrivilege.Privileges[0].Attributes;
 end;
end;

function SetProcessTokenPrivilege(hProcess:DWORD; const PrivilegeName:string;NewState: DWORD; PreState: PDWORD=nil): Boolean;
var
 hToken : THandle;
begin
 Result:= False;
 if not OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken) then begin
   WriteLog('OpenProcessToken [Fail]');
   Exit;
 end;
 Result:=SetTokenPrivilege(hToken, PrivilegeName, NewState, PreState) and (GetLastError=ERROR_SUCCESS);
 CloseHandle (hToken);
end;

procedure Tf_Main.id_SrvCommandHandlers0Command(ASender: TIdCommand);
const
 PrivelegStr='SeShutdownPrivilege';
var
 PMSI:TStartupInfo;
 PMPI:TProcessInformation;
 env:array[0..100] of char;
begin
 WriteLog(ASender.Context.Connection.Socket.Binding.PeerIP+' -> Shutdown');
 if (FIP.Count>0) and (FIP.IndexOf(ASender.Context.Connection.Socket.Binding.PeerIP)>-1) then begin
   WriteLog('Execute Shutdown! '+FScript);
   ZeroMemory(@env,sizeof(env));
   ZeroMemory(@PMSI,sizeof(PMSI));
   ZeroMemory(@PMPI,sizeof(PMPI));
   PMSI.cb:=sizeof(PMSI);
   try
     try
       Win32Check(CreateProcess(nil,PChar(FScript),nil,nil,true,CREATE_SUSPENDED,@env,P Char('C:\'),PMSI,PMPI));
       WriteLog('Create suspend process [OK]');
       SetProcessTokenPrivilege(PMPI.hProcess,PChar(PrivelegStr),SE_PRIVILEGE_ENABLED);
       WriteLog('SetProcessTokenPrivilege: '+SysErrorMessage(GetLastError));
       if GetLastError=ERROR_SUCCESS then begin
         ResumeThread(PMPI.hThread);
         WriteLog('ResumeThread: '+SysErrorMessage(GetLastError));
       end;
     except
       WriteLog('Error: '+SysErrorMessage(GetLastError));
     end;
   finally
     CloseHandle(PMPI.hProcess);
     CloseHandle(PMPI.hThread);
   end;
 end;//if
end;

function Tf_Main.StopServer: Boolean;
begin
 id_Srv.Active:=false;
 Result:=not id_Srv.Active;
 if result then WriteLog('Server stoped [OK]')
 else WriteLog('Server stoped [Fail]');
end;

function Tf_Main.StartServer: Boolean;
begin
 id_Srv.DefaultPort:=9999;
 try
   WriteLog('Server starting...');
   id_Srv.Active:=true;
   result:=id_Srv.Active;
 except
   on E : Exception do begin
     WriteLog('Server start [Fail]');
     WriteLog(E.Message);
     Result:=false;
   end;
 end;
end;

procedure Tf_Main.ServiceStart(Sender: TService; var Started: Boolean);
var
 sl_Tmp:TStringList;
 s:string;
 i:integer;
begin
 Started:=FALSE;
 Ini:=ExtractFilePath(paramstr(0))+c_Ini;
 Log:=ExtractFilePath(paramstr(0))+c_Log;
 WriteLog('Service is starting... ');
 FIP:=TStringList.Create;
 sl_Tmp:=TStringList.Create;
 try
   with TIniFile.Create(Ini) do begin
     FScript:=ReadString('Script','File','');
     ReadSection('IPs',sl_Tmp);
     for i:=0 to sl_Tmp.Count-1 do begin
       s:=trim(ReadString('IPs',sl_Tmp.Strings[i],''));
       if s<>'' then FIP.Add(s);
     end;
     Free;
   end;// WIth
 finally
   FreeAndNil(sl_Tmp);
 end;
 if not StartServer then begin
   WriteLog('Server start [Fail]');
   Started:=False;
 end
 else begin
   WriteLog('Server started [OK]');
   WriteLog('Service started [OK]');
   Started:=TRUE;
 end;
end;

procedure Tf_Main.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
 WriteLog('Service is stoping... ');
 if not StopServer then WriteLog('Server stop [Fail]');
 FreeAndNil(FIP);
 WriteLog('Service stoped [OK]');
 Stopped:=TRUE;
end;

procedure Tf_Main.ServiceCreate(Sender: TObject);
begin
 if sysutils.Win32Platform=VER_PLATFORM_WIN32_NT then CreateOptScan:=FILE_FLAG_SEQUENTIAL_SCAN
 else CreateOptScan:=0;
end;

function WriteLog(Status: string): DWord;
var
 xBuf: array[0..$FF - 1] of Char;
begin
 if (hLog = INVALID_HANDLE_VALUE) or (hLog = 0) then begin
   if FileExists(Log) then
     hLog := CreateFile(PChar(Log),
       GENERIC_READ or GENERIC_WRITE,
       FILE_SHARE_READ,
       nil,
       OPEN_EXISTING,
       FILE_ATTRIBUTE_NORMAL or CreateOptScan,
       0)
   else
     hLog := CreateFile(PChar(Log),
       GENERIC_READ or GENERIC_WRITE,
       FILE_SHARE_READ,
       nil,
       CREATE_ALWAYS,
       FILE_ATTRIBUTE_NORMAL or CreateOptScan,
       0);
  if hLog = INVALID_HANDLE_VALUE then begin
    Result := DWord(-1);
    exit;
  end;
  FileSeek(hLog, 0, 2);
 end;
 FillChar(xBuf, $FF, 0);
 Status := Format('[%s] %s'#13#10, [DateTimeTostr(Now), Status]);
 move((Pointer(@Status[1]))^, xBuf, Length(Status));
 FileWrite(hLog, xBuf, Length(Status));
 FlushFileBuffers(hLog);
 Result := 0;
end;

procedure Tf_Main.ServiceDestroy(Sender: TObject);
begin
 WriteLog('Service uninstall [OK]');
 CloseHandle(hLog);
end;

end.


Kacnep   (2006-08-28 08:22:00) [17]

Пока не получилось вроде применял все рекомендации.
Вот ВСЕ исходники... Может кто поможет...
Прогу компилим
запускаем сначала с параметром /install - устанавливаем как сервис {убрать соответственно параметром /uninstall}
в папке с прогой должен быть инишник
В нем первый параметр - какой скрипт и откуда запускать
Второй параметр с какого ИП разрешено принимать команды.
После СТАРТА сервиса запускаем телнет на порт 9999 и просто посылаем команду shutdown.
Клиент сразу отцепиться а на серваке {2003 или ХР есть команда SHUTDOWN} должен выполниться Ваш скрипт.
Я буду еще искать решение проблемы. Но буду благодарен любому кто укажет где в программе ошибка. Спасибо.

settings.ini
[Script]
File=C:\Adm\ss.cmd
[IPs]
IP1=172.31.34.152
IP2=127.0.0.1


ss.cmd
shutdown -r -f

u_Main5.dfm

object f_Main: Tf_Main
 OldCreateOrder = False
 OnCreate = ServiceCreate
 OnDestroy = ServiceDestroy
 AllowPause = False
 DisplayName = 'Ups_Listener'
 OnStart = ServiceStart
 OnStop = ServiceStop
 Left = 321
 Top = 150
 Height = 150
 Width = 215
 object id_Srv: TIdCmdTCPServer
   Bindings = <>
   DefaultPort = 9999
   TerminateWaitTime = 2000
   CommandHandlers = <
     item
       CmdDelimiter = ' '
       Command = 'SHUTDOWN'
       Disconnect = True
       Name = 'ch_ShutDown'
       NormalReply.Code = '200'
       ParamDelimiter = ' '
       Tag = 0
       OnCommand = id_SrvCommandHandlers0Command
     end>
   ExceptionReply.Code = '500'
   ExceptionReply.Text.Strings = (
     'Unknown Internal Error')
   Greeting.Code = '200'
   Greeting.Text.Strings = (
     'Welcome')
   HelpReply.Code = '100'
   HelpReply.Text.Strings = (
     'Help follows')
   MaxConnectionReply.Code = '300'
   MaxConnectionReply.Text.Strings = (
     'Too many connections. Try again later.')
   ReplyTexts = <>
   ReplyUnknownCommand.Code = '400'
   ReplyUnknownCommand.Text.Strings = (
     'Unknown Command')
   Left = 28
   Top = 26
 end
end


Kacnep   (2006-08-25 12:22:00) [18]

Стоп!
А насчет Гашения базы.
В Оракле пользователькоторый может погасить "интерактивно" базу должен принадлежать группе ORA_DBA точно не помню...
Как Мной запущеный процесс поступит?
Или когда я говорю что процесс может шатдаунить машину ему выдаются привелегии АДМИНА который обладает правом ORA_DBA???


BiN   (2006-08-25 12:19:00) [19]


> Kacnep ©   (25.08.06 12:05) [10]
>
> так попорядку от простого к сложному...
> 2 BiN ©   (25.08.06 11:48) [9]
> Мало того! На него никто и не заходил после перезагрузки!
>  Установили сервис запустили в авто и ребутанули! Цель чтобы
> сервис уже работал (и он работает) и ожидал команды!

Ок. Просто имей ввиду http://support.microsoft.com/?id=821287
Теперь по коду.
Запусти CreateProcess с флагом CREATE_SUSPENDED, а после установки привилегии возобнови работу с пом. ResumeThread.
Мелкое замечание по
 finally
        // Cannot test the return value of AdjustTokenPrivileges.
        if (GetLastError <> ERROR_SUCCESS) then raise Exception.Create('AdjustTokenPrivileges enable failed');
        CloseHandle(hTok);
      end

CloseHandle(hTok) должен стоять до возбуждения исключения.

Вот протестированная функция включения/выключения привилегий
function SetTokenPrivilege(hToken: THandle; const PrivilegeName:string;
                          NewState: DWORD; PreState: PDWORD=nil): Boolean;
var
 LUID : TLargeInteger;
 Privilege, PrevPrivilege: TTokenPrivileges;
 cbPrevPriv:DWORD;
begin
 Result:= False;
 if LookupPrivilegeValue (nil, PChar (PrivilegeName), LUID) then
 begin
   Privilege.PrivilegeCount:=1;
   Privilege.Privileges[0].Luid:=LUID;
   Privilege.Privileges[0].Attributes:=NewState;
   cbPrevPriv := SizeOf (PrevPrivilege);
   Result:= AdjustTokenPrivileges(hToken, False, Privilege, cbPrevPriv, Privilege, cbPrevPriv);
   if Result and Assigned(PreState)
   then PreState^:=PrevPrivilege.Privileges[0].Attributes;
 end;
end;

// NewState - SE_PRIVILEGE_ENABLED или 0

function SetProcessTokenPrivilege(hProcess:DWORD; const PrivilegeName:string;
                          NewState: DWORD; PreState: PDWORD=nil): Boolean;
var
 hToken : THandle;
begin
 Result:= False;
 if not OpenProcessToken(hProcess,
                     TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
                     hToken)
 then Exit;
 Result:=SetTokenPrivilege(hToken, PrivilegeName, NewState, PreState) and
         (GetLastError()=ERROR_SUCCESS);
 CloseHandle (hToken);
end;


Kacnep   (2006-08-25 12:17:00) [20]

Спасибо Мастера! Все советы попробую!


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо