информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяЗа кого нас держат?Страшный баг в Windows
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[Win32 Delphi 5] У кого мозги не засохли — нужна помощь ;-) 19.10.02 19:21  
Автор: HandleX <Александр М.> Статус: The Elderman
Отредактировано 19.10.02 19:47  Количество правок: 3
<"чистая" ссылка>
Не понимаю, почему я не могу взять строки lpRebootMsg или lpCommand из структуры... Это указатель, но указывает на какую-то хрень... Помогите, pls...
Прогу наваял специально для тестирования этого случая, думаю проблем скомпилить не составит, у кого Delphi 5.


program Main;
{$APPTYPE CONSOLE}
uses
  SysUtils, Windows, WinSvc;

  Function forCons(aStr: String): String;
  Begin
    Result := aStr; UniqueString(Result);
    ANSItoOEM(PChar(Result), PChar(Result));
  End;

  Function QueryServiceConfig2A(
    hService: SC_HANDLE;   // handle to service
    dwInfoLevel: DWORD;    // information level
    lpInfo: Pointer;       // new data
    cbBufSize: DWORD;      // size of buffer
    Var pcbBytesNeeded: DWORD // bytes needed
  ): BOOL; StdCall; External AdvApi32;

Type
  _SERVICE_DESCRIPTION = Record
    lpDescription: LPTSTR;
  End;
  SERVICE_DESCRIPTION = _SERVICE_DESCRIPTION;
  PSERVICE_DESCRIPTION = ^SERVICE_DESCRIPTION;

  _SC_ACTION_TYPE = (SC_ACTION_NONE, SC_ACTION_RESTART, SC_ACTION_REBOOT, SC_ACTION_RUN_COMMAND);
  SC_ACTION_TYPE = _SC_ACTION_TYPE;

  _SC_ACTION = Record
    aType: SC_ACTION_TYPE;
    Delay: DWORD;
  End;
  TSC_ACTION = _SC_ACTION;
  PSC_ACTION = ^TSC_ACTION;

  TSC_ACTION_Array = Array[0..0] Of TSC_ACTION;
  PSC_ACTION_Array = ^TSC_ACTION_Array;

  _SERVICE_FAILURE_ACTIONS = Record
    dwResetPeriod: DWORD;
    lpRebootMsg: LPTSTR;
    lpCommand: LPTSTR;
    cActions: DWORD;
    lpsaActions: PSC_ACTION_Array;
  End;
  TSERVICE_FAILURE_ACTIONS = _SERVICE_FAILURE_ACTIONS;
  PSERVICE_FAILURE_ACTIONS = ^TSERVICE_FAILURE_ACTIONS;

Const
  SERVICE_CONFIG_DESCRIPTION = 1;
  SERVICE_CONFIG_FAILURE_ACTIONS = 2;

  ActionTypeStrings: Array[SC_ACTION_NONE..SC_ACTION_RUN_COMMAND] Of String = (
    'SC_ACTION_NONE', 'SC_ACTION_RESTART', 'SC_ACTION_REBOOT', 'SC_ACTION_RUN_COMMAND'
  );

  Function GetServiceDescription(sHndl: THandle): String;
  Var
    BytesNeeded: DWord;
    OutBuff: PSERVICE_DESCRIPTION;
  Begin
    QueryServiceConfig2A(sHndl, SERVICE_CONFIG_DESCRIPTION, Nil, 0, BytesNeeded);
    If GetLastError <> ERROR_INSUFFICIENT_BUFFER Then
      RaiseLastWin32Error;
    GetMem(OutBuff, BytesNeeded);
    Try
      Win32Check(QueryServiceConfig2A(sHndl, SERVICE_CONFIG_DESCRIPTION, OutBuff, BytesNeeded, BytesNeeded));
      Result := OutBuff.lpDescription;
    Finally
      FreeMem(OutBuff);
    End;
  End;

  Function GetServiceFailureActions(sHndl: THandle): PSERVICE_FAILURE_ACTIONS;
  Var
    BytesNeeded: DWord;
  Begin
    QueryServiceConfig2A(sHndl, SERVICE_CONFIG_DESCRIPTION, Nil, 0, BytesNeeded);
    If GetLastError <> ERROR_INSUFFICIENT_BUFFER Then
      RaiseLastWin32Error;
    GetMem(Result, BytesNeeded);
    Try
      Win32Check(QueryServiceConfig2A(sHndl, SERVICE_CONFIG_FAILURE_ACTIONS, Result, BytesNeeded, BytesNeeded));
    Except
      FreeMem(Result);
      Raise;
    End;
  End;

