DelphiSiWin32

Win32 api funkcije.
Odgovori
GJ
Prispevkov: 1078
Pridružen: 13.03.2004 12:34:48

DelphiSiWin32

Odgovor Napisal/-a GJ » 30.04.2008 12:34:04

Evo sem pogledu kaj sem jaz do sedaj rabu..:P

Koda: Izberi vse

  
function TestCX8: Boolean;
//CPU cmpxchg8b instruction support test  (Minimun level is Pentium2 )
//eax = Result
asm
  push          ebx
  mov           eax, 1
  cpuid
  bt            edx, 8
  setc          al
  movzx         eax, al
  pop           ebx
end;

function AtomicCmpXchg64(var Dest64: Int64; const CmpValue64, NewValue64: Int64) :Boolean;
{
begin
  if CmpValue64 = Dest64 then
  begin
    Dest64 := NewValue64;
    Result := True;
  end else
    Result := False;
}
//eax = Result
asm
  push          ebx
  push          edi
  mov           edi, Dest64
  mov           eax, dword ptr[CmpValue64]
  mov           edx, dword ptr[CmpValue64 + 4]
  mov           ebx, dword ptr[NewValue64]
  mov           ecx, dword ptr[NewValue64 + 4]
  lock cmpxchg8b [edi]
  setz          al
  movzx         eax, al
  pop           edi
  pop           ebx
end;

function AtomicXchg64(var Dest64; const Source64: Int64): Int64;
{
begin
  Result := Dest64;
  Dest64 := Source64;
end;
}
//edx:eax = Result
asm
  push          ebx
  push          edi
  mov           edi, Dest64
  mov           ebx, dword ptr[Source64]
  mov           ecx, dword ptr[Source64 + 4]
@DoSpin:
  mov           eax, [edi]
  mov           edx, [edi + 4]
  lock cmpxchg8b [edi]
  jnz           @DoSpin
  pop           edi
  pop           ebx
end;

function AtomicIncXchg64(var Dest64; const Num64: Int64 = 1): Int64;
{
begin
  Result := Dest64;
  Dest64 := Dest64 + Num64;
end;
}
//edx:eax = Result
asm
  push          ebx
  push          edi
  mov           edi, Dest64
@DoSpin:
  mov           eax, [edi]
  mov           edx, [edi + 4]
  mov           ebx, dword ptr[Num64]
  mov           ecx, dword ptr[Num64 + 4]
  add           ebx, eax
  adc           ecx, edx
  lock cmpxchg8b [edi]
  jnz           @DoSpin
  pop           edi
  pop           ebx
end;

function AtomicDecXchg64(var Dest64; const Num64: Int64 = 1): Int64;
{
begin
  Result := Dest64 ;
  Dest64 := Dest64 - Num64;
end;
}
//edx:eax = Result
asm
  push          ebx
  push          edi
  mov           edi, Dest64
@DoSpin:
  mov           ebx, [edi]
  mov           ecx, [edi + 4]
  mov           eax, ebx
  mov           edx, ecx
  sub           ebx, dword ptr[Num64]
  sbb           ecx, dword ptr[Num64 + 4]
  lock cmpxchg8b [edi]
  jnz           @DoSpin
  pop           edi
  pop           ebx
end;
Če ti kaj prav pride predeli..

LP :D GJ
Kdor se zadnji smeje, se smeje zadnji!

gabr
Prispevkov: 4129
Pridružen: 28.08.2001 14:10:47

DelphiSiWin32

Odgovor Napisal/-a gabr » 18.08.2008 10:34:47

Tiburon. Eh, problemi :(

DSiWin32 ima kar nekaj funkcij, ki dinamično linkajo Win32 DLLje. Recimo DSiLogonUser, ki naloži LogonUserA.

No, zdaj je treba zadevo spravit v Delphi 2009. Moje mnenje je, da moram DSiLogonUser popravit, da bo uporabljal LogonUserW. Potem se bo zadeva obnašala tako kot so se spremenile druge funkcije v Tiburonu (vse je avtomatsko ratalo Wide).

Ne vem pa, če se splača še definirat DSiLogonUserA in DSiLogonUserW, ki bi bila neodvisna od platforme. Kaj menite?

Gp

Miha-R
Prispevkov: 2155
Pridružen: 14.05.2001 21:29:53

DelphiSiWin32

Odgovor Napisal/-a Miha-R » 18.08.2008 12:18:20

DsiLogonUser ima problem s parametri, ki so samo prepisani iz APIja. Jaz bi tako funkcijo spremenil nekako takole:

Koda: Izberi vse

function DSiLogonUser(UserName, Domain, Password: string;
  LogonType, LogonProvider: LongWord; var Token: THandle): Boolean;
Argument za tako spremembo imaš v DSiExecuteAsUser, kjer delaš konverzijo iz stringa v PChar ravno zaradi tako definiranih parametrov.
Ne vem pa, če se splača še definirat DSiLogonUserA in DSiLogonUserW, ki bi bila neodvisna od platforme. Kaj menite?
Ne vidim vzroka, zakaj bi bilo potrebno. Če imaš parametre definirane kot string, bodo v starih verzijah delovali kot AnsiString, od D2009 dalje pa kot UnicodeString.
Zadnjič spremenil Miha-R, dne 18.08.2008 12:19:26, skupaj popravljeno 1 krat.
Vedno sem želel napisati prav tak odgovor.

Uporabniški avatar
Lipe
Prispevkov: 232
Pridružen: 12.10.2005 11:31:25
Kraj: Kranj

DelphiSiWin32

Odgovor Napisal/-a Lipe » 16.12.2008 08:23:08

Ko uporabim funkcijo DSiDeleteWithBatch(), na direktoriju ostanejo datoteke kot spodaj, za vsak klic funkcije po ena. Brisanje sem izvajal na Temp direktoriju uporabnika (C:\Documents and Settings\[User]\Local Settings\Temp\) in tam so te datoteke tudi ostale. Delphi 2007, Windows 2003 Server. Bug morda?

12.12.2008 08:40 0 wt8F0.tmp
12.12.2008 08:48 0 wt8F3.tmp
12.12.2008 08:50 0 wt8F4.tmp
Nič ni nič, pa tudi nekaj ni bogve kaj.

gabr
Prispevkov: 4129
Pridružen: 28.08.2001 14:10:47

DelphiSiWin32

Odgovor Napisal/-a gabr » 16.12.2008 09:10:27

Po moje manjkajo narekovaji. DSiDeleteWithBatch naredi batch file, ki na koncu zbriše samega sebe, ampak svojega imena ne da v narekovaje. Ti pa imaš v potki presledke in ga to usuje.

V DSiDeleteWithBatch imaš kodo

if rmDir
then Writeln(bat,'rmdir "',ExtractFilePath(fileName),'"');
Writeln(bat,'del ',tmpFile);
Close(bat);

Poskusi jo spremenit v

if rmDir
then Writeln(bat,'rmdir "',ExtractFilePath(fileName),'"');
Writeln(bat,'del "',tmpFile,'"');
Close(bat);

in poročaj.

Gp

Uporabniški avatar
Lipe
Prispevkov: 232
Pridružen: 12.10.2005 11:31:25
Kraj: Kranj

DelphiSiWin32

Odgovor Napisal/-a Lipe » 16.12.2008 12:56:53

OK, kodo popravim po navodilih:
Writeln(bat,'del "',tmpFile,'"');
Vendar ni nobene razlike.

Če tik pred brisanjem pogledam datoteke, je stanje tako:

wtFCB.bat
wtFCB.tmp, velikost 0

Vsebina wtFCB.bat:

:repeat
del "C:\DOCUME~1\userx\LOCALS~1\Temp\test.txt"
if exist "C:\DOCUME~1\userx\LOCALS~1\Temp\test.txt" goto repeat
del "C:\DOCUME~1\userx\LOCALS~1\Temp\wtFCB.bat"

Narekovaji zgleda niti niso potrebni, ker DSiGetTempFileName vrne ime direktorija v kratki obliki.

Če spremljam datoteke med izvajanjem funkcije, je pa takole:

Datoteka tmp se pojavi takoj po klicu
tmpFile := ChangeFileExt(DSiGetTempFileName('wt'),'.bat');

Čudno, ampak bat datoteke v tem trenutku še ni, samo tmp. Bat se pojavi po izvršitvi vrstice
Rewrite(bat);
Vendar tmp z velikostjo 0 ostane. Nimam pa pojma, če med step-by-step izvrševanjem sploh vidim pravo stanje na disku.

V nadaljevanju batch datoteka lepo izbriše cilj in samo sebe, ampak tmp pa ostane.

Sicer pa je na temp direktoriju še ene par tisoč datotek raznih velikosti. Tako da je tale malenkost pomembna samo za perfekcioniste. Vsi pa vemo, da je Gabr perfekcionist.
Nič ni nič, pa tudi nekaj ni bogve kaj.

gabr
Prispevkov: 4129
Pridružen: 28.08.2001 14:10:47

DelphiSiWin32

Odgovor Napisal/-a gabr » 16.12.2008 16:14:24

Ahhhhh, zdaj mi je šele potegnilo. Tmpfile nastane ko koda pokliče DSiGetTempFileName. Potem samo zamenja ime v .bat, ampak temp file pa pusti na miru. Eh.

Probaj tako (untested):

Koda: Izberi vse

  function DSiDeleteWithBatch(const fileName: string; rmDir: boolean): boolean;
  // Idea stollen from the article by Jeffrey Richter, first published in
  // Microsoft Systems Journal, reprinted in Microsoft Developer Network.
  // Simple but effective solution: create batch file that deletes exe and then
  // deletes itself, then run it as an invisible console app with low priority.
  var
    bat    : text;
    pi     : TProcessInformation;
    si     : TStartupInfo;
    tmpFile: string;
    winTemp: string;
  begin
    Result := false;
    try
      winTemp := DSiGetTempFileName('wt');
      if winTemp <> '' then begin
        tmpFile := ChangeFileExt(winTemp, '.bat');
        MoveFile(PChar(winTemp), PChar(tmpFile));
        Assign(bat, tmpFile);
        Rewrite(bat);
        Writeln(bat,':repeat');
        Writeln(bat, 'del "', fileName, '"');
        Writeln(bat, 'if exist "', fileName, '" goto repeat');
        if rmDir then
          Writeln(bat,'rmdir "', ExtractFilePath(fileName), '"');
        Writeln(bat,'del "', tmpFile, '"');
        Close(bat);
        FillChar(si, SizeOf(si), 0);
        si.cb := SizeOf(si);
        si.dwFlags := STARTF_USESHOWWINDOW;
        si.wShowWindow := SW_HIDE;
        if (CreateProcess(nil, PChar(tmpFile), nil, nil, false,
          CREATE_SUSPENDED or IDLE_PRIORITY_CLASS, nil,
          PChar(ExtractFilePath(tmpFile)), si, pi)) then
        begin
          SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE);
          CloseHandle(pi.hProcess);
          ResumeThread(pi.hThread);
          CloseHandle(pi.hThread);
          Result := true;
        end;
      end;
    except end;
  end; { DSiDeleteWithBatch }

Uporabniški avatar
Lipe
Prispevkov: 232
Pridružen: 12.10.2005 11:31:25
Kraj: Kranj

DelphiSiWin32

Odgovor Napisal/-a Lipe » 18.12.2008 14:31:35

Da, zdaj zadeva pravilno deluje, datoteke več ne ostajajo.
Nič ni nič, pa tudi nekaj ni bogve kaj.

Uporabniški avatar
Lipe
Prispevkov: 232
Pridružen: 12.10.2005 11:31:25
Kraj: Kranj

DelphiSiWin32

Odgovor Napisal/-a Lipe » 18.06.2009 11:23:25

Oni dan sem dobil nalogo, da ugotovim, ali na sistemu teče program in če teče, ga postavim v ospredje in prikažem. Znano je bilo pa samo ime izvršne datoteke tega programa. Naročniku sem rekel, da je to mala malica, da bo naslednji dan gotovo. Potem pa z grozo ugotovim, da tale naša knjižnica nima ničesar na to temo. To je bil šok, a štekate?

No, sem mukoma spacal skupaj nekaj kode, ki to naredi. Najprej se je treba ukvarjati z enumeriranjem procesov, ker ima zgleda samo proces informacijo o izvršni datoteki. Nato je treba na osnovi identifikatorja procesa pridobiti handle od okna, da ga lahko dvignemo v ospredje.

Zdaj, a bi taka stvar pasala v tole knjižnico?
Nič ni nič, pa tudi nekaj ni bogve kaj.

gabr
Prispevkov: 4129
Pridružen: 28.08.2001 14:10:47

DelphiSiWin32

Odgovor Napisal/-a gabr » 18.06.2009 12:38:10

Bi. Kar se mene tiče, vse stvari ki pomagajo programerju priti od procesa do handla glavnega okna in nazaj (in podobno) sodijo v DSiWin32.

Lahko pomailaš direkt meni, pa bom vgradil.

Gp

Odgovori