Solved

C: Is computer reachable

Posted on 2004-09-21
38
790 Views
Last Modified: 2012-06-27
Hello experts,
I'm looking for a solution in pure C (Windows APIs are needed?) to verify if a computer is reachable or not.
I'm using Visual Studio 6.

If anyone knows how to do this
please supply an appropriate snippet.

Thank you for any help.

   HStrix

0
Comment
Question by:HStrix
  • 19
  • 12
  • 6
  • +1
38 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
You can use Winsock functions: gethostbyname and gethostbyaddr:
http://msdn.microsoft.com/library/en-us/winsock/winsock/gethostbyname_2.asp
http://msdn.microsoft.com/library/en-us/winsock/winsock/gethostbyaddr_2.asp

also you can make a ping to know if computer is available in real-time.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Also, take a look to this article about pinging in Windows:
http://www.codeproject.com/internet/winping.asp
0
 

Author Comment

by:HStrix
Comment Utility
Thank you jaime_olivares,
I found the following code (at http://msdn.microsoft.com/library/en-us/winsock/winsock/gethostbyname_2.asp):
---
      // Declare and initialize variables
      hostent* remoteHost;
      char* host_name;
      unsigned int addr;
      //----------------------
      // User inputs name of host
      //printf("Input name of host: ");                                
      host_name = (char*) malloc(sizeof(char*)*16);
      //fgets(host_name, 16, stdin);                              /7  <= original code
      host_name = "mycomputername";                       // <== this doesn't work ??
---
Can you help me to replace that statement?
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Just need this:

     hostent* remoteHost;
     char* host_name;
     unsigned int addr;
     host_name = "mycomputername";
     // now you can call your function      
0
 

Author Comment

by:HStrix
Comment Utility
OK, after this my code is:
---
      // If the user input is an alpha name for the host, use gethostbyname()
      // If not, get host by addr (assume IPv4)
      //if (isalpha(host_name[0])) {   /* host address is a name */
      //host_name[strlen(host_name)-1] = '\0'; /* NULL TERMINATED */
      remoteHost = gethostbyname(host_name);
      //}
      //else  {
      //addr = inet_addr(host_name);
      //remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
      //}

                int intLastErr = WSAGetLastError(); // gives 10093

      if (WSAGetLastError() != 0) {
      if (WSAGetLastError() == 11001)
      //printf("Host not found...\nExiting.\n");
            strcpy(strComputerVerify,"Host not found");
      }
      else
      //printf("error#:%ld\n", WSAGetLastError());
            strcpy(strComputerVerify,"unknown error");
---
I get in remotehost as address all zeros.
WSAGetLastError = 10093
Can you help me again?
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
You have commented the most important line:
addr = inet_addr(host_name);
0
 

Author Comment

by:HStrix
Comment Utility
Now my code looks as follows:
---
      // If the user input is an alpha name for the host, use gethostbyname()
      // If not, get host by addr (assume IPv4)
      //if (isalpha(host_name[0])) {   /* host address is a name */
      //host_name[strlen(host_name)-1] = '\0'; /* NULL TERMINATED */
      //remoteHost = gethostbyname(host_name);
      //}
      //else  {
      addr = inet_addr(host_name);
      remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);  // remoteHost is again zero
      //}
      int intLastErr = WSAGetLastError(); // 10093 appears again
      //if (WSAGetLastError() != 0) {
      if (intLastErr != 0)
      {
            //if (WSAGetLastError() == 11001)
            if (intLastErr == 11001)
            {
                  //printf("Host not found...\nExiting.\n");
                  strcpy(strComputerVerify,"Host not found");
            } else
            {
                  strcpy(strComputerVerify,"???");
            }
      }
      else
            //printf("error#:%ld\n", WSAGetLastError());
            strcpy(strComputerVerify,"unknown error")
---
Something is not working...
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
'gethostbyname()' will not help you in determining if a machine is reachable. It just tells whether there's a DNS record available or not. You could just use

WKSTA_INFO_100 w100;

NetWkstaGetInfo ( L"\\\\themachine", 100, &w100);

If that call fails, the machine is not reachable.
0
 

Author Comment

by:HStrix
Comment Utility
Thank you jkr,
what .h file and which .lib file do I need?
I added netapi32.lib, but I miss something.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
The header file is 'lmwksta.h' - BTW, NOTE that this might also fail if theat machine is not running windows or the Workstation service is not running (the latter meaning "unreachable" anyway). However, a machine can also be cofigured to not answer to "pings".
0
 

Author Comment

by:HStrix
Comment Utility
OK,
now I get the error
---
error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'
---
My code is:
---
void verifyComputer(void)
{
   WKSTA_INFO_100 w100;
   NetWkstaGetInfo ( L"\\\\mycomputername", 100, &w100);
}
---
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
>NOTE that this might also fail if theat machine is not running windows or the >Workstation service is not running (the latter meaning "unreachable" anyway).
That's why ping is a better solution

> However, a machine can also be cofigured to not answer to "pings".
In case machines are yours, then there is no such problem
0
 

Author Comment

by:HStrix
Comment Utility
Concerning the machine:
I know that the machine I'm trying to verify does exist.
But I'm not sure that it is running.
In addition the caller might have made a typo (the access in made via a .bat file).
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to
>>'LPSTR'

Are you on Win9x? Then use

void verifyComputer(void)
{
  WKSTA_INFO_100 w100;
  NetWkstaGetInfo ( _T("\\\\mycomputername"), 100, &w100);
}

0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>In case machines are yours, then there is no such problem

And no problem about the WkStaSvc.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Notices there are many considerations when using NetWkstaGetInfo, depending on Operating System and security rights. Read more at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netwkstagetinfo.asp
0
 

Author Comment

by:HStrix
Comment Utility
I'm in Win2000 Workstation.
0
 

Author Comment

by:HStrix
Comment Utility
But it is not an MFC application,
it is a console application, it starts with
---
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR        lpCmdLine,
                     int             nCmdShow )
{

    ......

}
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>> Notices there are many considerations when using NetWkstaGetInfo, depending on Operating
>>System

The idea is that
a) All users can use infolevel 100
b) If the call is successful, the machine is available.

>> I'm in Win2000 Workstation.

The following compiles just fine:

#include <windows.h>
#include <lm.h>
#include <lmwksta.h>
#include <tchar.h>

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

void verifyComputer(void)
{
 WKSTA_INFO_100* pw100;
 NetWkstaGetInfo ( _T("\\\\mycomputername"), 100, (LPBYTE*) &pw100);

 NetApiBufferFree ( pw100);
}

int APIENTRY WinMain(HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR        lpCmdLine,
                    int             nCmdShow )
{

   return 0;

}

0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 22

Expert Comment

by:grg99
Comment Utility
You need to clarify a few details:

What do you mean by "reachable"?

Some possibilities:

(1)  The DNS name exists

(2)  That IP address responds to "ping".

(3) Some port accepts connections:  Which one? Could be Telnet, www, FTP, Gopher, IRC, DNS, SMB.

----------------

Note that a lot of computers are behind firewalls, or have ping turned off, specifically to avoid other computers figuring out they are there.

Perhaps if you'd explain exactly what you're trying to do we could suggest something appropriate.

0
 

Author Comment

by:HStrix
Comment Utility
Thanks, now I modified the code to
---
void verifyComputer(void)
{
      DWORD netret;
      LPTSTR pszServerName = NULL;
      pszServerName = (char *)L"\\\\mycomputername"; // result is "\" only
      pszServerName = _T("\\\\mycomputername");        // result is "\\mycomputername"
      WKSTA_INFO_100* pw100;
      //netret = NetWkstaGetInfo ( pszServerName, 100, (LPBYTE *)&pw100);
                netret = NetWkstaGetInfo ( _T("\\\\mhpab5gc"), 100, (LPBYTE *)&pw100);  // it leads to the same result
      if( netret == NERR_Success )  // netret = 53
      {
            strcpy(strComputerVerify,"Host is available");
      } else
      {
            strcpy(strComputerVerify,"Host not found");
      }
      NetApiBufferFree ( pw100);
}
---
It compiles error free, but the execution gives code 53.

If I use
--
pszServerName = (char *)L"\\\\mycomputername"; // result is "\" only
//netret = NetWkstaGetInfo ( pszServerName, 100, (LPBYTE *)&pw100);
---
then I get netret=0, but is this OK for the contents of pszServerName?

For testing I use the computername I'm running on,
so I'm sure that it is OK.

If I use
--
pszServerName = (char *)L"\\\\mycomputernameX"; // result is "\" only but "mycomputernameX" is unknown
//netret = NetWkstaGetInfo ( pszServerName, 100, (LPBYTE *)&pw100);
---
then I get netret=53.

0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>pszServerName = (char *)L"\\\\mycomputernameX"; // result is "\" only but "mycomputernameX" i

That cannot work (thus the ERROR_BAD_NETPATH). It needs to be UNICODE:

void verifyComputer(char* pszName)
{
WKSTA_INFO_100* pw100;
wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];

wsprintf ( awcName, "%S", pszNme);

NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);

NetApiBufferFree ( pw100);
}
0
 

Author Comment

by:HStrix
Comment Utility
Here is some more explanation:

The C[++] I'm writing is designed to invoke another program (using ShellExecute)
and then stops working.

The another program is located on a share.
Now I want to check step-by-step
 - of the computer is reachable,
 - then if the share is still available
 - and at last if the program I want to activate is on that share.
And in each case I want to inform the user about the cause of an occured problem.

Everything is already working, if the three checks above are not required.
But I thought, there might be some circumstances, that problems occur.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>Now I want to check step-by-step
>>- of the computer is reachable,
>>- then if the share is still available

Then, the next step is using 'NetShareGetInfo()'...

>> - and at last if the program I want to activate is on that share.

... followed by 'NetShareAdd()'.

0
 

Author Comment

