Windows API - EnableRouter

EdwardBlack

Grünschnabel
Hallo, ich versuche mich mit der Windows API vertraut zu machen.
Zum Test versuche ich die Funktion EnableRouter zu schreiben.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365896(v=vs.85).aspx

Hier ist mein Versuch:

Code:
#include <windows.h>
#include <iphlpapi.h>

using namespace std;

HANDLE    *Handle;
OVERLAPPED *Overlapped;
DWORD ret;

int main()
{
   ret = EnableRouter(Handle, Overlapped);
   cout << "ret = " << ret << endl;

   cin.get(); cin.get();

   return 0;
}


Es wird 87 ausgegeben, gebe ich den Befehl ipconfig /all in der CMD ein, steht dort "IP Routing aktiviert . . . . Nein". Es hat also nicht funktioniert. Wer kann mir helfen?

Danke im voraus
 
Hi

87 ist ERROR_INVALID_PARAMETER
(siehe https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx)
und genau das ist bei dir auch der Fall, bzw. du verwendest die Pointer falsch.

Dein "Overlapped" kann die Adresse zu einer OVERLAPPED-Variable aufnehmen, bei dir bekommt es aber nirgends eine Adresse. Du übergibst einen Pointer zu Nirgendwo an die FUnktion. Eine echte OVERLAPPED-Variable ist zuerst einmal nötig, und damit wird der extra benamte Pointer in dem Fall überflüssig: übergib einfach "&variable" direkt an die Funktion.

Außerdem muss die OVERLAPPED-Variable zeurst initialisiert werden, laut Doku:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365896(v=vs.85).aspx
Alles außer hEvent muss 0 sein, und hEvent braucht ein gültiges Event (CreateEvent...)

PS: Verlass dich nicht darauf, bei solchen Fehlern immer nette Fehlerreturnwerte zu bekommen.
Vor allem Pointerprobleme bewirken oft ganz andere unerklärbare Sachen
(Werte von anderen Variablen, die sich selbst ändern usw.usw.)
 
Danke für deine Antwort,
ok dort steht "all members of this structure should be set to zero"

Wie ich sehe ist dort ein struct im struct, das habe ich so noch nie gesehen.

Leider ist mein Versuch die Overlapped Variable zu initialisieren gescheitert.

Code:
HANDLE    *Handle;
OVERLAPPED &Overlapped;
DWORD ret;

int main()
{
   Overlapped.Internal     = 0;
   Overlapped.InternalHigh = 0;
   Overlapped.Offset     = 0;
   Overlapped.OffsetHigh   = 0;
   Overlapped.Pointer     = 0;


   ret = EnableRouter(Handle, &Overlapped);
   cout << "ret = " << ret << endl;

   cin.get(); cin.get();

   return 0;
}

Fehlermeldung: Verweise müssen intialisiert werden
Vermutlich liegt es daran das ich mich noch nicht um hEvent gekümmert habe, da ich leider nicht weiss wie genau ich vorgehen muss.
 
Zuletzt bearbeitet:
OVERLAPPED &Overlapped;
Jetzt hast du eine Referenz auf nichts (sollte schon da Fehler ergeben)
C++:
OVERLAPPED Overlapped; //normal, das brauchst du
OVERLAPPED *Overlapped; // Pointer
OVERLAPPED &Overlapped; //Referenz
Wie genau Pointer und Referenzen funktionieren bitte nachlesen (oder ich beschreibts später),
weil das geht grad zu weit am Thema vorbei.

Der Aufruf von EnableRouter ist so in Ordnung.

Eine Struct-Variable in einem anderen Struct wäre ("wäre") kein Problem, in dem Fall hätte die innere Struct-Var aber auch einen Namen, und man kann das Ganze verschachtelt ansprechen (a.b.c.d usw.).

Hier ist aber kein Struct, sondern eine Union: Im Wesentlichen teilen sich beide Hälften innen den selben Speicher; und man kann nur immer eine Hälfte verwenden. Also entweder man verwendet "Pointer" und dafür die Offset-Variablen nicht, oder umgekehrt.
Bzw., man kann schon alle drei verwenden, aber beim Zuweisen von Werten geht der Wert vom jeweils anderen Teil kaputt (ganz genau genommen darf man mit der Verwendung nicht beliebig wechseln, weil dann noch mehr komische Sachen im Programm passieren könnten, aber auf üblichen Geräten und Betriebssystem passiert nichts)

Und hEvent fehlt noch, wie du selber schon schreibst.
 
Danke sheel, sehr lehrreich!
Ich habe es jetzt soweit hinbekommen, sollte passen, jedenfalls kann ich das Programm nun ohne Fehler aufrufen und bekomme dieses mal für ret den Wert 5 ausgegeben, was "Access denied" bedeuted.
Möglicherweise muss ich das Programm als Admin ausführen?

Code:
#include <windows.h>
#include <iphlpapi.h>
#include <iostream>

using namespace std;

HANDLE       *Handle;
OVERLAPPED Overlapped;
DWORD ret;

SECURITY_ATTRIBUTES security_test;

int main()
{
    security_test.bInheritHandle            = true;
    security_test.lpSecurityDescriptor    = NULL;
    security_test.nLength   = sizeof (SECURITY_ATTRIBUTES);

    Overlapped.Internal         = 0;
    Overlapped.InternalHigh  = 0;
    Overlapped.Offset           = 0;
    Overlapped.OffsetHigh    = 0;
    Overlapped.Pointer         = 0;
    Overlapped.hEvent  = CreateEvent(&security_test, false, true, NULL);


    ret = EnableRouter(Handle, &Overlapped);
    cout << "ret = " << ret << endl;

    cin.get(); cin.get();

    return 0;
}