Var
  scHndl, sHndl: THandle;
  anActions: PSERVICE_FAILURE_ACTIONS;
  J: Integer;
begin
  Try
    WriteLn;
    WriteLn('Hello, this test application will show work of some API functions, wait...');
    Write('Try to open SC Manager...');
    scHndl := OpenSCManager(Nil, Nil, MAXIMUM_ALLOWED);
    Win32Check(scHndl <> 0);
    Try
      WriteLn('Ok');

      Write('Try to open "WinMgmt" Service...');
      sHndl := OpenService(scHndl, 'WinMgmt', MAXIMUM_ALLOWED);
      Win32Check(sHndl <> 0);
      Try
        WriteLn('Ok');

        Write('Getting Service Description...');
        WriteLn('Ok'#$A'Service Description is: "' + forCons(GetServiceDescription(sHndl)) + '";');

        Write('Getting Service Failure Actions...');

        anActions := GetServiceFailureActions(sHndl);
        Try
          WriteLn('Ok');

          If anActions = Nil Then
            Raise EAbort.Create('Very strange error... Exiting!');

          WriteLn('Reset Period, seconds: ', anActions.dwResetPeriod);
          WriteLn('Reboot message: "', String(anActions.lpRebootMsg), '";');
          WriteLn('Command action: "', String(anActions.lpCommand), '";');
          WriteLn('Actions count: ', anActions.cActions, ';');

          For J := 0 To anActions.cActions - 1 Do
          Begin
            WriteLn;
            WriteLn(J, ' action type: ', ActionTypeStrings[anActions.lpsaActions[J].aType]);
            WriteLn(J, ' action delay, msec: ', anActions.lpsaActions[J].Delay);
          End;

          WriteLn;
          WriteLn('End of actions enumeration.');

        Finally
          FreeMem(anActions);
        End;
      Finally
        CloseServiceHandle(sHndl);
      End;
    Finally
      CloseServiceHandle(scHndl);
    End;

  Except
    on E: Exception Do
    Begin
      WriteLn; WriteLn;
      If E Is EAbort Then WriteLn(forCons(E.Message))
      Else Begin
        WriteLn('Exception occured, apllication will be terminated!');
        WriteLn('Exception class: "' + E.ClassName + '";');
        WriteLn('Exception message: "' + ForCons(E.Message) + '".');
      End;
    End;
  End;

  Write('Press Enter to exit...');
  ReadLn;
end.

---
Тестировать надо под Win2k, что понятно ввиду специфики API. Нужно открыть консоль MMC, для сервиса «Инструментарий управления Windows», выбрать вкладку «Восстановление», потом сказать, что при последующих сбоях надо перезагружать компьютер, нажать на кнопку «Параметры перезагрузки компьютера», там закрыжить, что нужно слать сообщение, и набрать некое сообщение. После чего запустить прогу.

К сожалению, не могу добиться того, чтобы извлечь это сообщение программно.
Всем заранее огромное спасибо!
Всем спасибо за мозговой штурм, сам разобрался. ;-) и вам на заметку — ansi версия queryserviceconfig2a работает криво при вызове с параметром service_config_failure_actions. не конвертит, сволочь уникод в анси, да и ладно, а то ещё и память портит! ;-) 20.10.02 13:34  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка>
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach