You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
841 lines
21 KiB
841 lines
21 KiB
//++
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1987 - 1999
|
|
//
|
|
// Module Name:
|
|
//
|
|
// ndutils.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Queries into network drivers
|
|
//
|
|
// Author:
|
|
//
|
|
// Anilth - 4-20-1998
|
|
//
|
|
// Environment:
|
|
//
|
|
// User mode only.
|
|
// Contains NT-specific code.
|
|
//
|
|
// Revision History:
|
|
//
|
|
//--
|
|
|
|
#include "precomp.h"
|
|
#include "global.h"
|
|
#include <ntstatus.dbg>
|
|
#include <winerror.dbg>
|
|
#include "ipcfg.h"
|
|
|
|
#define MAX_NET_STATUS_LENGTH 80
|
|
#define MAX_WINERR_SIZE 80
|
|
|
|
const TCHAR c_szSectionName[] = _T("NetDiagContact");
|
|
const TCHAR c_szFileName[] = _T("NdContact.ini");
|
|
|
|
|
|
HRESULT HResultFromWin32(DWORD dwErr)
|
|
{
|
|
return HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
|
|
LPTSTR Win32ErrorToString(DWORD Id)
|
|
{
|
|
|
|
int i = 0;
|
|
static TCHAR s_szWinerr[MAX_WINERR_SIZE + 1];
|
|
|
|
while (winerrorSymbolicNames[ i ].SymbolicName)
|
|
{
|
|
if (winerrorSymbolicNames[ i ].MessageId == Id)
|
|
{
|
|
_tcsncpy( s_szWinerr, A2T(winerrorSymbolicNames[ i ].SymbolicName),
|
|
MAX_WINERR_SIZE);
|
|
|
|
return s_szWinerr;
|
|
}
|
|
else
|
|
{
|
|
i ++;
|
|
}
|
|
}
|
|
|
|
|
|
//if we reach here, then we cannot find the Win32 Error string
|
|
|
|
_stprintf(s_szWinerr, _T("%X"), (DWORD)Id);
|
|
|
|
return s_szWinerr;
|
|
|
|
}
|
|
|
|
LPSTR
|
|
FindSymbolicNameForStatus(
|
|
DWORD Id
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
i = 0;
|
|
if (Id == 0) {
|
|
return "STATUS_SUCCESS";
|
|
}
|
|
|
|
if (Id & 0xC0000000) {
|
|
while (ntstatusSymbolicNames[ i ].SymbolicName) {
|
|
if (ntstatusSymbolicNames[ i ].MessageId == (NTSTATUS)Id) {
|
|
return ntstatusSymbolicNames[ i ].SymbolicName;
|
|
} else {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
while (winerrorSymbolicNames[ i ].SymbolicName) {
|
|
if (winerrorSymbolicNames[ i ].MessageId == Id) {
|
|
return winerrorSymbolicNames[ i ].SymbolicName;
|
|
} else {
|
|
i += 1;
|
|
}
|
|
}
|
|
|
|
#ifdef notdef
|
|
while (neteventSymbolicNames[ i ].SymbolicName) {
|
|
if (neteventSymbolicNames[ i ].MessageId == Id) {
|
|
return neteventSymbolicNames[ i ].SymbolicName
|
|
} else {
|
|
i += 1;
|
|
}
|
|
}
|
|
#endif // notdef
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
PrintSid(
|
|
IN NETDIAG_PARAMS *pParams,
|
|
IN PSID Sid OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints a SID
|
|
|
|
Arguments:
|
|
|
|
Sid - SID to output
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
|
|
if ( Sid == NULL )
|
|
{
|
|
//IDS_UTIL_SID_NULL "(null)\n"
|
|
PrintMessage(pParams, IDS_UTIL_SID_NULL);
|
|
}
|
|
else
|
|
{
|
|
UNICODE_STRING SidString;
|
|
NTSTATUS Status;
|
|
|
|
Status = RtlConvertSidToUnicodeString( &SidString, Sid, TRUE );
|
|
|
|
if ( !NT_SUCCESS(Status) )
|
|
{
|
|
//IDS_UTIL_SID_INVALID "Invalid 0x%lX\n"
|
|
PrintMessage(pParams, IDS_UTIL_SID_INVALID, Status);
|
|
}
|
|
else
|
|
{
|
|
//IDS_GLOBAL_UNICODE_STRING "%wZ"
|
|
PrintMessage(pParams, IDS_GLOBAL_UNICODE_STRING, &SidString);
|
|
PrintNewLine(pParams, 1);
|
|
RtlFreeUnicodeString( &SidString );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NET_API_STATUS
|
|
IsServiceStarted(
|
|
IN LPTSTR pszServiceName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queries the Service Controller to find out if the
|
|
specified service has been started.
|
|
|
|
Arguments:
|
|
|
|
pszServiceName - Supplies the name of the service.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR: if the specified service has been started
|
|
-1: the service was stopped normally
|
|
Otherwise returns the reason the service isn't running.
|
|
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
SC_HANDLE hScManager;
|
|
SC_HANDLE hService;
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
|
|
if ((hScManager = OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_CONNECT
|
|
)) == (SC_HANDLE) NULL) {
|
|
|
|
NetStatus = GetLastError();
|
|
|
|
DebugMessage2(" IsServiceStarted(): OpenSCManager failed. [%s]\n", NetStatusToString(NetStatus));
|
|
|
|
return NetStatus;
|
|
}
|
|
|
|
if ((hService = OpenService(
|
|
hScManager,
|
|
pszServiceName,
|
|
SERVICE_QUERY_STATUS
|
|
)) == (SC_HANDLE) NULL)
|
|
{
|
|
|
|
NetStatus = GetLastError();
|
|
|
|
DebugMessage3(" IsServiceStarted(): OpenService '%s' failed. [%s]\n",
|
|
pszServiceName, NetStatusToString(NetStatus) );
|
|
|
|
(void) CloseServiceHandle(hScManager);
|
|
|
|
return NetStatus;
|
|
}
|
|
|
|
if (! QueryServiceStatus(
|
|
hService,
|
|
&ServiceStatus
|
|
)) {
|
|
|
|
|
|
NetStatus = GetLastError();
|
|
|
|
DebugMessage3(" IsServiceStarted(): QueryServiceStatus '%s' failed. [%s]\n",
|
|
pszServiceName, NetStatusToString(NetStatus) );
|
|
|
|
(void) CloseServiceHandle(hScManager);
|
|
(void) CloseServiceHandle(hService);
|
|
|
|
return NetStatus;
|
|
}
|
|
|
|
(void) CloseServiceHandle(hScManager);
|
|
(void) CloseServiceHandle(hService);
|
|
|
|
switch ( ServiceStatus.dwCurrentState )
|
|
{
|
|
case SERVICE_RUNNING:
|
|
case SERVICE_CONTINUE_PENDING:
|
|
case SERVICE_PAUSE_PENDING:
|
|
case SERVICE_PAUSED:
|
|
NetStatus = NO_ERROR;
|
|
break;
|
|
case SERVICE_STOPPED:
|
|
case SERVICE_START_PENDING:
|
|
case SERVICE_STOP_PENDING:
|
|
if ( ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR )
|
|
{
|
|
NetStatus = ServiceStatus.dwServiceSpecificExitCode;
|
|
if ( NetStatus == NO_ERROR )
|
|
{
|
|
NetStatus = ServiceStatus.dwWin32ExitCode;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NetStatus = ServiceStatus.dwWin32ExitCode;
|
|
if ( NetStatus == NO_ERROR )
|
|
{
|
|
NetStatus = -1;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
NetStatus = ERROR_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
|
|
return NetStatus;
|
|
|
|
} // IsServiceStarted
|
|
|
|
|
|
|
|
LPSTR MapTime(DWORD_PTR TimeVal)
|
|
//++
|
|
//
|
|
// Description:
|
|
// Converts IP lease time to more human-sensible string
|
|
//
|
|
// ENTRY TimeVal - DWORD (time_t) time value (number of milliseconds since
|
|
// virtual year dot)
|
|
//
|
|
//
|
|
// RETURNS pointer to string
|
|
//
|
|
// ASSUMES 1. The caller realizes this function returns a pointer to a static
|
|
// buffer, hence calling this function a second time, but before
|
|
// the results from the previous call have been used, will destroy
|
|
// the previous results
|
|
//--
|
|
{
|
|
|
|
struct tm* pTime;
|
|
static char timeBuf[128];
|
|
static char oemTimeBuf[256];
|
|
|
|
if (pTime = localtime(&TimeVal)) {
|
|
|
|
SYSTEMTIME systemTime;
|
|
char* pTimeBuf = timeBuf;
|
|
int n;
|
|
|
|
systemTime.wYear = pTime->tm_year + 1900;
|
|
systemTime.wMonth = pTime->tm_mon + 1;
|
|
systemTime.wDayOfWeek = (WORD)pTime->tm_wday;
|
|
systemTime.wDay = (WORD)pTime->tm_mday;
|
|
systemTime.wHour = (WORD)pTime->tm_hour;
|
|
systemTime.wMinute = (WORD)pTime->tm_min;
|
|
systemTime.wSecond = (WORD)pTime->tm_sec;
|
|
systemTime.wMilliseconds = 0;
|
|
n = GetDateFormat(0, DATE_LONGDATE, &systemTime, NULL, timeBuf, sizeof(timeBuf));
|
|
timeBuf[n - 1] = ' ';
|
|
GetTimeFormat(0, 0, &systemTime, NULL, &timeBuf[n], sizeof(timeBuf) - n);
|
|
|
|
//
|
|
// we have to convert the returned ANSI string to the OEM charset
|
|
//
|
|
//
|
|
|
|
if (CharToOem(timeBuf, oemTimeBuf)) {
|
|
return oemTimeBuf;
|
|
}
|
|
|
|
return timeBuf;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
|
|
|
|
//used in DCListTest and TrustTest
|
|
NTSTATUS
|
|
NettestSamConnect(
|
|
IN NETDIAG_PARAMS *pParams,
|
|
IN LPWSTR DcName,
|
|
OUT PSAM_HANDLE SamServerHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if the DomainSid field of the TestDomain matches the DomainSid
|
|
of the domain.
|
|
|
|
Arguments:
|
|
|
|
DcName - Dc to connect to
|
|
|
|
SamServerHandle - Returns a Sam server handle
|
|
|
|
Return Value:
|
|
|
|
TRUE: Test suceeded.
|
|
FALSE: Test failed
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING ServerNameString;
|
|
SAM_HANDLE LocalSamHandle = NULL;
|
|
|
|
BOOL fImpersonatingAnonymous = FALSE;
|
|
HANDLE hCurrentToken;
|
|
|
|
//
|
|
// Connect to the SAM server
|
|
//
|
|
|
|
RtlInitUnicodeString( &ServerNameString, DcName );
|
|
|
|
Status = SamConnect(
|
|
&ServerNameString,
|
|
&LocalSamHandle,
|
|
SAM_SERVER_LOOKUP_DOMAIN,
|
|
NULL);
|
|
|
|
//
|
|
// Consider the case where we don't have access to the DC.
|
|
// We might be logged on locally due to the domain sid being wrong.
|
|
//
|
|
|
|
if ( Status == STATUS_ACCESS_DENIED ) {
|
|
|
|
//
|
|
// Try impersonating the anonymous token.
|
|
//
|
|
|
|
//
|
|
// Check to see if we're already impsonating
|
|
//
|
|
|
|
Status = NtOpenThreadToken(
|
|
NtCurrentThread(),
|
|
TOKEN_IMPERSONATE,
|
|
TRUE, // as self to ensure we never fail
|
|
&hCurrentToken );
|
|
|
|
if ( Status == STATUS_NO_TOKEN ) {
|
|
//
|
|
// We're not already impersonating
|
|
hCurrentToken = NULL;
|
|
|
|
} else if ( !NT_SUCCESS( Status) ) {
|
|
PrintGuruMessage(" [WARNING] Cannot NtOpenThreadToken" );
|
|
PrintGuru( NetpNtStatusToApiStatus( Status ), SAM_GURU );
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Impersonate the anonymous token
|
|
//
|
|
Status = NtImpersonateAnonymousToken( NtCurrentThread() );
|
|
|
|
if ( !NT_SUCCESS( Status)) {
|
|
PrintGuruMessage(" [WARNING] Cannot NtOpenThreadToken" );
|
|
PrintGuru( NetpNtStatusToApiStatus( Status ), SAM_GURU );
|
|
goto Cleanup;
|
|
}
|
|
|
|
fImpersonatingAnonymous = TRUE;
|
|
|
|
//
|
|
// Try the SamConnect again
|
|
//
|
|
|
|
Status = SamConnect(
|
|
&ServerNameString,
|
|
&LocalSamHandle,
|
|
SAM_SERVER_LOOKUP_DOMAIN,
|
|
NULL);
|
|
|
|
if ( Status == STATUS_ACCESS_DENIED ) {
|
|
// One can configure SAM this way so it isn't fatal
|
|
DebugMessage2(" [WARNING] Cannot connect to SAM on '%ws' using a NULL session.", DcName );
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
|
|
if ( !NT_SUCCESS(Status)) {
|
|
LocalSamHandle = NULL;
|
|
DebugMessage2(" [FATAL] Cannot connect to SAM on '%ws'.", DcName );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
|
|
*SamServerHandle = LocalSamHandle;
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
//
|
|
// Cleanup locally used resources
|
|
//
|
|
Cleanup:
|
|
if ( fImpersonatingAnonymous ) {
|
|
NTSTATUS TempStatus;
|
|
|
|
TempStatus = NtSetInformationThread(
|
|
NtCurrentThread(),
|
|
ThreadImpersonationToken,
|
|
&hCurrentToken,
|
|
sizeof(HANDLE) );
|
|
|
|
if (!NT_SUCCESS( TempStatus)) {
|
|
DebugMessage2( "SamConnect: Unexpected error reverting to self: 0x%lx\n",
|
|
TempStatus );
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
//only used in Kerberos test so far
|
|
VOID
|
|
sPrintTime(
|
|
LPSTR str,
|
|
LARGE_INTEGER ConvertTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print the specified time
|
|
|
|
Arguments:
|
|
|
|
Comment - Comment to print in front of the time
|
|
|
|
Time - GMT time to print (Nothing is printed if this is zero)
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// If we've been asked to convert an NT GMT time to ascii,
|
|
// Do so
|
|
//
|
|
|
|
if ( ConvertTime.QuadPart != 0 ) {
|
|
LARGE_INTEGER LocalTime;
|
|
TIME_FIELDS TimeFields;
|
|
NTSTATUS Status;
|
|
|
|
Status = RtlSystemTimeToLocalTime( &ConvertTime, &LocalTime );
|
|
if ( !NT_SUCCESS( Status )) {
|
|
sprintf(str, "Can't convert time from GMT to Local time" );
|
|
LocalTime = ConvertTime;
|
|
}
|
|
|
|
RtlTimeToTimeFields( &LocalTime, &TimeFields );
|
|
|
|
sprintf(str, "%ld/%ld/%ld %ld:%2.2ld:%2.2ld",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second );
|
|
}
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
GetComputerNameInfo
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT GetComputerNameInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
|
|
{
|
|
DWORD cchSize;
|
|
WCHAR swzNetBiosName[MAX_COMPUTERNAME_LENGTH+1];
|
|
|
|
cchSize = DimensionOf(swzNetBiosName);
|
|
|
|
if ( !GetComputerNameW( swzNetBiosName, &cchSize ) )
|
|
{
|
|
PrintMessage(pParams, IDS_GLOBAL_NoComputerName);
|
|
return HResultFromWin32(GetLastError());
|
|
}
|
|
|
|
lstrcpynW(pResults->Global.swzNetBiosName, swzNetBiosName,
|
|
MAX_COMPUTERNAME_LENGTH+1);
|
|
|
|
return hrOK;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
GetDNSInfo
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT GetDNSInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
|
|
{
|
|
UINT cchSize;
|
|
TCHAR szDnsName[DNS_MAX_NAME_LENGTH+1];
|
|
HRESULT hr = hrOK;
|
|
//
|
|
// Get the DNS host name.
|
|
//
|
|
|
|
memset(szDnsName,0,sizeof(TCHAR)*(DNS_MAX_NAME_LENGTH+1));
|
|
cchSize = DimensionOf(szDnsName);
|
|
|
|
|
|
if (!GetComputerNameExA( ComputerNameDnsFullyQualified,
|
|
szDnsName,
|
|
&cchSize))
|
|
{
|
|
PrintMessage(pParams, IDS_GLOBAL_ERR_NoDnsName);
|
|
}
|
|
else
|
|
{
|
|
lstrcpyn(pResults->Global.szDnsHostName, szDnsName, DNS_MAX_NAME_LENGTH+1);
|
|
// Look for the first '.' in the name
|
|
pResults->Global.pszDnsDomainName = strchr(pResults->Global.szDnsHostName,
|
|
_T('.'));
|
|
|
|
|
|
if (pResults->Global.pszDnsDomainName != NULL)
|
|
{
|
|
pResults->Global.pszDnsDomainName++;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
GetNetBTParameters
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT GetNetBTParameters(IN NETDIAG_PARAMS *pParams,
|
|
IN OUT NETDIAG_RESULT *pResults)
|
|
{
|
|
LONG err;
|
|
HRESULT hr = hrOK;
|
|
HKEY hkeyServices;
|
|
HKEY hkeyNetBT;
|
|
DWORD dwLMHostsEnabled;
|
|
DWORD dwDnsForWINS;
|
|
DWORD dwType;
|
|
DWORD dwLength;
|
|
|
|
if (!pParams->fVerbose)
|
|
return hrOK;
|
|
|
|
// set defaults
|
|
pResults->Global.dwLMHostsEnabled = E_FAIL;
|
|
pResults->Global.dwDnsForWINS = E_FAIL;
|
|
|
|
err = RegOpenKey(HKEY_LOCAL_MACHINE,
|
|
_T("SYSTEM\\CurrentControlSet\\Services"),
|
|
&hkeyServices
|
|
);
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
pResults->Global.dwLMHostsEnabled = HResultFromWin32(err);
|
|
pResults->Global.dwDnsForWINS = HResultFromWin32(err);
|
|
|
|
PrintDebugSz(pParams, 0, _T("Services opening failed\n"));
|
|
}
|
|
else
|
|
{
|
|
err = RegOpenKey(hkeyServices,
|
|
_T("NetBT\\Parameters"),
|
|
&hkeyNetBT
|
|
);
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
pResults->Global.dwLMHostsEnabled = HResultFromWin32(err);
|
|
pResults->Global.dwDnsForWINS = HResultFromWin32(err);
|
|
|
|
PrintDebugSz(pParams, 0, _T("Parameters opening failed\n"));
|
|
}
|
|
else
|
|
{
|
|
dwLength = sizeof(DWORD);
|
|
err = RegQueryValueEx(hkeyNetBT,
|
|
_T("EnableLMHOSTS"),
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&dwLMHostsEnabled,
|
|
&dwLength
|
|
);
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
pResults->Global.dwLMHostsEnabled = HResultFromWin32(err);
|
|
DebugMessage("Quering EnableLMHOSTS failed !\n");
|
|
}
|
|
else
|
|
{
|
|
pResults->Global.dwLMHostsEnabled = dwLMHostsEnabled;
|
|
}
|
|
|
|
//
|
|
// In NT 5.0 - Dns for wins resolution is enabled by
|
|
// default and the "EnableDNS" key will not be found.
|
|
// If it is not found, we will assume its enabled.
|
|
// In NT 4.0 - the key will be there and its value
|
|
// should let us know whether the option is enabled
|
|
// or disabled
|
|
//
|
|
|
|
dwLength = sizeof(DWORD);
|
|
err = RegQueryValueEx(hkeyNetBT,
|
|
"EnableDNS",
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&dwDnsForWINS,
|
|
&dwLength
|
|
);
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
pResults->Global.dwDnsForWINS = dwDnsForWINS;
|
|
}
|
|
else
|
|
{
|
|
pResults->Global.dwDnsForWINS = TRUE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return hrOK;
|
|
}
|
|
|
|
|
|
ULONG inet_addrW(LPCWSTR pswz)
|
|
{
|
|
ULONG ulReturn;
|
|
CHAR * psaz;
|
|
|
|
psaz = StrDupAFromW(pswz);
|
|
if (psaz == NULL)
|
|
return 0;
|
|
|
|
ulReturn = inet_addrA(psaz);
|
|
Free(psaz);
|
|
|
|
return ulReturn;
|
|
}
|
|
|
|
|
|
|
|
|
|
LPTSTR
|
|
NetStatusToString(
|
|
NET_API_STATUS NetStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Conver a net status code or a Windows error code to the description string.
|
|
NOTE: The string is garuanteed to be valid only right after NetStatusToString is called.
|
|
|
|
Arguments:
|
|
|
|
NetStatus - The net status code to print.
|
|
|
|
Return Value:
|
|
|
|
The status description string
|
|
|
|
--*/
|
|
{
|
|
static TCHAR s_szSymbolicName[MAX_NET_STATUS_LENGTH + 1];
|
|
ZeroMemory(s_szSymbolicName, sizeof(s_szSymbolicName));
|
|
|
|
switch (NetStatus)
|
|
{
|
|
case NERR_Success:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_Success") );
|
|
break;
|
|
|
|
case NERR_DCNotFound:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_DCNotFound") );
|
|
break;
|
|
|
|
case NERR_UserNotFound:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_UserNotFound") );
|
|
break;
|
|
|
|
case NERR_NetNotStarted:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_NetNotStarted") );
|
|
break;
|
|
|
|
case NERR_WkstaNotStarted:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_WkstaNotStarted") );
|
|
break;
|
|
|
|
case NERR_ServerNotStarted:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_ServerNotStarted") );
|
|
break;
|
|
|
|
case NERR_BrowserNotStarted:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_BrowserNotStarted") );
|
|
break;
|
|
|
|
case NERR_ServiceNotInstalled:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_ServiceNotInstalled") );
|
|
break;
|
|
|
|
case NERR_BadTransactConfig:
|
|
_tcscpy( s_szSymbolicName, _T("NERR_BadTransactConfig") );
|
|
break;
|
|
|
|
default:
|
|
{
|
|
LPSTR paszName = FindSymbolicNameForStatus( NetStatus );
|
|
USES_CONVERSION;
|
|
|
|
|
|
if (NULL == paszName)
|
|
{
|
|
_stprintf(s_szSymbolicName, _T("%X"), (DWORD)NetStatus);
|
|
}
|
|
else
|
|
{
|
|
_tcsncpy( s_szSymbolicName, A2T(paszName), MAX_NET_STATUS_LENGTH);
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
return s_szSymbolicName;
|
|
}
|
|
|
|
//Load contact info from the [NetDiagContact] section of the ini file.
|
|
// pszTestName [in] short name of the test, which is also the key name in the ini file
|
|
// pszContactInfo [out] the string of contact info. It will be empty string of the key cannot be found.
|
|
// cChSize [in] the buffer size, in characters, of pszContactInfo
|
|
//
|
|
// return: the number of characters copied to the buffer.
|
|
DWORD LoadContact(LPCTSTR pszTestName, LPTSTR pszContactInfo, DWORD cChSize)
|
|
{
|
|
return GetPrivateProfileString(c_szSectionName,
|
|
pszTestName,
|
|
_T(""),
|
|
pszContactInfo,
|
|
cChSize,
|
|
c_szFileName);
|
|
|
|
}
|