D2010 PosEx problemi

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
dpcmsx
Üye
Mesajlar: 22
Kayıt: 06 Eyl 2011 04:25

D2010 PosEx problemi

Mesaj gönderen dpcmsx »

Herkese çok selamlar.

Daha önce bahsetmiştim, d2007'den d2010'a bir projeyi çeviriyordum. Bir sürü sorunla karşılaştım özellikle unicode ile. Neyse çoğunu hallettim fakat henüz başaramadığım bir kısım var. 3 gündür uğraştım ancak işin içinden çıkamadım.

Önce program hakkında bilgi vereyim. Bu program kullanıcının seçtiği modele göre tamamen binary olan data dosyalarında 3 - 10 yeri bulup değiştiren bir mekanizma. Kısaca kullanıcı yüklüyor, program yerleri buluyor ve gerekli değişiklikleri yapıyor, sonuçta yeni bir dosya olarak yazıyor.

İçinden çıkamadığım nokta, program Türkçe (kullandığım) Windows'da bu noktaları gayet iyi bir şekilde buluyor ve yapıyor. Ancak, diğer dillerde aşağıda belirttiğim bir tarama kodunu bulmadığını söyleyip hata veriyor. Kodun için diğerlerinde olduğu gibi 00 yok. Benim istediğim D7'de olduğu gibi ne verirsem onu araması. Dolasıyla problemin PosEx'den kaynaklandığını farkındayım ancak Codepage mi değişecek yok tanımlamada mı birşey belirtmem gerekiyor bir türlü anlamadım.

Kullanıcıdan OpenDialog1 ile aldığım dosya bilgisini aşağıdaki prosedure ile string olarak yüklüyorum:

Kod: Tümünü seç

var
  buf1 : Ansistring;

Begin

     if not sOpenDialog1.Execute then
    sMemo1.Lines.Add('File dont open!') // file dont opened
    else
  begin
    buf1 := LoadStringFromFile(sOpenDialog1.FileName,TEncoding.Default);
Yükleyici procedure ise :

Kod: Tümünü seç

function LoadStringFromFile(const filename: string; encoding: TEncoding = nil): string;
var
  FPreambleLength: Integer;
begin
  with TBytesStream.Create do
  try
    LoadFromFile(filename);
    FPreambleLength := TEncoding.GetBufferEncoding(Bytes, encoding);
    Result := encoding.GetString(Bytes, FPreambleLength, Size - FPreambleLength);
  finally
    Free;
  end;
end;

Sonra program "case of nn" ile seçilen kısma geliyor ve işlem başlıyor.

Kod: Tümünü seç

//---------------------------------------------------------------------------
Procedure Model253(var filebuf : Ansistring; fsize :integer; fpath :string); 
var
  s1 : Ansistring;
  c,i : integer;

begin
    s1 := 'Extended253';
   c := PosEx(s1,filebuf,1);
   if c = 0 then
    begin
    ShowMessage('Sign Error');
  end;

//Test için hazırladım, codepage bende 1254 çalışmayanlarda 1250 olarak gözüküyor.
   Form1.sMemo1.Lines.Add('Default Code page : ' + IntToStr(StringCodePage(filebuf)));
   Form1.sMemo1.Lines.Add('Default Element Size : ' + IntToStr(StringElementSize(filebuf)));

//Patchpro sadece işlemi kısaltıyor.
  arama :=1;
  s1 :=#$01#$01#$10#$00#$01#$01#$01#$00;
  PatchPro(filebuf,s1,$04,$00,$00,22,$00,$00,lastpos,fpath,fsize);

 arama :=2;
 s1 :=#$40#$9f#$be#$77#$40#$9f#$e7#$6d#$44;
  PatchPro(filebuf,s1,$04,$00,$00,22,$00,$00,lastpos,fpath,fsize);

Kod: Tümünü seç

Procedure PatchPro(var filebuf: Ansistring; sstr: Ansistring; pfar: integer; pval1: byte; pval2:byte; psize: integer; end1:byte; end2:byte; posnext:integer; fpath : string; fsize:integer);
var
  s1,strnew,filebufnew : string;
  c,i,mboxsel,clen : integer;

begin 
...
  posnext := lastpos;
    c := PosEx(sstr,filebuf,posnext);
    if c = 0  then
    begin
    Form1.Memo1.Lines.add('Error '+IntToStr(arama)+ 'not found' +IntToHex(posnext,8));
    end;
...
// işlem tamamsa dosyayı değiştiriliyor.

Burada garip çözemediğim olay şudur :

Aranan 2 tane kod dizilimi var : Arama1 : 01 01 10 00 01 01 01 00 ve Arama2 : 40 9f be 77 40 9f e7 6d 44.

- 1. arama hiç sorunsuz oluyor ve işlem başarıyla yapılıyor. Fakat 2. aramaya gelince belirtilen kod olduğu halde bulamadım diyor hata veriyor (Türkçe Windows ve hepsinde).

- Eğer 2. arama için farklı bir dizilim verirsem örneğin : 44 7a 00 00 44 61 00 00 başarıyla buluyor ve yapıyor. Fakat programda yüzden fazla bölüm var ve hepsini değiştirmek çok fazla zaman istiyor.

Sorunun iyice araştırmak için debugger ile tek tek inceledim. Gördüm ki, 2 aramada PosEx'e giren çalışmayan kod dizilimi değişiyor ve farklı bir şey aratılıyor.

Bu noktada ne yapmak gerekiyor ki PosEx Delphi7'de olduğu gibi her verdiğimi aynı şekilde arasın? Görüldüğü gibi eğer aranan dizin içinde 00 01 değerleri varsa PosEx arama string'ini aynen alıp kullanıyor ama 2 dizilim gibi olunca bunu (unicode değil) farklı bir şekile çevirip aramaya çalışıyor.

Delphi2010'un Unicode olduğunu biliyorum fakat nerede ne hata yaptığımı maalesef çözemedim.

Yardımlarınızı ve önerilerinizi bekliyorum.

Saygılar ve sevgiler.
Kullanıcı avatarı
warder
Üye
Mesajlar: 255
Kayıt: 10 Mar 2004 04:59

Re: D2010 PosEx problemi

Mesaj gönderen warder »

Öncesinde yaptığınız hatalar olabilir.

Kod: Tümünü seç

function LoadStringFromFile(const filename: string; encoding: TEncoding = nil): string;
fonksiyonunuzu güzel tanımlamışsınız.
encoding: TEncoding = nil istenilen şekilde...
Ancak kullanırken parametre olarak nil durumunu bozup Default göndermişsiniz.
Sistem default encoding her neyse onu parametre yapmışsınız. Dolayısıyla preamble olarak onu ölçüyorsunuz.
Oysa burda..

Kod: Tümünü seç

FPreambleLength := TEncoding.GetBufferEncoding(Bytes, encoding);
encoding in NULL olması gerekiyor ki bilinmeyen encoding i bulsun.
...
Kodunuzun vermediğiniz kısımlarında Stream kullanıyorsanız kendisini yanıltmaya çalıştığınızdan hata fırlatıp görevi sonlandırıyordur.
Global bir hata deneteleyicisinde fırlatılan hataları toparlayabilirsiniz.
Yanlış hatırlamıyorsan EEncodingError hatası gönderiyor olmalı....
Buraya kadar doğruysa bundan sonrası yolunuzu belirleyecektir.
... Muhtaç olduğun kudret, damarlarındaki asil kanda mevcuttur!
Mustafa Kemal Atatürk...
dpcmsx
Üye
Mesajlar: 22
Kayıt: 06 Eyl 2011 04:25

Re: D2010 PosEx problemi

Mesaj gönderen dpcmsx »

Teşekkürler sayın Warder;

Söz konusu procedure direk olarak internetten alıntı yaptım. Aslında FileStream kullanıyorum ve stream ile alınan binary dosya bilgisinin string olarak aktarıyorum. Bu prosederü kullanma nedenim TEncoding ile yüklenen dosyayı conversion yapabilme ve test edebilmedir. Zira D7 ile kullandığım FileStream D2010'da tamamen yanlış bir buffer veriyor. Dosyayı yükleyip Ansi olarak string'e atmak için Stream'dan API yollarına kadar hepsini denedim. Fakat en iyi sonucu bu prosedure ile alabildim. Zira diğerlerinde (örneğin Array ile) programın bütün yapısını değiştirmem gerekiyor.

Ollydebug ile ve sanal makinada kurulu Slovakça Windows'u inceledim. Aynı zamanda Türkçe Windows yüklü sistemde de adım adım takip ettim. Dosya yükleme Türkçe Windows'da Ansi kurallarına göre oluyor ama Ansi tanımlamış olsak bile bütün stringler yine de Unicode şekline çevriliyor.

Öz eleştiri yapmam gerekirse Unicode konusunu tam anlamadığımı ve anlamadan böyle detaylı bir çevrime başladığımı düşünüyorum. Forumlarda ve bloglarda String --> AnsiString ve Char--> AnsiChar yapın herşey tamam denilmiş. Fakat göründüğü kadar basit değilmiş. Sorunu anlayamama nedenlerimden birisi ise 1 aramanın olması amap 2. aramanın Türkçe dışındaki Windows sürümlerinde hata vermesi. Devam eden 3 ve 4 aramaları da başarıyla sonuçlanıyor. Ancak 2. aramada olan hata dosya yapılan işlemin doğruluğunu ortadan kaldırıyor. Bu sadece bir örnek, asıl programda 120 civarında böyle arama - değiştirme prosedure mevcut. Bunları tamamen değiştirmem çok uzun zaman alır. Dolasıyla D7 ile çalıştığı sistemden düzeltmeye çalıştım.

Programın prototipini kaynak koduyla aşağıya yükledim. Türkçe bir Windows ile denerseniz hepsini bulacak. Ama başka bir dilde Windows ile denerseniz 2. arama hata verecek. Hemde TEncoding Default page olduğu halde. Çözemediğim tek sorun bu maalesef. Bu da benim Unicode konusunda yetersiz bilgim olmasından kaynaklanıyor.

Tavsiye ettiğiniz gibi TEncoding parametresini NULL yaptım ancak 1. arama hariç diğerleri hata verdi.


Türkçe Windows ile :

Found : OBD_YD25
Search1 Found : 000902FE
Search2 Found : 00095661
Search3 Found : 000E1CA5
Search4 Found : 000E27FB

Slovakça yada diğer dilde Windows ile
Found : OBD_YD25
Search1 Found : 000902FE
Search2 Error : 000000000
Search3 Found : 000E1CA5
Search4 Found : 000E27FB
http://www.ecudecoder.com/popup/temp/UniTest2.rar

Selamlar.
Kullanıcı avatarı
warder
Üye
Mesajlar: 255
Kayıt: 10 Mar 2004 04:59

Re: D2010 PosEx problemi

Mesaj gönderen warder »

Delphi ile Builder aynı kütüphanelerden beslendiği için fikir yürütmeye çalışıyorum. Yoksa delphi ile program yazmışlığım yok. Kullandığım sürümün delphi kısmını da yüklemiyorum.
Ancak..
Kodunuzda Encoding Convert ile ilgili bir işlem görmedim.

Kod: Tümünü seç

Result:= TEncoding.ASCII.GetString(Bytes);
............
Aşağıdaki bağlantıdaki kodu bir inceleyin.
TEncoding (Delphi)
burada convert gerçekleşiyor.

Kod: Tümünü seç

LBuffer := LEncoding.Convert(LEncoding, DestEncoding, LBuffer,
      LOffset, Length(LBuffer) - LOffset);
Her Encode için karakter kodlamaları ascii 127 üstünde farklılık göstermeye başlıyor.
Arama yapyığınız hex karşılıkları farklı encode değerleri için farklı ise bu durumu kodunuzda işlemeniz gerekir.
Kaçış kısayolu veya tavsiyesi olarak nacizane... utf16 yapıp öyle kullanın. Convert işlemini utf16 için gerçekleştirip hemen her kodlamayı kapsarsınız.
... Muhtaç olduğun kudret, damarlarındaki asil kanda mevcuttur!
Mustafa Kemal Atatürk...
Cevapla