Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi NT-Dienste, Fehler im Code...nur wo? (https://www.delphipraxis.net/7028-nt-dienste-fehler-im-code-nur-wo.html)

LeoDD 30. Jul 2003 17:14


NT-Dienste, Fehler im Code...nur wo?
 
Hallo :)

Ich sitz derzeit an nem kleinen Programm, was den Status und die Config für einen bestimmten Dienst ("Messenger") abfragen soll und auch ändern soll (später).

Während die Statusabfrage problemlos läuft, verzweifel ich an der Konfigurationsabfrage. Zunächst mal der Codeschnipsel:

Code:
procedure GetMessengerInfo(var ServiceStatus: TServiceStatus; var ServiceConfig: TQueryServiceConfig);
var
   SMH, MH: THandle;
   NeededBytes: dword;
   R: boolean;

begin
SMH:=OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if SMH = null then begin
   ShowMessage(SysErrorMessage(GetLastError));
   Application.Terminate;
end;

MH:=OpenService(SMH, PChar('Messenger'), SC_MANAGER_ALL_ACCESS);

if MH = null then begin
   ShowMessage(SysErrorMessage(GetLastError));
end;

if not QueryServiceStatus(MH, ServiceStatus) then begin
   ShowMessage(SysErrorMessage(GetLastError));
end;

NeededBytes:=0;

R:=QueryServiceConfig(MH, @ServiceConfig, sizeof(ServiceConfig), NeededBytes);

if not R then begin
   if GetLastError = ERROR_INSUFFICIENT_BUFFER then begin
      if not QueryServiceConfig(MH, @ServiceConfig, sizeof(ServiceConfig) + NeededBytes, NeededBytes) then begin
         ShowMessage(SysErrorMessage(GetLastError));
      end;
   end else begin
      ShowMessage(SysErrorMessage(GetLastError));
   end;
end;

CloseServiceHandle(MH);
CloseServiceHandle(SMH);
end;
Diese Funktion soll also den Status und die Config in die übergebenen Parameter ablegen. Dabei erscheint auch keine Fehlermeldung. Aber beim Beenden des Programms kommt eine "access violation".

Kann sich bitte einer von euch mal der Sache annehmen und mir einen Hinweis geben was ich falsch mache? :|

Gruß
Leo

-Amazeroth- 30. Jul 2003 23:31

Re: NT-Dienste, Fehler im Code...nur wo?
 
In deinem Code schreibst du ÜBER deinen Speicher hinaus. Daher die AV.
Du hast nur den Speicher für eine TQueryServiceConfig-Struktur reserviert. Allerdings willst du im zweiten Aufruf "QueryServiceConfig(MH, @ServiceConfig, sizeof(ServiceConfig) + NeededBytes, NeededBytes)" plötzlich mehr Bytes geschrieben haben, als du reserviert hast. Es geht nicht so simpel. Du mußt mit Pointern arbeiten!
Hier eine Lösung. Allerdings verlangt sie, daß du per GetMemory() vorher Speicher reservierst und danach per FreeMemory() wieder freigibst.

Delphi-Quellcode:
procedure GetMessengerInfo(var ServiceStatus: TServiceStatus; var ServiceConfig: PQueryServiceConfig);
var
  SMH, MH: THandle;
  NeededBytes: dword;
  R: boolean;
begin
  SMH := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SMH <> 0 then // NULL <> 0!!!
  try
    MH := OpenService(SMH, 'Messenger', SC_MANAGER_ALL_ACCESS); // Literale gehen auch so!
    if MH <> 0 then
    try
      if not QueryServiceStatus(MH, ServiceStatus) then
        ShowMessage(SysErrorMessage(GetLastError));
      NeededBytes := 0;
      R := QueryServiceConfig(MH, ServiceConfig^, sizeof(ServiceConfig^), NeededBytes);
      if not R then
        (
          if GetLastError = ERROR_INSUFFICIENT_BUFFER then
          begin
            FreeMemory(ServiceConfig);
            ServiceConfig := GetMemory(NeededBytes);
            if Assigned(ServiceConfig) then
              if not QueryServiceConfig(MH, ServiceConfig^, NeededBytes, NeededBytes) then
                ShowMessage(SysErrorMessage(GetLastError));
          end
          else
            ShowMessage(SysErrorMessage(GetLastError))
              )
    finally
      CloseServiceHandle(MH);
    end
    else
      ShowMessage(SysErrorMessage(GetLastError));
  finally
    CloseServiceHandle(SMH);
  end
  else
  begin
    ShowMessage(SysErrorMessage(GetLastError));
    Application.Terminate;
  end;
end;
Aufruf ca so ...

Delphi-Quellcode:
var
  ServiceStatus: TServiceStatus;
  ServiceConfig: PQueryServiceConfig;
begin
  ServiceConfig := GetMemory(sizeof(ServiceConfig^));
  if Assigned(ServiceConfig) then
  try
    ZeroMemory(ServiceConfig, sizeof(ServiceConfig^));
    GetMessengerInfo(ServiceStatus, ServiceConfig);
// Hier wird die Konfiguration ausgewertet
// ...
  finally
// Freigegeben des Speichers
    FreeMemory(ServiceConfig);
  end;
end;

LeoDD 31. Jul 2003 08:48

Re: NT-Dienste, Fehler im Code...nur wo?
 
Ein ganz dickes Dankeschön :hello:

Ich werds gleich mal testen :coder:

Nachtrag:
Der Compiler sagt:
Zitat:

[Fehler] MainUnit.pas(48): Inkompatible Typen: '_QUERY_SERVICE_CONFIGA' und 'PQueryServiceConfigA'
[Fehler] MainUnit.pas(56): Inkompatible Typen: '_QUERY_SERVICE_CONFIGA' und 'PQueryServiceConfigA'
Nachtrag2:

habs gelöst und es läuft :) Nochmal vielen Dank :love:


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz