Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 23.01.2022, 09:46
frkbvfnjh frkbvfnjh вне форума
Прохожий
 
Регистрация: 18.10.2011
Сообщения: 12
Репутация: 10
По умолчанию QueryServiceLockStatus

Всем привет! Мучаюсь уже не первый день. Никак не могу найти в сети пример использования функции QueryServiceLockStatus на Delphi. Вроде как есть примеры на C++, в этом языке я вообще 0, но как мне кажется параметры этой функции там объявлены иначе. Причем прецедент уже был со стороны Delphi - в этом же модуле функция EnumServicesStatus так же была объявлена с ошибкой и в новых версиях Delphi ее исправили, видимо и с этой тоже самое. Я попытался написать обёртку для этой функции:

Код:
function IsLockServiceDatabase(
  out ErrCode: Integer;
  out LockOwner: string;
  out LockDuration: Cardinal
): Boolean;
var
  hSCManager: SC_HANDLE;
  BufSize, BytesNeeded: DWORD;
  //Buffer: PByte;
  LockStatus: QUERY_SERVICE_LOCK_STATUS;
begin
  Result := False;
  ErrCode := ERROR_SUCCESS;
  LockOwner := '';
  LockDuration := 0;

  hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCManager > 0 then
  try
    BufSize := 0;
    BytesNeeded := 0;

    if not QueryServiceLockStatus(
      hSCManager,
      LockStatus,
      BufSize,
      BytesNeeded
    ) and (GetLastError() = ERROR_INSUFFICIENT_BUFFER) then
    begin
      BufSize := BytesNeeded;
      //GetMem(Buffer, BytesNeeded);
      try
        if QueryServiceLockStatus(
          hSCManager,
          LockStatus,
          BufSize,
          BytesNeeded
        ) then
        begin
          Result := not (LockStatus.fIsLocked = 0);
          if Result then
          begin
            LockOwner := LockStatus.lpLockOwner;
            LockDuration := LockStatus.dwLockDuration;
          end;
        end else
          ErrCode := GetLastError();
      finally
        //FreeMem(Buffer);
      end;
    end;
  finally
    CloseServiceHandle(hSCManager);
  end else
    ErrCode := GetLastError();
end;

но когда я вызываю QueryServiceLockStatus второй раз то меняется значение в переменной BufSize, видимо где-то затирается память. Кроме того теряется весь смысл получения размера для буфера данных, ведь в Delphi 2-ой параметр в этой функции не объявлен как указатель, в С++ это как раз указатель на буффер в памяти. Я попытался переопределить описание функции:

Код:
function QueryServiceLockStatus(hSCManager: SC_HANDLE;
  var lpLockStatus: PByte; cbBufSize: DWORD;
  pcbBytesNeeded: PDWORD): BOOL; stdcall;
  function QueryServiceLockStatus; external advapi32 name 'QueryServiceLockStatusW';

function IsLockServiceDatabase(
  out ErrCode: Integer;
  out LockOwner: string;
  out LockDuration: Cardinal
): Boolean;
var
  hSCManager: SC_HANDLE;
  BufSize, BytesNeeded: DWORD;
  Buffer: PByte;
  lpLockStatus: LPQUERY_SERVICE_LOCK_STATUSW; //QUERY_SERVICE_LOCK_STATUS;
begin
  Result := False;
  ErrCode := ERROR_SUCCESS;
  LockOwner := '';
  LockDuration := 0;

  hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCManager > 0 then
  try
    BufSize := 0;
    BytesNeeded := 0;

    if not QueryServiceLockStatus(
      hSCManager,
      Buffer, //lpLockStatus,
      BufSize,
      @BytesNeeded
    ) and (GetLastError() = ERROR_INSUFFICIENT_BUFFER) then
    begin
      BufSize := BytesNeeded;
      GetMem(Buffer, BytesNeeded);
      try
        if QueryServiceLockStatus(
          hSCManager,
          Buffer, //lpLockStatus,
          BufSize,
          @BytesNeeded
        ) then
        begin
          Result := not (LPQUERY_SERVICE_LOCK_STATUSW(Buffer)^.fIsLocked = 0);
          if Result then
          begin
            LockOwner := LPQUERY_SERVICE_LOCK_STATUSW(Buffer)^.lpLockOwner;
            LockDuration := LPQUERY_SERVICE_LOCK_STATUSW(Buffer)^.dwLockDuration;
          end;
        end else
          ErrCode := GetLastError();
      finally
        FreeMem(Buffer);
      end;
    end;
  finally
    CloseServiceHandle(hSCManager);
  end else
    ErrCode := GetLastError();
end;

Все компилится, по при выполнении падает в виолейшин.

Может кто нибудь привести объяснить и привести пример кода, как правильно работать с этим зверем? Код пишу в Delphi 10.4, одна из последних версий. Ооооочень нужна помощь. Заранее спасибо!
Ответить с цитированием
  #2  
Старый 24.01.2022, 22:41
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,004
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

1. lpLockStatus - это поинтер на структуру
3. cbBufSize - размер памяти переданный через lpLockStatus
2. pcbBytesNeeded - тоже поинтер, на DWORD
Оба параметра, если правильно помню, передавать как var параметры

Т.е. сигнатура будет примерно такой:
Код:
function QueryServiceLockStatus(hSCManager: SC_HANDLE;
  var lpLockStatus: QUERY_SERVICE_LOCK_STATUS; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL;
Попробуй так (в cbBufSize передавать SizeOf(QUERY_SERVICE_LOCK_STATUS))

Если все сработает для одного статуса, то тогда можно будет дальше эксперементировать с тем, что бы получать несколько статусов.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 00:47.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter