Przechwycenie void *zmienna z kailleraclient.dll jako string i zapis do pliku.

0

Cześć.

Zwykle radze sobie sam. Ale mam problem ponieważ dllka, którą Hookuje jest w C++. I nie bardzo radzę sobie z podstawieniem typów. Oryginalny opis rzecze to co poniżej:

  /*  
     kailleraModifyPlayValues: 
     You must call this method at every frame after you retrieved values from your input devices. 
     This method will record/bufferize the values you send in and will manage to mix them with  
     the other players. 
 
     Basically, each players sends his values and receive all players values concatened. 
 
     e.g: 
     t   - player 1 sends "867F"            - player 2 sends "964F" 
     t+1 - player 1 receives "867F964F"     - player 2 receives "867F964F" 
 
     you may want to look at the modified MAME source code available on kaillera's home page 
     to have a working example out of this (look in inptport.c) 
 
     Ideally, your input values should be defined like 1 bit for a given key, which has to be  
     unset when the key is not pressed and set when the key is pressed. 
 
     The size of the values you pass to this function is the size for ONE player's values. 
     Also, it must be the SAME for a given game and should be kept to a minimum (for network  
     speed and latency issues). 
 
     Be sure that the values parameters has enough space for receiving all inputs from all players 
     (8 players max.) 
 
     returns: length received or -1 on network error (player no more in the game) 
  */ 
  DLLEXP kailleraModifyPlayValues(void *values, int size); 

I teraz mam taki kod pod Delphi. Do pliku zapisuje się w kolejnych wierszach wielokrotnie liczba 2. I teraz pytania.

Czy dobrze zadeklarowałem values jako typ PChar? Jeśli nie, to jak powinno to wyglądać pod Delphi 7. I w jaki sposób zapisać to, co będzie zawierała ta zmienna, jako string do pliku tekstowego z logiem?

function SaveOrAppendTextToFile(AFileName : string; InStr : string; AppendFile : boolean) : boolean;
const
  Append_Arr : array[boolean] of DWORD = (CREATE_ALWAYS, OPEN_ALWAYS);
var
  OutFile : THandle;
  BytesWritten : DWORD;
  OutFileSize : integer;
begin
  OutFile := CreateFile(PChar(AFileName), GENERIC_WRITE,
    FILE_SHARE_READ, nil, Append_Arr[AppendFile], FILE_ATTRIBUTE_NORMAL, 0);
  Result := OutFile <> INVALID_HANDLE_VALUE;
  if Result then
  begin
    OutFileSize := Length(InStr);
    if AppendFile then
    begin
      FileSeek(OutFile, 0, FILE_END);
    end;
    WriteFile(OutFile, InStr[1], OutFileSize, BytesWritten, nil);
    CloseHandle(OutFile);
  end;
end;

procedure Hooked_kailleraModifyPlayValues(values : PChar; Size : integer); stdcall;
type
  TOriginal_kailleraModifyPlayValues = procedure(values : PChar; Size : integer); stdcall;
var
  LogFileName : string;