by:HStrix
Comment Utility
Yes, I wanted to ask appropriate questions in that order.
0
 

Author Comment

by:HStrix
Comment Utility
For the code
---
void verifyComputer(char* pszName)
{
      DWORD netret;
      WKSTA_INFO_100* pw100;
      wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];
 // error C2664: 'wsprintfA': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'                    occurs for next line:
      wsprintf ( awcName, "%S", pszName);
// error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'           occurs for next line:            
      NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);
---
I get above's errors.

I call the routine as follows
---
char *computername = "";
computername= token; // as it is in =>http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21137583.html
verifyComputer(computername);
---
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>> // error C2664: 'wsprintfA':

Ouch :o) - that should be 'wsprintfW()'

Try

#include <windows.h>
#ifndef UNICODE
#define UNICODE
#include <lm.h>
#include <lmwksta.h>
#undef UNICODE
#endif

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

void verifyComputer(char* pszName)
{
WKSTA_INFO_100* pw100;
wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];

wsprintfW ( awcName, L"%S", pszName);

NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);

NetApiBufferFree ( pw100);
}
0
 

Author Comment

by:HStrix
Comment Utility
Still I get the following:
---
     WKSTA_INFO_100* pw100;
     wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];
     wsprintfW ( awcName, L"%S", pszName);
// error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'           occurs for next line:            
     NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);
---
0
 

Author Comment

by:HStrix
Comment Utility
I changed
   NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);
to
  netret = NetWkstaGetInfo ( (LPSTR) &awcName, 100, (LPBYTE*) &pw100);
then I get netret=0.
But I'm confused is this OK or not?
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
'0' is

#define NERR_Success            0       /* Success */

But something is fishy here - could you look up the declaration of 'NetWkstaGetInfo()' in your header file?
0
 

Author Comment

by:HStrix
Comment Utility
OK, I'll check that tomorrow.
On my computer is the environment of .Net 2003 and of the Platform SDK.
0
 

Author Comment

by:HStrix
Comment Utility
Here it is:
---
excerpt from lmwksta.h
---
//
// Function Prototypes
//

NET_API_STATUS NET_API_FUNCTION
NetWkstaGetInfo (
    IN  LMSTR   servername OPTIONAL,
    IN  DWORD   level,
    OUT LPBYTE  *bufptr
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaSetInfo (
    IN  LMSTR   servername OPTIONAL,
    IN  DWORD   level,
    IN  LPBYTE  buffer,
    OUT LPDWORD parm_err OPTIONAL
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaUserGetInfo (
    IN  LMSTR  reserved,
    IN  DWORD   level,
    OUT LPBYTE  *bufptr
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaUserSetInfo (
    IN  LMSTR  reserved,
    IN  DWORD   level,
    OUT LPBYTE  buf,
    OUT LPDWORD parm_err OPTIONAL
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaUserEnum (
    IN  LMSTR       servername OPTIONAL,
    IN  DWORD       level,
    OUT LPBYTE      *bufptr,
    IN  DWORD       prefmaxlen,
    OUT LPDWORD     entriesread,
    OUT LPDWORD     totalentries,
    IN  OUT LPDWORD resumehandle OPTIONAL
    );
---
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Hmm, the part of interest now would be the typedef for 'LMSTR'...
0
 

Author Comment

by:HStrix
Comment Utility
Here it is:
---
excerpt from lmcons.h
---
//
// Only the UNICODE version of the LM APIs are available on NT.
// Non-UNICODE version on other platforms
//
#if defined( _WIN32_WINNT ) || defined( WINNT ) || defined( __midl ) \
    || defined( FORCE_UNICODE )
#define LMSTR   LPWSTR
#define LMCSTR  LPCWSTR
#else
#define LMSTR   LPSTR
#define LMCSTR  LPCSTR
#endif
---
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
Comment Utility
Ah, here we have it :o)

Then, that should be

Try

#include <windows.h>
#define FORCE_UNICODE
#include <lm.h>
#include <lmwksta.h>

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

void verifyComputer(char* pszName)
{
WKSTA_INFO_100* pw100;
wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];

wsprintfW ( awcName, L"%S", pszName);

NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);

NetApiBufferFree ( pw100);
}

Actually, _WIN32_WINNT or WINNT  should be defined somewhere, though...
0
 

Author Comment

by:HStrix
Comment Utility
and follow up ...

excerpt from mapinls.h (appears first in the dropdownlist referring to definition)
---
typedef CHAR FAR *                                    LPSTR;
---

excerpt from winnt.h (appears secondly in the dropdownlist)
---
typedef CHAR *LPSTR, *PSTR;
---
0
 

Author Comment

by:HStrix
Comment Utility
I tested it and it works as expected.
To get this solution some very special know-how seems to be required.
But as you know this was not your first help for me.

Thank you jkr very much for your great help!

    HStrix
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>To get this solution some very special know-how seems to be required.

Actually, some experience with MS' poorly doumented network APIs helps also :o)

Great that it finally worked.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now