Edit: Nachdem ich das Programm als Administrator gestartet habe, bekomme ich den ret value = 997 (Overlapped I/O operation is in progress.)

Das IP Routing wurde jedoch aktiviert wie ein aufruf von "ipconfig /all" zeigt :)
Wenn mir jemand sagen kann warum ich (Overlapped I/O operation is in progress.) bekomme und ob das jetzt schlimm ist, wäre ich dankbar. Kann es sein das ich ein Sleep Befehl aufrufen muss bevor ich EnableRouter aufrufe??
Edit: Nein, auch ein Sleep von 4000 ms ändert nichts.
 
Zuletzt bearbeitet:
Hi

ja, Netzwerkzeug auf der Ebene ist nicht für jeden User erlaubt.

Das 997 soll so sein: Das Aktivieren vom Routing kann je nach Situation etwas dauern, und die Funktion ist aber absichtlich so gemacht dass sie sofort fertig ist (auch wenn das Routing noch nicht fertiggestartet hat). Mit dem hEvent vom OVERLAPPED kann man dann mitverfolgen, wann das Starten fertig ist (zB. mit WaitForSingleObject einfach das Programm auf die Fertigstellung warten lassen).
Bzw. man "kann" nicht nur, man sollte das auch machen, so dass das Programm sicher erst dann beendet wird, wenn das Routing gestartet hat (keine Ahnung, ob es sonst Probleme gibt, aber besser nicht riskieren).

Nach dem Fertigwarten auf hEvent kann/soll man es mit CloseHandle auch noch freigeben.

Und beim ersten Parameter von CreateEvent (das Security-Ding) sollte NULL
übergeben werden, wenn man nichts spezifisches festlegt.

(PS: Ja, diese Bereiche der Windowsfunktionensammlung sind absichtlich umständlich :p)
 
Mir ist gerade aufgefallen das dieses ganze gedöns nicht nötig ist, da es auch ohne funktioniert.
Auch mit diesem Code funktioniert es das ipv4 forwarding einzuschalten.

C++:
#include <windows.h>
#include <iphlpapi.h>
#include <iostream>

using namespace std;

#pragma comment     (lib, "iphlpapi.lib")

OVERLAPPED Overlapped;
DWORD ret;

int main()
{

   ret = EnableRouter(NULL, &Overlapped);
   cout << "ret = " << ret << endl;

   cin.get(); cin.get();

   return 0;
}


Mit dem hEvent vom OVERLAPPED kann man dann mitverfolgen, wann das Starten fertig ist (zB. mit WaitForSingleObject einfach das Programm auf die Fertigstellung warten lassen)

Danke für die Info, werde ich gleich mal versuchen.

Edit:
Habe es mal so versucht:

C++:
int main()
{

   OVERLAPPED   Overlapped;
   DWORD     ret;

   ret = EnableRouter(myHandle, &Overlapped);
   WaitForSingleObject(myHandle, 3000);
   cout << "ret = " << ret << endl;

   cin.get(); cin.get();

   return 0;
}

Ich sehe das WaitForSingleObject ein DWORD zurückgibt, ich habe diesen ausgeben lassen und den Wert 4294967295 bekommen. Da kann doch etwas nicht korrekt sein. Ich werde mir mal die API Beschreibung genauer durchlesen.

Edit: Ich habe folgendes erfahren "The handle must have the SYNCHRONIZE access right."
Doch ich konnte leider nicht herausfinden, wie ich meinem Handle dieses Recht geben kann.
 
Zuletzt bearbeitet:
Das Problem bei C++ ist, das vieles scheinbar funktioniert,
nur später kommt man drauf dass es doch nicht immer so ist :)
Verlassen auf die Kurzvariante kann man sich nicht.

Der Returnwert ist tatsächlich nicht gut, aber vor irgendwelchen Versuchen solltest du nach der Funktion auch einmal GetLastError aufrufen und den Returnwert davon anschauen (ja, manche Funktionen lagern ihren Returnwert in andere Funktionen aus ... wie gesagt, absichtlich umständlich :D)
 
Die Funktion "GetLastError" ist extrem nützlich, danke für die Info :)
Ich habe herausgefunden das der Handle ungültig zu sein scheint (error 6), ich denke jedoch das es in diesem Fall nicht schlimm ist, denn in der Doku zu EnableRouter steht bezüglich des Handle Parameters folgendes geschrieben:
"A pointer to a handle. This parameter is currently unused."
Man könnte also meiner Meinung nach genauso gut einfach NULL übergeben.
Jedoch klappt die Funktion "WaitForSingleObject(myHandle, 3000);" somit vermutlich nicht, da ein gültiger Handle erwartet wird. Oder es liegt eben daran, das mein Handle möglicherweise nicht SYNCHRONIZE Rechte hat, da ich ja leider nicht weiss wie man dies macht.
"The handle must have the SYNCHRONIZE access right."

PS: Schon komisch das Microsoft das absichtlich so abstrakt gestaltet hat o_O?
 
Ah moment, du übergibst ja das falsche Ding :)
WaitForSingleObject ist nicht für das unbenutzte Handle gedacht, sondern für das hEvent im OVERLAPPED.

Und auch das vorher erwähnte CloseHandle ist für das Event, in dem Fall.
CloseHandle closed so ziemlich alles bei solchen Sachen, auch wenn es nie ein Handle war.
Jaja, MS.

PS: Die Sachen mit den Sync-Rechten sollten nur dann relevant werden,
wenn du Handles aus anderen Prozessen etc. verwenden willst.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück