Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник
Коллекция курьезных вопросов из форумов
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »
Страницы: 1

QueryServiceLockStatus [D7]


apic   (23.01.22 09:43

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

[Code]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;[/Code]

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

[Code]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;[/Code]

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

Может кто нибудь привести объяснить и привести пример кода, как правильно работать с этим зверем? Код пишу в Delphi 10.4, одна из последних версий. Ооооочень нужна помощь. Заранее спасибо!


Rouse_ ©   (23.01.22 11:42[1]

var lpLockStatus: PByte <<<< var убери, иначе у тебя указатель на указатель получается.


apic   (23.01.22 12:00[2]

Ураааааааа, спасибо большое! Все отработало отлично! И имя пользователя правильно получил из LPQUERY_SERVICE_LOCK_STATUSW(Buffer)^.lpLockOwner, а то до этого мусор сыпался. Офигеть, я был близок, но это нюанс проглядел. Спасибо большое еще раз! Вы лучший!


Rouse_ ©   (23.01.22 13:14[3]

Мусор сыпался потому что из-за двойного указателя у тебя функция выводила данные в стековые переменные затирая все что выше Buffer, отсюда у тебя и менялось число в BufSize т.к. она входит в требуемый размер возвращаемой структуры.


Страницы: 1 версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо