![]() |
CTL_CODE Funktion in Delphi
Hallo,
hat jemand zufälligerweise ein DDK installiert und kann mir kurz den Wert IOCTL_PROCVIEW_GET_PROCINFO berechnen: #define FILE_DEVICE_UNKNOWN 0x00000022 #define IOCTL_PROCVIEW_GET_PROCINFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) ich habe zwar ne Delphi CTL_CODE-Variante im Internet gefunden
Delphi-Quellcode:
aber anscheinend ist die nicht richtig oder ich vermurkse sonst noch etwas bei der Kommunikation mit dem Treiber...
function CTL_CODE(DeviceType, _Function, Method, Access: Cardinal): Cardinal;
begin Result := (DeviceType shl 16) or (Access Shl 14) or (_Function shl 2) or (Method); end; Noch eine Frage: Ist BOOLEAN in C++ äquivalent zu Boolean in Delphi? Danke im Voraus!!! Viele Grüße peanut. |
Re: CTL_CODE Funktion in Delphi
Zitat:
ich denke dass ist nicht der Fall. Ich kann mich da natürlich auch irren, aber Boolean in Delphi ist imho nur 1 Byte groß. In C++ verwendet man hingegen einen 4 Byte Wert (LongBool in Delphi). Das hat Perfomancegründe. Was du sonst unter äquivalent verstehst ist halt so eine Sache. Selbst für C gilt schon, dass die Wert 1,2,3,4,... und -1,-2,.. alle äquivalent sind, was den Wahrheitswert angeht. Es wird nur 0 und nicht 0 unterschieden, ein direkter Vergleich ob zwei Werte gleich sind ist also eine nicht sinnvolle Aussage (wenn es um Wahrheitswerte geht), ob beide ungleich null sind wäre hingegen eine sinnvolle Aussage. Gruß Der Unwissende |
Re: CTL_CODE Funktion in Delphi
In C++ gibt es nur den Typ bool. Ich weiß nicht, inwieweit der Ähnlichkeiten mit dem Delphi-Boolean hat. BOOLEAN hingegen ist eine Definition der Windows-API und sie müsste kompatibel zu Delphis LongBool sein.
|
Re: CTL_CODE Funktion in Delphi
Moin Peanut,
also ich erhalte da $0022E000 als Ergebnis. Die Werte kannst Du übrigens aus der WinIoCtl.h aus dem PSDK erhalten. Die Funktion sieht auch gut aus. Woher hast Du eigentlich IOCTL_PROCVIEW_GET_PROCINFO ? Das kann ich auch im DDK (Windows 2003) nicht entdecken. |
Re: CTL_CODE Funktion in Delphi
Hallo,
um die Situation zu klären: Ich verwende einen Treiber von Ivo Ivanov (CodeProject: ![]() Ich möchte dann mittels DeviceIoControl() und GetOverlappedResult() die von ihm definierte Datenstruktur typedef struct _CallbackInfo { HANDLE hParentId; HANDLE hProcessId; BOOLEAN bCreate; // (*) }CALLBACK_INFO, *PCALLBACK_INFO; auslesen. Leider scheitert bei mir folgender Aufruf
Delphi-Quellcode:
Ich denke, dass es vielleicht an meiner TCallbackInfo-Datenstruktur liegt:
DeviceIoControl(m_hDriver, IOCTL_PROCVIEW_GET_PROCINFO, nil, 0, @CallbackInfo^, SizeOf(TCallbackInfo), dwBytesReturned, @ov)
Delphi-Quellcode:
Nun wollte ich wissen, welches Delphi-Boolean nun dem BOOLEAN Typ aus C++ entspricht, siehe (*), denn THandle = HANDLE => das kann demnach nicht falsch sein. Auch das Initialisieren des Treibers und Warten bis ein Event gefeuert wird funktioniert, nur der Aufruf mittels DeviceIoControl scheitert.
TCallbackInfo = record
ParentId : THANDLE; ProcessId: THANDLE; bCreate : LongBool; end; PCallbackInfo = ^TCallbackInfo; Zitat:
Was die CTL_CODE Funktion betrifft. Ivo hat mit IOCTL_PROCVIEW_GET_PROCINFO wohl einen eigenen IoControlCode eingeführt, keine Ahung wieso? Definiert hatte er ihn aber wie folgt: #define FILE_DEVICE_UNKNOWN 0x00000022 #define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN #define IOCTL_NTPROCDRV_GET_PROCINFO CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) somit müsste doch IOCTL_NTPROCDRV_GET_PROCINFO auch ein FILE_DEVICE_UNKNOWN sein oder??? Viele Grüße peanut. |
Re: CTL_CODE Funktion in Delphi
Moin Peanut,
in der Winnt.h ist BOOLEAN als BYTE deklariert, dürfte also im Wesentlichen dem Delphi-Boolean entsprechen. Probier auch mal die Struktur als Packed zu deklarieren. Klingt alles interessant. Vielleicht komme ich morgen mal dazu mir den Artikel durchzulesen, und die Sourcen anzusehen. |
Re: CTL_CODE Funktion in Delphi
BOOLEAN ist als Byte deklariert, waehrend BOOL als DWORD deklariert ist. Die Entsprechung ist daher ByteBool fuer BOOLEAN bzw LongBool fuer BOOL.
Records in DDK-C-Headern sind gerne auf 1-Byte-Grenze gepackt. Das CTL_CODE Makro sollte man nicht in eine Funktion ueberfuehren, denn dann hat man keine Konstante die der Compiler direkt handhaben kann. |
Re: CTL_CODE Funktion in Delphi
Hallo!
Vielen Dank für die Informationen. Ich habe die Datenstruktur nun als packed deklariert und den Booleanwert geändert. Statt des CTL_CODE Makros habe ich direkt eine Konstante mit dem entsprechenden Wert definiert. UND...... es hat funktioniert!!! :-D Nochmals DANKE! Wenn Interesse besteht, kann ich den Sourcecode hier rein posten. Es ist interessant, wenn man weiß, welcher Prozess wann gestartet und beendet wird. Viele Grüße peanut. |
Re: CTL_CODE Funktion in Delphi
Zitat:
|
Re: CTL_CODE Funktion in Delphi
Zitat:
Nachdem ich in letzter Zeit von einem Fettnäpfchen ins nächste tappe: Kann mir jemand ein Buch empfehlen, das einem einen guten Überblick über die tiefere System-API gibt inkl. Verweise was sich gehört und was man aus Effizienz- oder anderen Gründen lieber sein lässt. DANKE :) |
Re: CTL_CODE Funktion in Delphi
Zitat:
Zitat:
- Native API (UM) - Native API (KM) + Rest vom KM UM == User-Mode KM == Kernel-Mode Ich stehe dir gern per PM zur Verfügung, soweit es meine Zeit zuläßt. Vielleicht könnten wir gemeinsam einen Artikel zu diesem Thema verfassen - für das "de-delphi"-Projekt auf SF.net! |
Re: CTL_CODE Funktion in Delphi
Zu dem BOOLEAN
wenn das wirklich ByteBoll ist, dann sollte das wohl auch besser als ByteBoll definiert werden und nicht mal einfach so als Boolaen(Delphi) ich glaub das war so:
Delphi-Quellcode:
ByteBool(True) = $FF
Boolean(True) = $01 ByteBool(False) = $00 Boolean(False) = $00 ach ja, die C-Header im PSDK sind wohl an 8 Byte-Grenzen gepackt ... warum MS das im DDK anscheinend anders gemacht hat ... keine Ahnung ._. |
Re: CTL_CODE Funktion in Delphi
Zitat:
Reicht das? :zwinker: :mrgreen: Nachtrag: natürlich wissen wir ja alle, daß wir lieber Puffer mit Pointern benutzen sollten (über ExAllocatePoolWithTag), aber wenn man eben doch mal eine Struktur direkt auf dem Stack zu liegen hat, kann das kleinste Byte über Wohl oder Wehe des Threads entscheiden. |
Re: CTL_CODE Funktion in Delphi
Zitat:
|
Re: CTL_CODE Funktion in Delphi
Hallo,
anbei der Code zum Thema. Ich habe ihn überarbeitet und festgestellt, dass es auch ohne packed-Deklaration funktioniert.
Delphi-Quellcode:
{
Based on an article and code by Ivo Ivanov at The Code Project: Detecting Windows NT/2K process execution url: [url]http://www.codeproject.com/threads/procmon.asp[/url] PLEASE NOTE: Download driver 'NTProcDrv.sys' at the url noted above!!! } program NTDriverController; {$APPTYPE CONSOLE} uses SysUtils, Windows, psapi, WinSvc; type TCallbackInfo = record ParentId : THANDLE; ProcessId: THANDLE; bCreate : ByteBool; end; PCallbackInfo = ^TCallbackInfo; const IOCTL_PROCVIEW_GET_PROCINFO = $0022E000; //CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) var m_hSCM : SC_HANDLE; m_hDriver : SC_HANDLE; nServiceStatus : SERVICE_STATUS; strServiceName : String = 'NTProcDrv'; strDisplayName : String = 'Process creation/termination detector for Windows XP'; strFileName : String = ''; lpServiceArgVectors: PAnsiChar = nil; m_hShutDownEvent : THandle; //////////////////////////////////////////////////////////////////////////////// function GetExeNameByPID(dwPID: DWord): String; var h: THandle; begin Result := ''; h := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, dwPID); if (h <> 0) then try SetLength(Result, MAX_PATH); ZeroMemory(@Result[1], MAX_PATH); SetLength(Result, GetModuleFileNameEx(h, 0, @Result[1], MAX_PATH)); finally CloseHandle(h); end; Result := LowerCase(Result); end; //////////////////////////////////////////////////////////////////////////////// function KeyboardThread(dwArg: DWORD): DWORD; var nEvents : Cardinal; dwNumRead: DWORD; InputRec : TInputRecord; begin Result := 0; while (true) do begin GetNumberOfConsoleInputEvents(GetStdHandle(STD_INPUT_HANDLE), nEvents); if (nEvents > 0) then begin ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), InputRec, 1, dwNumRead); if (InputRec.Event.KeyEvent.AsciiChar = 'q') then break; end; Sleep(800); end; writeln('# shutting down, please wait...'); SetEvent(m_hShutDownEvent); ExitThread(0); end; //////////////////////////////////////////////////////////////////////////////// function WaitForState(dwDesiredState: DWORD; pss: SERVICE_STATUS): Boolean; var dwWaitHint: DWORD; begin Result := False; if (m_hDriver <> 0) then while (True) do begin // Get current state of driver Result := QueryServiceStatus(m_hDriver, pss); // If we can't query the driver, we're done if not(Result) then break; // If the driver reaches the desired state if (pss.dwCurrentState = dwDesiredState) then break; // We're not done, wait the specified period of time dwWaitHint := pss.dwWaitHint div 10; // Poll 1/10 of the wait hint if (dwWaitHint < 1000) then dwWaitHint := 1000; // At most once a second if (dwWaitHint > 10000) then dwWaitHint := 10000; // At least every 10 seconds Windows.Sleep(dwWaitHint); end; end; //////////////////////////////////////////////////////////////////////////////// procedure RetrieveProcessInfo(hDriver: THandle; CallbackInfo, CallbackTemp: PCallbackInfo); var dwBytesReturned: DWORD; ov : OVERLAPPED; begin ZeroMemory(@ov, SizeOf(OVERLAPPED)); dwBytesReturned := 0; ov.hEvent := CreateEvent(nil, True, False, nil); if DeviceIoControl(hDriver, IOCTL_PROCVIEW_GET_PROCINFO, nil, 0, @CallbackInfo^, SizeOf(TCallbackInfo), dwBytesReturned, @ov) then GetOverlappedResult(m_hDriver, ov, dwBytesReturned, True) else writeln('! Error while DeviceIoControl, code: ' + IntToStr(GetLastError)); if ((callbackTemp^.ParentId <> callbackInfo^.ParentId) or (callbackTemp^.ProcessId <> callbackInfo^.ProcessId) or (callbackTemp^.bCreate <> callbackInfo^.bCreate)) then begin if(callbackInfo^.bCreate) then begin Sleep(300); // sleep some ms or image name could not be determinated :-( writeln('# process created, PID : ' + IntToStr(callbackInfo^.ProcessId) + ' ' + GetExeNameByPID(callbackInfo.ProcessId)) end else writeln('# process terminated, PID: ' + IntToStr(callbackInfo^.ProcessId)); end; CloseHandle(ov.hEvent); // Store the data for next time to prevent doubled events callbackTemp^ := callbackInfo^; end; //////////////////////////////////////////////////////////////////////////////// procedure ProcessMonitor; var szDriverName : String; hDriver : THandle; m_hProcessEvent: THandle; CallbackInfo : TCallbackInfo; CallbackTemp : TCallbackInfo; lpHandles : TWOHandleArray; dwResult : DWORD; dwThreadID : DWORD; begin szDriverName := '\\.\Global\NTProcDrv'#0; // Change to '\\.\NTProcDrv'#0 if CreateFile failes... hDriver := CreateFile(@szDriverName[1], GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (hDriver <> INVALID_HANDLE_VALUE) then begin m_hShutdownEvent := CreateEvent(nil, False, False, nil); m_hProcessEvent := OpenEvent(SYNCHRONIZE, False, 'NTProcDrvProcessEvent'); ZeroMemory(@lpHandles, SizeOf(lpHandles)); lpHandles[0] := m_hShutdownEvent; lpHandles[1] := m_hProcessEvent; CreateThread(nil, 0, @KeyboardThread, nil, 0, dwThreadID); ZeroMemory(@CallbackInfo, SizeOf(TCallbackInfo)); ZeroMemory(@CallbackTemp, SizeOf(TCallbackInfo)); while (True) do begin dwResult := WaitForMultipleObjects(2, @lpHandles, False, INFINITE); if (dwResult = 0) then break; // user pressed 'q' RetrieveProcessInfo(hDriver, @CallbackInfo, @CallbackTemp); end; Sleep(1000); // ExitThread(0) and cleaning stack might take some ms CloseHandle(m_hProcessEvent); CloseHandle(m_hShutdownEvent); CloseHandle(hDriver); end; end; //////////////////////////////////////////////////////////////////////////////// begin writeln('# opening Servive Control Manager (SCM)...'); m_hSCM := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if (m_hSCM <> 0) then begin writeln('# opened SCM'); strFileName := ExtractFilePath(ParamStr(0)) + strServiceName + '.sys'; m_hDriver := OpenService(m_hSCM, PChar(strServiceName), SERVICE_ALL_ACCESS); if (m_hDriver <> 0) then begin if ControlService(m_hDriver, SERVICE_CONTROL_STOP, nServiceStatus) then WaitForState(SERVICE_STOPPED, nServiceStatus); DeleteService(m_hDriver); CloseServiceHandle(m_hDriver); writeln('! driver was not deleted last time.'); CloseServiceHandle(m_hDriver); Sleep(1000); end; m_hDriver := CreateService(m_hSCM, PChar(strServiceName), PChar(strDisplayName), SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, PChar(strFilename), nil, nil, nil, nil, nil); if (m_hDriver <> 0) then begin writeln('# service created, starting kernel driver...'); if (StartService(m_hDriver, 0, lpServiceArgVectors)) then WaitForState(SERVICE_RUNNING, nServiceStatus) else begin DeleteService(m_hDriver); CloseServiceHandle(m_hDriver); CloseServiceHandle(m_hSCM); writeln('! error while starting driver'); exit; end; writeln('# kernel driver started'); // interact with driver now... ProcessMonitor; writeln('# stopping kernel driver...'); if ControlService(m_hDriver, SERVICE_CONTROL_STOP, nServiceStatus) then WaitForState(SERVICE_STOPPED, nServiceStatus) else writeln('! could not stop kernel driver'); // Mark the service for deletion. if DeleteService(m_hDriver) then writeln('# service deleted') else writeln('! could not delete service'); CloseServiceHandle(m_hDriver); end; CloseServiceHandle(m_hSCM); end; Sleep(1000); end. |
Re: CTL_CODE Funktion in Delphi
Zitat:
Delphi-Quellcode:
sizeof(TCallbackInfo2) == 12
TCallbackInfo1 = packed record
ParentId : THANDLE; bCreate : ByteBool; ProcessId: THANDLE; end; TCallbackInfo2 = record ParentId : THANDLE; bCreate : ByteBool; ProcessId: THANDLE; end; sizeof(TCallbackInfo1) == 9 Übrigens, wenn du deinen Code noch etwas würzen willst, könntest du ![]() |
Re: CTL_CODE Funktion in Delphi
Zitat:
|
Re: CTL_CODE Funktion in Delphi
Ist nicht nur Kosmetik. Ich hatte vergessen, daß die etwas ausgereiftere Variante
![]() |
Re: CTL_CODE Funktion in Delphi
Zitat:
Gruß peanut. |
Re: CTL_CODE Funktion in Delphi
Zitat:
![]() Macht sich besonders bei Treibern sehr sehr schön. |
Re: CTL_CODE Funktion in Delphi
szDriverName könntest du auch als Konstante deklarieren ... sie bräuchte dann och keinen eigenen Platz im RAM.
Und die #0 könnte auch weg ... Delphi-Strings sind ja schon von Haus aus #0-terminiert. |
Re: CTL_CODE Funktion in Delphi
Hallo,
baue gerade meine eigene Version des Treibers... Wenn es fertig ist, poste ich das gesamte Paket hier rein. Zitat:
Zitat:
Viele Grüße peanut. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz