[bcc32 Fehler] Keine Übereinstimmung des Parametertyps hModule, HINSTANCE__ *' erwartet



  • Hallo,
    in einer Anwendung mit c++ builder XE7 nutze ich zum Anpingen von Rechnern im Netzwerk folgenden Code (siehe auch bytesandmore-Artikel http://www.bytesandmore.de/rad/cpp/snipp/sc08012.php), der bisher (bis vor XE7) fehlerfrei compiliert wurde:

    #include <winsock.h>
    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <icmpapi.h>
    #pragma comment(lib, "iphlpapi.lib")
    #pragma comment(lib, "ws2_32.lib")
    ...
    
    int PingHost(String slAddress, TStrings* pStrings)
    {
      // Stringsliste leeren:
      if(pStrings) pStrings->Clear();
    
      // ICMP.DLL laden:
      HANDLE hIcmp = LoadLibrary(L"ICMP.DLL");
      if(hIcmp == NULL)
      {
    	if(pStrings) pStrings->Add("Could not load ICMP.DLL");
    	return -1;
      }
    
      // Zeiger auf die Funktionen besorgen:
      PF_CMPCREATEFILE pfIcmpCreateFile = (PF_CMPCREATEFILE)
    	GetProcAddress(hIcmp, "IcmpCreateFile");          <== hier Fehlermeldung!
      PF_ICMPCLOSEHANDLE pfIcmpCloseHandle = (PF_ICMPCLOSEHANDLE)
    	GetProcAddress(hIcmp,"IcmpCloseHandle");
      PF_ICMPSENDECHO pfIcmpSendEcho = (PF_ICMPSENDECHO)
    	GetProcAddress(hIcmp,"IcmpSendEcho");
    
      // Funktionszeiger prüfen:
      if (pfIcmpCreateFile == NULL || pfIcmpCloseHandle == NULL ||
    	pfIcmpSendEcho == NULL)
      {
    	if(pStrings) pStrings->Add("Error getting ICMP proc address");
    	FreeLibrary(hIcmp);
    	return -1;
      }
    
      // WinSock initialisieren
      WSADATA wsaData;
      int ilRetVal = WSAStartup(0x0101, &wsaData );
      if(ilRetVal)
      {
    	if(pStrings)
    	  pStrings->Add("Winsock-Initialsierungsfehler: " + IntToStr(ilRetVal));
        WSACleanup();
    	FreeLibrary(hIcmp);
    	return -1;
      }
      // Check WinSock version
      if(0x0101 != wsaData.wVersion)
      {
    	if(pStrings)
    	  pStrings->Add("Fehler: Winsock Version 1.1 oder höher nicht vorhanden !");
        WSACleanup();
    	FreeLibrary(hIcmp);
    	return -1;
      }
    
      // Prüfen, ob es sich bei der Zieladresse um IP-Adresse handelt und
      // ggf. den die Adresse zum Namen ermitteln:
      struct in_addr iaDest;  // Struktur für die Internet-Adresse
      iaDest.s_addr = inet_addr(slAddress.c_str());
      LPHOSTENT pHost;  // Zeiger auf die Host Entry Struktur
      if (iaDest.s_addr == INADDR_NONE) pHost = gethostbyname(slAddress.c_str());
      else pHost = gethostbyaddr((BYTE *)&iaDest, sizeof(struct in_addr), AF_INET);
      if(pHost == NULL)
      {
    	if(pStrings)
    	  pStrings->Add("Fehler: Adresse " + slAddress + " wurde nicht gefunden !");
    	WSACleanup();
    	FreeLibrary(hIcmp);
    	return -1;
      }
    
      if(pStrings)
    	pStrings->Add("Ping an " + AnsiString(pHost->h_name) + "[" +
    	  AnsiString(inet_ntoa((*(LPIN_ADDR)pHost->h_addr_list[0]))) + "]");
    
      // IP-Adresse kopieren
      DWORD* pAddress = (DWORD*)(*pHost->h_addr_list);
    
      // ICMP Echo Request Handle besorgen:
      HANDLE hIcmpFile = pfIcmpCreateFile();
    
      ICMPECHO icmpEcho;      // ICMP-Echo Antwortbuffer
      IPINFO ipInfo;          // IP-Optionenstruktur
    
      int ilTimeSum = 0;      // Summe der Round Trip Time-Daten
      int ilCount   = 0;      // Anzahl der Round Trip Time-Daten
    
      for (int ilPingNo = 0; ilPingNo < 3; ilPingNo++)
      {
    	// Default-Werte festlegen:
    	::ZeroMemory(&ipInfo, sizeof(ipInfo));
    	ipInfo.bTimeToLive = 255;
        // ICMP Echo anfordern:
    	pfIcmpSendEcho(hIcmpFile,   // Handle von IcmpCreateFile()
                       *pAddress,   // Ziel-IP Addresse
    					NULL,       // Zeiger auf den Buffer mit den
    								// zu sendenden Daten
    					0,          // Buffergrösse in Bytes
                        &ipInfo,    // Request-Optionen
    					&icmpEcho,  // Antwort-Buffer
                        sizeof(struct tagICMPECHO), // Buffergrösse
    					5);      // Max. Wartezeit in Millisekunden  default:5000
    
    	// Ergebnisse anzeigen:
        iaDest.s_addr = icmpEcho.dwSource;
    	if(pStrings)
    	{
    	  AnsiString slMessage = "Antwort von "+AnsiString(
    		inet_ntoa(iaDest)); //+ ": Zeit=" + IntToStr(icmpEcho.dwRTTime) +
    		//" ms, Time to Live=" + IntToStr(icmpEcho.ipInfo.bTimeToLive) + " ms";
          pStrings->Add(slMessage);
    	}
        // falls Fehler aufgetreten:
    	if(icmpEcho.dwStatus)
    	{
    	  if(pStrings)
    		pStrings->Add("Fehler: IcmpEcho-Status"); //=" + IntToStr(icmpEcho.dwStatus));
    	  break;
    	}
    	ilTimeSum += icmpEcho.dwRTTime;
    	ilCount++;
    	if(ilPingNo < 2) Sleep(200);
      }
    
      // Echo-Request File Handle schliessen:
      pfIcmpCloseHandle(hIcmpFile);
      // ICMP.DLL freigeben:
      FreeLibrary(hIcmp);
      // Winsock schliessen:
      WSACleanup();
    
      // Den Mittelwert aller Round Trip Times zurückgeben:
      return ilRetVal = ilCount ? ilTimeSum/ilCount : -1;
    }
    

    Seit XE7 kommt in den Zeilen "GetProcAddress(hIcmp, ...)" die Fehlermeldung

    [bcc32 Fehler] Unit3.cpp(101): E2034 Konvertierung von 'void *' nach 'HINSTANCE__ *' nicht möglich
    

    und

    [bcc32 Fehler] Unit3.cpp(101): E2342 Keine Übereinstimmung des Parametertyps 'hModule' ('HINSTANCE__ *' erwartet, 'void *' erhalten)
    

    Hat jemand eine Idee? Danke!
    Oder hat jemand eine ganz andere Ping-Methode parat?



  • HANDLE hIcmp = LoadLibrary(L"ICMP.DLL");
    

    HMODULE = HINSTANCE != HANDLE:
    Der Typ ist HMODULE oder HINSTANCE und nicht HANDLE. Dann kommt GetProcAddress auch klar.



  • Laut msdn müsste HINSTANCE das gleiche sein wie HANDLE, dh PVOID, dh void*. Bei dir wohl nicht, mach einfach einen reinterpret_cast rein.



  • Laut msdn müsste HINSTANCE das gleiche sein wie HANDLE, dh PVOID, dh void*.

    Nein. laut msdn ist HINSTANCE ein Zeiger auf die __HINSTANCE Struktur und kein void pointer. HANDLE ist ein typedef für void*. HMODULE ist ein typedef für HINSTANCE.



  • Man scheint sich dann wohl nicht einig zu sein: https://msdn.microsoft.com/de-de/library/windows/desktop/aa383751(v=vs.85).aspx

    This type is declared in WinDef.h as follows:
    typedef HANDLE HINSTANCE;



  • Habe HANDLE durch HINSTANCE ersetzt u. scheint OK zu sein.
    Jedoch meckert der Compiler in der Zeile

    iaDest.s_addr = inet_addr(slAddress.c_str());
    
    E2342 Keine Übereinstimmung des Parametertyps 'name' ('const char *' erwartet, 'wchar_t *' erhalten)
    


  • gelöst:

    LPCSTR(slAddress.c_str())
    


  • Solange LPCTSTR als den gleichen Typ definiert ist wie den, den String::c_str() zurückgibt, geht das gut. Ansonsten hast du ein Problem.



  • Ja, habe es gerade gemerkt! Umwandlung klappt leider nicht. Hat jemand eine Idee?



  • Du musst halt einen ansi-string und keinen widestring übergeben. Die String Klasse sollte das schon handeln können...



  • Entweder du konvertierst den String von UTF-16 nach ANSI. Wie das am einfachsten geht hängt von den zur Verfüngung stehenden Libs ab, und da ich den C++ Builder und seine Libs nicht kenne... => selber googeln.

    Oder sonst könntest du RtlIpv4StringToAddress und/oder RtlIpv6StringToAddress verwenden (gibt es ab Windows Vista). Die kommen mit wchar_t const* klar.

    Nur wird das wohl nicht der einzige Fehler sein den du beim Compilieren bekommen wirst. Ich vermute nämlich dass dein Projekt von ANSI auf UNICODE umgestellt wurde. (Wieso sonst sollte es jetzt auf einmal ein Problem mit inet_addr geben - was ja mit der HANDLE/HINSTANCE Geschichte überhaupt nix zu tun hat?) Und wenn du davor nie einen UNICODE Build hattest, dann wäre es einigermassen überraschend wenn das der einzige Fehler wäre.


Anmelden zum Antworten