Newsgroup: it.comp.lang.delphi
Titolo: Sempre sugli HANDLE

Salve a tutti,
Sto leggendo già con interesse l'altro thread sugli Handle ma purtroppo il
mio problema è diverso. Infatti non si tratta nel mio caso di lanciare
un'applicazione e ricavarne un handle...bensì di ricavare l'handle
dell'istanza di un'applicazione specifica GIA' in esecuzione all'avvio del
mio programma.
Non sono bravo inq ueste cose comunque siccome uso Win2000 ho visto (con
ctrlaltcanc) che in un preciso momento ci sono qualcosa come 7000 handle
caricati.....ma come faccio a identificare quello che mi interessa sapendo
il semplice nome dle programma?
prendiamo per esempio che esegua calc.exe (sempre lui) e poi eseguo il mio
programma mentre cal.exe è aperto...come potrei "scovare" l'handle correlato
al calc.exe in esecuzione?
Vi cheiderei di non essere troppo tecnici se possibile...non sono un
principiante ma su queste questioni un po' "fuori dal programma" mi perdo
facilmente...:(
--
Giulio Pipitone (
www.fighters4web.com
 )
#sito per la lotta agli abusi in rete#

 al calc.exe in esecuzione?
Potresti fare come ti ho scritto sopra, oppure potresti trovarti un Handle
di finestra con FindWindow(), poi ottenere il Process Id via
GetWindowThreadProcessId() e successivamente richiamare OpenProcess() per
ottenere un handle valido.
Ciao
--
- Carlo -
cbertu81(at)libero(dot)it

Ti invio la stessa procedura che ho postato all'altro thread, solo che
nell'altra avevo aggiunto una riga per terminare il processo:
FUNCTION PrgInRun(    FileName : String;//path+nome del file da cercare tra
i programmi in run
                       MaxNrPrg : Word;//max numero di cicli di ricerca (per
evitare un loop infinito)
                   Var FNHandle : THandle) : Boolean;//FNHandle = Handle
dell'applicazione trovata
     VAR  ProcData : TProcessEntry32;
          HDLTool  : THandle;
          HDLProc  : THandle;
          Var1     : Integer;
    BEGIN
          Result := False;
          HDLTool := 0;
          HDLProc := 0;
          ProcData.dwSize := SizeOf(ProcData);
          Try HDLTool := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
              Var1 := 1;
              If Process32First(HDLTool,ProcData) Then
                 Begin
                 Inc(Var1);
                 While ((Process32Next(HDLTool,ProcData)) And
(Var1<=MaxNrPrg)) Do//non più di "MaxNrPrg" processi
                    begin
                    If AnsiCompareText(ProcData.szExeFile,FileName)=0 Then
                       Try HDLProc := OpenProcess(SYNCHRONIZE or
PROCESS_ALL_ACCESS,False,ProcData.th32ProcessID);
                           FNHandle := HDLProc;
                           Result := True;
                           Break;
                           Finally
                           CloseHandle(HDLProc);
                       End;
                    End;
                 End;
              Finally
              CloseHandle(HDLTool);
          End;
    END;

Grazie a entrambi...ci sto smanettando su.....


 PROCESS_ALL_ACCESS,False,ProcData.th32ProcessID);
soluzione ottima ma va specificato che non funziona su Windows NT.


 ha scritto nel messaggio
news:ZLDR8.58979$Kt3.1...@twister2.libero.it...


 invece di dare "Path+Nome applicazione" basta "Nome applicazione".
La hai provata su NT e funziona oppure la hai provata sul 2000 e ne hai
dedotto che funziona anche su NT?
In teoria le ToolHelp su WinNT non sono disponibili e vanno utilizzate le
PSAPI


 ha scritto nel messaggio
news:2AER8.60012$j65.1...@twister1.libero.it...


Per fortuna nel mioc aos uso win2000....fiuuuuuu ;)


Grazie, non ll'ho provata su NT. Ma per farla funziare anche li come bisogna
fare?

 fare?
purtroppo su WinNT non esistono le ToolHelp e le uniche system call
documentate per risolvere il problema sono le PSAPI.
Ti posto un po' di codice contenente funzioni per lavorare sui processi ...
è una Unit che ho scritto un po' di tempo fa e che si è rivelata utile in
più casi!
Forse è da rivedere proprio la funzione per la gestione dei processi! :-)
Eccola!
--
unit ProcManager;
interface
uses psapi, tlhelp32, SysUtils, Windows, Dialogs;
type TProcInfo = Record
     ProcessName: String;
     Path: String;
     Priority: String;
     ProcessID: dWord;
     ThreadCount: ShortInt;
end;
type TModInfo = Record
     ModuleName : String;
     ModInstance: HModule;
     ModuleSize : Cardinal;
end;
Type TprocInfoArr = Array of TProcInfo;
Type TModInfoArr = Array of TModInfo;
{ Dichiarazione funzione per ottenere la priorità }
function GetPriorityClass(hProcess: THandle): dWord; stdcall;
         external 'kernel32.DLL';
function SetPriorityClass(hProcess: THandle; dwPriorityClass: DWORD):
Boolean; stdcall;
         external 'kernel32.DLL';
{ La funzione ProcessList riempie un Array di Record dinamico con le
informazioni
  relative ai processi attivi sulla macchina - L'array restituito è
Zero-Based
  e l'ultimo processo è alla posizione High(ProcInfoArray) }
function ProcessList(var ProcInfoArray: TprocInfoArr): boolean;
{ La funzione ModuleList riempie un Array di Record dinamico con le
informazioni
  relative ai moduli di un processo di cui si conosce l'ID(entifier) -
  L'array restituito è Zero-Based e l'ultimo processo è alla posizione
High(ModuleInfoArray) }
function ModuleList(var ModuleInfoArray: TModInfoArr; ProcessID: dWord):
boolean;
{ La seguente funzione imposta la priorità di un processo }
function SetProcessPriority(PID, Priority: dWord): Boolean;
implementation
{ Costanti priorità del processo - Utilizzate Internamente }
const NORMAL_PRIORITY_CLASS       = $00000020;
      IDLE_PRIORITY_CLASS         = $00000040;
      HIGH_PRIORITY_CLASS         = $00000080;
      REALTIME_PRIORITY_CLASS     = $00000100;
      BELOW_NORMAL_PRIORITY_CLASS = $00004000;
      ABOVE_NORMAL_PRIORITY_CLASS = $00008000;
{ La funzioni ExtractXXXData vengono utilizzate internamente alla Unit
(privati)
  e servono a riempire i Record tipo TXXXInfo partendo da TXXXEntry32
  (ToolHelp Record) -   Vengono utilizzate solo nella sezione Win9x/ME }
Function ExtractProcessData(RecToExtract: TProcessEntry32):TProcInfo;
begin
  With Result do begin
    ProcessName := ExtractFileName(RecToExtract.szExeFile);
    Path        := ExtractFilePath(RecToExtract.szExeFile);
    ProcessID   := RecToExtract.th32ProcessID;
    ThreadCount := RecToExtract.cntThreads;
  end;
end;
Function ExtractModuleData(RecToExtract: TModuleEntry32):TModInfo;
begin
  With Result do begin
    ModuleName  := RecToExtract.szModule;
    ModInstance := RecToExtract.hModule;
    ModuleSize  := RecToExtract.modBaseSize;
  end;
end;
{ Imposta nel Record TProcInfo il campo Priority }
Function Process_GetPriority(var ProcessInfo: TProcInfo; ProcessID: dWord):
boolean;
var hProcess: THandle;
    Priority: dWord;
begin
  result := false;
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION,false,ProcessID);
  if hProcess <> 0 then begin
     Priority := GetPriorityClass(hProcess);
     Case Priority of
       NORMAL_PRIORITY_CLASS :
         ProcessInfo.Priority := 'Normal_Priority';
       IDLE_PRIORITY_CLASS   :
         ProcessInfo.Priority := 'Idle_Priority';
       HIGH_PRIORITY_CLASS   :
         ProcessInfo.Priority := 'High_Priority';
       REALTIME_PRIORITY_CLASS :
         ProcessInfo.Priority := 'Realtime_Priority';
       BELOW_NORMAL_PRIORITY_CLASS :
         ProcessInfo.Priority := 'Below_Normal_Priority';
       ABOVE_NORMAL_PRIORITY_CLASS :
         ProcessInfo.Priority := 'Above_Normal_Priority';
     end;
     Result := True;
     CloseHandle(hProcess);
  end;
end;
{ Lista di processi }
function ProcessList(var ProcInfoArray: TprocInfoArr): boolean;
{ Variabili di Win9x/ME }
var hSnapShot: THandle;
    isNotLast: Boolean;
    ProcEntry: TProcessEntry32;
{ Variabili di WinNT/2K }
    cbNeeded, cbReturned: DWORD;
    PID: Array [1..1024] of dWord;
    hProcess, hModule: THandle;
    pName: pChar;
{ Variabili comuni - Contatori }
    Indice, Count: Integer;
begin
Result := false;
Indice := 1;
  case Win32Platform of
       Integer(VER_PLATFORM_WIN32_WINDOWS):
       begin
       { Codice di Windows 9x/ME }
          hSnapShot:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
          If (hSnapShot<>-1) then
          begin
             Result := True;
             SetLength(ProcInfoArray,Indice);
             IsNotLast:=Process32First(hSnapShot,ProcEntry);
             While IsNotlast do
             begin
                procInfoArray[Indice-1] := ExtractProcessData(ProcEntry);
                if not
Process_GetPriority(procInfoArray[Indice-1],ProcEntry.th32ProcessID) then
                   procInfoArray[Indice-1].Priority := 'Unknown_Priority';
                IsNotLast:=Process32Next(hSnapShot,ProcEntry);
                Inc(Indice);
                SetLength(ProcInfoArray,Indice);
             end;
             SetLength(ProcInfoArray,Indice-1);
             CloseHandle(hSnapShot);
          end;
       end;
       Integer(VER_PLATFORM_WIN32_NT):
       begin
       { Codice di Windows NT/2K }
         if EnumProcesses(@PID,SizeOf(PID),cbNeeded) then begin
            pName := AllocMem(MAX_PATH);
            Count := 0;
            for Indice := 1 to (cbNeeded div SizeOf(dWord)) do begin
                hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or
PROCESS_VM_READ,
                                   false,PID[Indice]);
                if hProcess <> 0 then
                begin
                  EnumProcessModules( hProcess, @hModule, sizeof(hModule),
cbReturned );
                  if GetModuleBaseName(hProcess,hModule,pName,MAX_PATH) <> 0
then begin
                        Inc(Count);
                        SetLength(ProcInfoArray,Count);
                        procInfoArray[Count-1].ProcessID := PID[Indice];
                        if not
Process_GetPriority(procInfoArray[Count-1],PID[Indice]) then
                           procInfoArray[Count-1].Priority :=
'Unknown_Priority';
                        procInfoArray[Count-1].ProcessName := String(pName);
GetModuleFileNameEx(hProcess,hModule,pName,MAX_PATH);
                        procInfoArray[Count-1].Path :=
ExtractFilePath(pName);
                     end;
                  CloseHandle(hProcess);
                end;
            end;
            Result := True;
            FreeMem(pName);
         end;
       end;
  end; {Case}
end;
{ Lista di moduli per Win9x - Privata}
function W9x_ModuleList(var ModuleInfoArray: TModInfoArr; ProcessID: dWord):
boolean;
var hSnapShot: THandle;
    isNotLast: Boolean;
    ModuleEntry: TModuleEntry32;
    Indice: Integer;
begin
  Result := false;
  hSnapShot:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessID);
  If (hSnapShot<>-1) then
  begin
    Indice := 1;
    Result := True;
    SetLength(ModuleInfoArray,Indice);
    IsNotLast:=Module32First(hSnapShot,ModuleEntry);
    While IsNotlast do
    begin
      ModuleInfoArray[Indice-1] := ExtractModuleData(ModuleEntry);
      IsNotLast:=Module32Next(hSnapShot,ModuleEntry);
      Inc(Indice);
      SetLength(ModuleInfoArray,Indice);
    end;
    SetLength(ModuleInfoArray,Indice-1);
  end;
  CloseHandle(hSnapShot);