begin
  Hook[5].UnHook;
  TOriginal_kailleraModifyPlayValues(Hook[5].BaseAddr)(values, Size);
  LogFileName := 'D:\test.log';
  SaveOrAppendTextToFile(LogFileName, IntToStr(Size) + #13#10, FileExists(LogFileName));
  Hook[5].Hook;
end;

Pytam, gdyż chcę zobaczyć w formie "namacalnej" co wysyła emulator gier, do którego kodu nie mam dostępu. A nawet jakbym miał, to pewnie był by on raczej w C++, który to język - jak wiecie - słabo toleruje. I praktycznie nie znam. Natomiast kombinacje z zapisem values na różne sposoby, powodowały, że otrzymywałem pusty string. To tyle. Z góry dziękuję za pomoc. I przykłady kodów źródlowych w Delphi pod WinAPI.

1

Jak tak patrzyłem po internetach w poszukiwaniu tej kailleraModifyPlayValues to zauważyłem, że przesyłane przy jej pomocy są raczej tablice czy struktury, a nie ciągi znaków.
Przykładowo:

	/* initialize randomizer agreed by all players */
	random[0] = time(0) & 0xff;
	random[1] = random[2] = random[3] = 0x00;
	length = kailleraModifyPlayValues(&random, sizeof(random[0]));
	if (length < 0) {
		goto release;
	}

Więc może raczej przechwytuj tablicę bajtów i do logu zapisuj ją w formie hexów? (0D AA FF...)

0

player 1 receives "867F964F"

To prawdopodobnie oznacza 4 bajty $86,$7F,$96,$4F a nie stringa '867F964F'.

0

void *values to chyba zwykły pointer jest.

0

To powinienem zrobić jakiś własny typ jako array[0..3] of Byte? Prosił bym o doprecyzowanie przykładem kodu.

0

Ja bym zrobił po prostu:

Var Data: PByte;
Begin
 Data := AllocMem(3);

 Data[0] := Random(50);
 Data[1] := Random(100);
 Data[2] := Random(150);

 kailleraModifyPlayValues(Data, 3);

 {...}
End;
0

@Patryk27 - a czy ta instrukcja:

length = kailleraModifyPlayValues(&random, sizeof(random[0]));

nie służy przypadkiem do zapisu tylko pierwszego pola macierzy? Już dawno nie pisałem w C++, ale ten sizeof(random[0]) sugeruje, że przekazane do parametru zostaną dane, rozpoczynające się od początku macierzy, a ich ilość określa rozmiar pierwszego pola macierzy; Czyli według mnie przekazana zostanie wartość z random[0] o rozmiarze sizeof(time), bo takie rzutowanie użyto w inicjalizacji; time to funkcja, nie rzutowanie (pomyliłem kolejność nawiasów), więc trzeba sprawdzić co zwraca ta funkcja;

Druga sprawa to typ argumentu - jak zauważył @babubabu, powinieneś użyć zwykłego **Pointer**a, dlatego że typ parametru w oryginalnym kodzie nie wskazuje na wskaźnik konkretnego typu;

Ale to tylko przypuszczenia, dlatego że tak jak wspomniałem - dawno pisałem w C++ i już większość zapomniałem;


olesio napisał(a)

To powinienem zrobić jakiś własny typ jako array[0..3] of Byte? Prosił bym o doprecyzowanie przykładem kodu.

Według mnie musisz użyć typu o rozmiarze dokładnie takim samym, jak zwracany typ z funkcji time z oryginalnego kodu; No i przekazać tylko jeden (pierwszy) element tablicy; Chyba że time to funkcja... :D

0
furious programming napisał(a):

@Patryk27 - a czy ta instrukcja:

length = kailleraModifyPlayValues(&random, sizeof(random[0]));

nie służy przypadkiem do zapisu tylko pierwszego pola macierzy?

No tak - zauważ, że reszta jest przecież tak czy siak wyzerowana :P

0

Dzięki Patrykowi wiem już jak miałbym to sam wysłać. A u mnie ogarnia to sam emulator. Ja chcę natomiast to prawidłowo odczytać pod Delphi. Sorry, że lamię ale z C++ nie jestem, jak pewnie wiecie "za pan brat" :/

0
procedure kailleraModifyPlayValues(values:pbyte; size:integer);

Pod wskaźnikiem values masz size bajtów danych, od values[0] do values[size-1].

0

@olesio: Tak jak babubabu napisał void *values oznacza zwykły Pointer. Niestety nie daje to informacji co tam tak naprawdę jest przesyłane. Najlepiej użyj debuggera typu OllyDbg albo IDA i zobacz skąd i jakie dane są tam przekazywane. Z samego opisu ciężko to wywnioskować.

0

Ok, dziękuję za wszystkie odpowiedzi. Później pokombinuje tak, jak doradził @Azarien. Ponieważ póki co mam takiego śpiocha. Chyba przez niestabilną pogodę, że nie chce się mi nic kodzić w tym momencie.

0
kailleraModifyPlayValues(void *values, int size);
kailleraModifyPlayValues(values : Pointer; size : integer);

a wlasciwie, chyba

function kailleraModifyPlayValues(values : Pointer; size : integer) : integer

PChar moglbys uzyc jakbys mial char*, PSTR albo LPSTR

1 użytkowników online, w tym zalogowanych: 0, gości: 1