[C++] GetPrivateProfileString

02/05/2012 17:52 » Fabi202cool#1
moin,
habe derzeit ein Problem mit "GetPrivateProfileString", bis jetzt habe ich den Pointer für ein Spiel immer mit
Code:
int pNetwork = 0x10731E08;
deklariert. Jetzt möchte ich aber, das der Pointer von einer ini Datei geladen wird. Bis jetzt ist das Spiel mit dem geladenen Pointer immer abgestürtzt...

Quote:
char buffer[10];

GetPrivateProfileStringA("Pointer","_pNetwork","0x 10731E08",buffer,10,"C:\settings.ini");
int BaseAddress = atoi(buffer);
Base = *(int*)(BaseAddress);
Ich hoffe ihr könnt mir helfen...
Fabi
02/05/2012 18:52 jacky919#2
Er liest die Zahl vermutlich nur bis zum "x" ein.
Quote:
0xDEADBEEF
Deswegen wir dein Pointer 0 sein, was das Spiel wiederum zum Absturz bringt.
Abhilfe wuerde die dezimale Schreibweise schaffen oder du laesst das "0x" weg.
02/05/2012 19:13 KDeluxe#3
Benutze doch gleich GetPrivateProfileInt.

Code:
UINT Base = GetPrivateProfileInt("Pointer", "_pNetwork", 0, "C:\settings.ini");
Der Inhalt der "settings.ini" sollte dabei so aussehen:
Code:
[Pointer]
_pNetwork=0x10731E08
Du könntest es aber so machen wie damals und das Programm die Adressen suchen lassen.
Ich hab mir mal eine kleine .dll erstellt und es getestet. Das kam dabei raus (aktueller GER Stand):
Code:
_pNetwork: 10731E08
_pUIMgr: 0
g_slZone: 106F9B00
CTimer::TickQuantum: 106300E0
_pUIMgr haben sie scheinbar entfernt.
02/05/2012 20:08 » Fabi202cool#4
Danke, werde es gleich mal ausprobieren.
PS: _pUIMgr ist jetzt unter SE_Get_UIManagerPtr zu finden.
02/05/2012 20:15 Dr. Coxxy#5
Code:
DWORD LoadConfigHex(wchar_t* IniName, wchar_t* Section, wchar_t* Name, DWORD default = 0x00000000)
{
	DWORD result = default;
	wchar_t textbuffer[256];
	GetPrivateProfileString(Section, Name, L"ERROR", textbuffer, sizeof(textbuffer), IniName);
	if (wcscmp(textbuffer, L"ERROR"))
	{
		result = wcstoul(textbuffer, NULL, 0);
	}
	return result;
}
02/06/2012 13:30 » Fabi202cool#6
Ok das Lesen geht jetzt ohne Probleme wenn ich einen festen Pfad angebe wie z.B. "C:\settings.ini", ich möchte die DLL aber injizieren, deshalb habe ich den Pfad auf "settings.ini" geändert. Jetzt wird aber die settings.ini überhaupt nichtmehr geladen, sie befindet sich im selben ordner wie die DLL und im selben wie die exe in die die DLL injiziert wird...

Habe auch schon versucht den Pfad herauszufinden:
Code:
WCHAR DllPath[MAX_PATH] = {0};
	GetModuleFileNameW(((HINSTANCE)&__ImageBase), DllPath, _countof(DllPath));

	char Pfad[255];
	sprintf(Pfad,"%s\settings.ini", DllPath);
Leider auch ohne Erfolg, der Pfad ist eintweder "D" oder "E" ^^
02/06/2012 14:25 jacky919#7
Wenn sie sich in selben Verzeichnis befindet sollte es reichen nur den Dateinamen an zu geben. "C:\settings.ini" wäre ein absoluter Pfad, "settings.ini", "..\settings.ini" oder "Data\settings.ini" wären relative Pfade, weil sie relativ vom Ausführunsverzeichnis ermittelt werden.
02/06/2012 14:57 » Fabi202cool#8
Habe jetzt alle relativen Pfade getestet, jedoch immernoch der selbe Fehler...
Teste es jetzt mit:

Code:
	FILE *fp = fopen("settings.ini","r");
	if( fp ) {
	MessageBoxA(0,"Ja","",0);
	fclose(fp);
	} else {
	MessageBoxA(0,"Nein","",0);
	}
Die Injizierte DLL muss irgendeinen anderen Pfad haben...
02/06/2012 16:06 jacky919#9
Das Ausführungsverzeichnis einer injizierten DLL ist selbstverständlich, das des Prozesses in den die DLL injiziert wurde.
02/06/2012 16:09 » Fabi202cool#10
Ok, fopen findet die Datei... Das Problem war das die Exe von einem Launcher gestartet wurde, das Verzeichniss war also das Verzeichniss des Launchers. Die .ini wird aber trotzdem nicht geladen. Werde die Datei jetzt wohl manuell einlesen müssen.
02/06/2012 16:15 jacky919#11
Teste das Laden der Daten aus der .ini doch einmal einfach in der Konole und versuche dort den Fehler zu beheben. Warum das Rad neu erfinden und einen eigenen .ini Parser schreiben, wenn es nicht unbedingt nötig ist.
02/06/2012 16:59 vwap#12
Deklarier einen Pointer so:

Code:
DWORD dwPointer = *(DWORD*) 0x00000;
02/06/2012 17:13 jacky919#13
Quote:
Originally Posted by Headpuster View Post
Deklarier einen Pointer so:

Code:
DWORD dwPointer = *(DWORD*) 0x00000;
Das würde aber auch direkt die Definition beinhalten, die vermutlich einen Crash verursachen würde, weil die Adresse 0x0 dereferenziert wird.
02/06/2012 17:18 link#14
Einfach mal die MSDN benutzen..
Quote:
lpFileName [in]
The name of the initialization file. If this parameter does not contain a full path to the file, the system searches for the file in the Windows directory.
Du musst also einen absoluten Pfad verwenden

Quote:
WCHAR DllPath[MAX_PATH] = {0};
GetModuleFileNameW(((HINSTANCE)&__ImageBase), DllPath, _countof(DllPath));

char Pfad[255];
sprintf(Pfad,"%s\settings.ini", DllPath);
ANSI und UNICODE zu vermischen ist keine gute Idee..
Außerdem kann das so schlecht funktionieren
GetModuleFileName -> C:\MeinOrdner\MeinProgramm.dll
sprintf -> C:\MeinOrdner\MeinProgramm.dll\settings.ini

Benutz dazwischen PathRemoveFileSpec, um "\MeinProgramm.dll" zu entfernen.
02/06/2012 18:08 KDeluxe#15
Quote:
Originally Posted by » Fabi202cool View Post
Ok das Lesen geht jetzt ohne Probleme wenn ich einen festen Pfad angebe wie z.B. "C:\settings.ini", ich möchte die DLL aber injizieren, deshalb habe ich den Pfad auf "settings.ini" geändert. Jetzt wird aber die settings.ini überhaupt nichtmehr geladen, sie befindet sich im selben ordner wie die DLL und im selben wie die exe in die die DLL injiziert wird...

Habe auch schon versucht den Pfad herauszufinden:
Code:
WCHAR DllPath[MAX_PATH] = {0};
	GetModuleFileNameW(((HINSTANCE)&__ImageBase), DllPath, _countof(DllPath));

	char Pfad[255];
	sprintf(Pfad,"%s\settings.ini", DllPath);
Leider auch ohne Erfolg, der Pfad ist eintweder "D" oder "E" ^^

Sag mir wenn ich mich irre, aber habe ich die die Lösung nicht schon 12 Stunden vor diesem Beitrag per PN beantwortet? Ich habe dir sogar zwei verschiedene Lösungsvorschläge genannt.

Nummer 1:
Code:
bool WINAPI DllMain(HINSTANCE hDllInstance, DWORD Reason, LPVOID){
	if(Reason == DLL_PROCESS_ATTACH){
		char DllPath[255];
		GetModuleFileName(hDllInstance, DllPath, 255);
		MessageBox(0, DllPath, "", 0);
	}

	return true;
}
hDllInstance könnte man als globale Variable benutzen, sodass es immer anwendbar ist. Andernfalls funktioniert noch

Nummer 2:
Code:
HMODULE GetCurrentModule(){
	HMODULE hModule;
	GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)GetCurrentModule, &hModule);

	return hModule;
}

DWORD WINAPI Thread(LPVOID lpParameter){
	char DllPath[255];
	GetModuleFileName(GetCurrentModule(), DllPath, 255);
	MessageBox(0, DllPath, "", 0);

	return 0;
}

bool WINAPI DllMain(LPVOID, DWORD Reason, LPVOID){
	if(Reason == DLL_PROCESS_ATTACH)
		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Thread, 0, 0, 0);

	return true;
}