end;
{ Lista di moduli per WinNT - Privata }
function WNT_ModuleList(var ModuleInfoArray: TModInfoArr; ProcessID: dWord):
boolean;
var hProcess: THandle;
    hModule: Array [1..1024] of THandle;
    cbReturned: dWord;
    mName: pChar;
    mInfo: TModuleInfo;
    Indice, Count: Integer;
begin
 Result := False;
 hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
                         false,ProcessID);
 if (hProcess <> 0) then begin
    Result := True;
    EnumProcessModules( hProcess, @hModule, sizeof(hModule), cbReturned );
    mName := AllocMem(MAX_PATH);
    Count := cbReturned div SizeOf(THandle);
    for Indice := 1 to Count do begin
        GetModuleBaseName(hProcess,hModule[Indice],mName,MAX_PATH);
        GetModuleInformation(hProcess,hModule[Indice],@mINFO,SizeOf(mInfo));
        SetLength(ModuleInfoArray,Indice);
        ModuleInfoArray[Indice-1].ModInstance := hModule[Indice];
        ModuleInfoArray[Indice-1].ModuleSize  := mInfo.SizeOfImage;
        ModuleInfoArray[Indice-1].ModuleName  := mName;
    end;
    FreeMem(mName);
 end;
 CloseHandle(hProcess);
end;
{ Funzione pubblica per la lista dei moduli }
function ModuleList(var ModuleInfoArray: TModInfoArr; ProcessID: dWord):
boolean;
Begin
  result := false;
  if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
     Result := W9x_ModuleList(ModuleInfoArray,ProcessID) else
  if Win32Platform = VER_PLATFORM_WIN32_NT then
     Result := WNT_ModuleList(ModuleInfoArray,ProcessID);
end;
{ Funzione pubblica per l'impostazione della priorità }
function SetProcessPriority(PID, Priority: dWord): Boolean;
var hProcess: THandle;
begin
  result := false;
  hProcess := OpenProcess(PROCESS_SET_INFORMATION,true,PID);
  if (hProcess <> 0) then begin
      if SetPriorityClass(hProcess,Priority) then
         result := true;
      CloseHandle(hProcess)
  end;
end;
(* funzioni di task managment da controllare
function WNT_ExitRemoteProcess(processID: DWord; msecs: DWord): boolean;
var
   hprocess, hthread: THandle;
   dwThreadID: DWord;
begin
   Result := True;
   hProcess := OpenProcess( PROCESS_ALL_ACCESS, False, processID);
   Win32Check( hProcess <> 0);
   hThread := CreateRemoteThread( hProcess,
                                  nil,
                                  0,
                                  GetProcAddress(
GetModuleHandle('Kernel32.dll'),
                                                  'ExitProcess'),
                                  nil,
                                  0,
                                  dwThreadID);
   CloseHandle( hProcess);
   Win32Check( hThread <> 0);
   try
     if WaitForSingleObject( hThread, msecs) = WAIT_TIMEOUT then
        Result := false;
   finally
     CloseHandle(hThread);
   end;
end;
Procedure Force_ExitRemoteProcess(processID: DWord);
var hProcess: THandle;
begin
  hProcess := OpenProcess(PROCESS_TERMINATE,False,ProcessID);
  TerminateProcess(hProcess,0);
  CloseHandle(hProcess);
end;
*)
end.


Grazie mille, ora me la studio.

 "scovare" l'handle correlato al calc.exe in esecuzione?
E va bene. L'hai voluto tu. Tempo di sfoderare le mie Conoscenze 
Occulte (TM). Usale solo per la causa del Bene (tutte funzioni 
orribilmente non documentate, tutto a tuo rischio e pericolo):
program ntfindproc;
  {$APPTYPE CONSOLE}
  type
    NTSTATUS = Cardinal;
    PVOID = Pointer;
    ULONG = Cardinal;
    PULONG = ^ULONG;
    USHORT = Word;
    LONG = Integer;
    HANDLE = Pointer;
    WCHAR = WideChar;
    PWCHAR = PWideChar;
    KPRIORITY = LONG;
    SYSTEM_INFORMATION_CLASS = (
      SystemBasicInformation, 
      SystemProcessorInformation,
      SystemPerformanceInformation,
      SystemTimeOfDayInformation,
      SystemNotImplemented1,
      SystemProcessesAndThreadsInformation,
      SystemCallCounts,
      SystemConfigurationInformation,
      SystemProcessorTimes,
      SystemGlobalFlag,
      SystemNotImplemented2,
      SystemModuleInformation,
      SystemLockInformation,
      SystemNotImplemented3,
      SystemNotImplemented4,
      SystemNotImplemented5,
      SystemHandleInformation,
      SystemObjectInformation,
      SystemPagefileInformation,
      SystemInstructionEmulationCounts,
      SystemInvalidInfoClass1,
      SystemCacheInformation,
      SystemPoolTagInformation,
      SystemProcessorStatistics,
      SystemDpcInformation,
      SystemNotImplemented6,
      SystemLoadImage,
      SystemUnloadImage,
      SystemTimeAdjustment,
      SystemNotImplemented7,
      SystemNotImplemented8,
      SystemNotImplemented9,
      SystemCrashDumpInformation,
      SystemExceptionInformation,
      SystemCrashDumpStateInformation,
      SystemKernelDebuggerInformation,
      SystemContextSwitchInformation, 
      SystemRegistryQuotaInformation,
      SystemLoadAndCallImage,
      SystemPrioritySeparation,
      SystemNotImplemented10,
      SystemNotImplemented11,
      SystemInvalidInfoClass2,
      SystemInvalidInfoClass3,
      SystemTimeZoneInformation,
      SystemLookasideInformation,
      SystemSetTimeSlipEvent,
      SystemCreateSession,
      SystemDeleteSession,
      SystemInvalidInfoClass4,
      SystemRangeStartInformation,
      SystemVerifierInformation,
      SystemAddVerifier,
      SystemSessionProcessesInformation
    );
    LARGE_INTEGER = record
      case Boolean of
        True:  (LowPart, HighPart: Cardinal);
        False: (QuadPart: Int64);
    end;
    UNICODE_STRING = record
      Length, MaximumLength: USHORT;
      Buffer: PWCHAR;
    end;
    VM_COUNTERS = record
      PeakVirtualSize: ULONG;
      VirtualSize: ULONG;
      PageFaultCount: ULONG;
      PeakWorkingSetSize: ULONG;
      WorkingSetSize: ULONG;
      QuotaPeakPagedPoolUsage: ULONG;
      QuotaPagedPoolUsage: ULONG;
      QuotaPeakNonPagedPoolUsage: ULONG;
      QuotaNonPagedPoolUsage: ULONG;
      PagefileUsage: ULONG;
      PeakPagefileUsage: ULONG;
    end;
    IO_COUNTERS = record
      ReadOperationCount: LARGE_INTEGER;
      WriteOperationCount: LARGE_INTEGER;
      OtherOperationCount: LARGE_INTEGER;
      ReadTransferCount: LARGE_INTEGER;
      WriteTransferCount: LARGE_INTEGER;
      OtherTransferCount: LARGE_INTEGER;
    end;
    CLIENT_ID = record
      UniqueProcess: HANDLE;
      UniqueThread: HANDLE;
    end;
    THREAD_STATE = (
      StateInitialized,
      StateReady,
      StateRunning,
      StateStandby,
      StateTerminated,
      StateWait,
      StateTransition,
      StateUnknown
    );
    KWAIT_REASON = (
      Executive,
      FreePage,
      PageIn,
      PoolAllocation,
      DelayExecution,
      Suspended,
      UserRequest,
      WrExecutive,
      WrFreePage,
      WrPageIn,
      WrPoolAllocation,
      WrDelayExecution,
      WrSuspended,
      WrUserRequest,
      WrEventPair,
      WrQueue,
      WrLpcReceive,
      WrLpcReply,
      WrVirtualMemory,
      WrPageOut,
      WrRendezvous,
      Spare2,
      Spare3,
      Spare4,
      Spare5,
      Spare6,
      WrKernel
    );
    SYSTEM_THREADS = record
      KernelTime: LARGE_INTEGER;
      UserTime: LARGE_INTEGER;
      CreateTime: LARGE_INTEGER;
      WaitTime: ULONG;
      StartAddress: PVOID;
      ClientId: CLIENT_ID;
      Priority: KPRIORITY;
      BasePriority: KPRIORITY;
      ContextSwitchCount: ULONG;
      State: THREAD_STATE;
      WaitReason: KWAIT_REASON;
    end;
    SYSTEM_PROCESSES = record
      NextEntryDelta: ULONG;
      ThreadCount: ULONG;
      Reserved1: array[1..6] of ULONG;
      CreateTime: LARGE_INTEGER;
      UserTime: LARGE_INTEGER;
      KernelTime: LARGE_INTEGER;
      ProcessName: UNICODE_STRING;
      BasePriority: KPRIORITY;
      ProcessId: ULONG;
      InheritedFromProcessId: ULONG;
      HandleCount: ULONG;
      Reserved2: array[1..2] of ULONG;
      VmCounters: VM_COUNTERS;
      case Boolean of
        True:  (
          IoCounters: IO_COUNTERS;
          Threads2k: array [0..0] of SYSTEM_THREADS );
        False: (
          Threads: array [0..0] of SYSTEM_THREADS );
    end; PSYSTEM_PROCESSES = ^SYSTEM_PROCESSES;
  const
    STATUS_INFO_LENGTH_MISMATCH: NTSTATUS = $C0000003;
  function NtQuerySystemInformation
  (
    SystemInformationClass: SYSTEM_INFORMATION_CLASS;
    var SystemInformation;
    SystemInformationLength: ULONG;
    out ReturnLength: ULONG
  ): NTSTATUS; stdcall external 'NTDLL.DLL';
  function RtlCompareUnicodeString(
    var String1: UNICODE_STRING;
    var String2: UNICODE_STRING;
    CaseInSensitive: BOOLEAN
  ): LONG; stdcall external 'NTDLL.DLL';
  procedure RtlInitUnicodeString(
    var DestinationString: UNICODE_STRING;
    const SourceString: PWCHAR
  ); stdcall external 'NTDLL.DLL';
  function NT_SUCCESS(Status: NTSTATUS): Boolean;
  begin
    Result:= (Status and $80000000) = 0;
  end;
  var
    ProcsBuf: PSYSTEM_PROCESSES;
    Process: UNICODE_STRING;    
    bufLen: ULONG;
    status: NTSTATUS;
begin
  // 65536 bytes buffer
  bufLen:= $10000;
  ProcsBuf:= nil;
  repeat
    // (re)allocate buffer
    ReallocMem(ProcsBuf, bufLen);
    // enumerate processes and threads
    status:= NtQuerySystemInformation(
      SystemProcessesAndThreadsInformation,
      ProcsBuf^,
      bufLen,
      PULONG(nil)^
    );
    // duplicate buffer size
    bufLen:= bufLen + bufLen;
  // repeat until the buffer is large enough
  until status <> STATUS_INFO_LENGTH_MISMATCH;
  // check for failure
  if not NT_SUCCESS(status) then
    Exit;
  // initialize UNICODE_STRING for wanted process name
  RtlInitUnicodeString(Process, 'calc.exe');
  repeat
    if RtlCompareUnicodeString(Process, ProcsBuf.ProcessName, True) = 0 
then begin
      // process found - write PID and exit
      WriteLn(ProcsBuf.ProcessId);
      Exit;
    end;
    // no more processes
    if ProcsBuf.NextEntryDelta = 0 then
      Exit;
    // go to next process
    ProcsBuf:= PSYSTEM_PROCESSES(ULONG(ProcsBuf) + 
ProcsBuf.NextEntryDelta);
  until False;
end.
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!

 end.
Gesù che codice lunghissimo! Ma regola anche il microonde in base al cibo
che inserisco automaticamente?!?!?!?! :-DDD
GRazie mille...lo proverò in alternativa con la'ltro codice postato. :)
--
Giulio Pipitone (
www.FIGHTERS4WEB.COM
)
#mirror italiano ufficiale 
http://spam.abuse.net#

 al cibo che inserisco automaticamente?!?!?!?! :-DDD
fa parte di una unit per FreePascal che sto scrivendo. In realtà si 
poteva ridurre di molto, semplicemente mettendo i valori direttamente, 
anzichè le costanti, ma ci avresti capito ancora meno
