1494 lines
35 KiB
C
1494 lines
35 KiB
C
//++
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1987 - 1999
|
|
//
|
|
// Module Name:
|
|
//
|
|
// nwtest.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 "nwtest.h"
|
|
|
|
HRESULT
|
|
NetwareTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
|
|
//++
|
|
//
|
|
// Description:
|
|
// This routine enumerates bindery or tree logins and in the case of tree login gives the
|
|
// default context.
|
|
// It also gets the server attached to.
|
|
//
|
|
// Argument:
|
|
// None.
|
|
//
|
|
// Author:
|
|
// Rajkumar .P 07/21/98
|
|
//
|
|
{
|
|
// PTESTED_DOMAIN Context = pParams->pDomain;
|
|
|
|
LPWSTR pszCurrentContext = NULL;
|
|
DWORD dwPrintOptions;
|
|
|
|
LPWSTR pszName;
|
|
WCHAR szUserName[MAX_PATH+1] = L"";
|
|
WCHAR szNoName[2] = L"";
|
|
DWORD_PTR ResumeKey = 0;
|
|
LPBYTE pBuffer = NULL;
|
|
DWORD EntriesRead = 0;
|
|
|
|
DWORD dwMessageId;
|
|
|
|
UNICODE_STRING uContext;
|
|
WCHAR szContext[MAX_PATH+1];
|
|
LPWSTR pszTemp;
|
|
|
|
// Get the current default tree or server name
|
|
DWORD err ;
|
|
PCONN_STATUS pConnStatus = NULL;
|
|
DWORD i;
|
|
PCONN_STATUS pConnStatusTmp;
|
|
PCONN_STATUS pConnStatusUser;
|
|
PCONN_STATUS pConnStatusNoUser;
|
|
HANDLE handleRdr;
|
|
LPWSTR pszText;
|
|
|
|
// WNet calls related declarations;
|
|
DWORD dwError;
|
|
LPNETRESOURCE lpNetResource = NULL;
|
|
HANDLE hEnum;
|
|
DWORD dwCount;
|
|
LPNETRESOURCE lpBuffer;
|
|
DWORD BufferSize;
|
|
|
|
HRESULT hr = hrOK;
|
|
|
|
|
|
InitializeListHead( &pResults->Netware.lmsgOutput );
|
|
|
|
PrintStatusMessage(pParams, 4, IDS_NETWARE_STATUS_MSG);
|
|
|
|
//
|
|
// Check if client services for netware has been installed
|
|
//
|
|
/*
|
|
dwError = WNetOpenEnum(
|
|
RESOURCE_GLOBALNET,
|
|
RESOURCETYPE_ANY | RESOURCETYPE_PRINT | RESOURCETYPE_DISK,
|
|
0,
|
|
lpNetResource,
|
|
&hEnum);
|
|
|
|
if (dwError != NO_ERROR) {
|
|
if (dwError == ERROR_NO_NETWORK)
|
|
printf("No Network is present\n");
|
|
printf("WNetOpenEnum failed. Not Able to determine client services for netware is installed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
lpBuffer = LocalAlloc(LMEM_ZEROINIT,sizeof(NETRESOURCE) * 100); // arbit
|
|
|
|
dwError = WNetEnumResource(
|
|
hEnum,
|
|
&dwCount,
|
|
lpBuffer,
|
|
&BufferSize);
|
|
|
|
|
|
if (dwError != NO_ERROR) {
|
|
|
|
if (DebugVerbose)
|
|
printf("Error: WNetEnumResource\n");
|
|
|
|
if (dwError == ERROR_NO_MORE_ITEMS)
|
|
printf("ERROR_NO_MORE_ITEM\n");
|
|
|
|
dwError = GetLastError();
|
|
|
|
if (dwError == ERROR_MORE_DATA) {
|
|
if (DebugVerbose)
|
|
printf("ERROR_MORE_DATA\n");
|
|
}
|
|
|
|
if (dwError == ERROR_INVALID_HANDLE)
|
|
printf("ERROR_INVALID_HANDLE\n");
|
|
|
|
if (dwError == ERROR_NO_NETWORK)
|
|
printf("ERROR_NO_NETWORK\n");
|
|
|
|
if (dwError == ERROR_EXTENDED_ERROR)
|
|
printf("ERROR_EXTENDED_ERROR\n");
|
|
}
|
|
else {
|
|
printf("dwCount %d \n",dwCount);
|
|
}
|
|
|
|
LocalFree(lpBuffer);
|
|
*/
|
|
|
|
// end of WNet calls
|
|
|
|
err = NwQueryInfo( &dwPrintOptions, &pszCurrentContext );
|
|
|
|
if ( err == NO_ERROR )
|
|
{
|
|
|
|
szContext[0] = 0;
|
|
uContext.Buffer = szContext;
|
|
uContext.Length = uContext.MaximumLength
|
|
= sizeof(szContext)/sizeof(szContext[0]);
|
|
|
|
if ( pszCurrentContext )
|
|
{
|
|
pszName = pszCurrentContext;
|
|
}
|
|
else
|
|
{
|
|
pszName = szNoName;
|
|
}
|
|
|
|
if ( pszName[0] == TREECHAR )
|
|
{
|
|
// Get the tree name from the full name *TREE\CONTEXT
|
|
|
|
if ( pszTemp = wcschr( pszName, L'\\' ))
|
|
*pszTemp = 0;
|
|
|
|
dwMessageId = NW_MESSAGE_NOT_LOGGED_IN_TREE;
|
|
}
|
|
else
|
|
{
|
|
dwMessageId = NW_MESSAGE_NOT_LOGGED_IN_SERVER;
|
|
}
|
|
|
|
if ( pszName[0] != 0 ) // there is preferred server/tree
|
|
{
|
|
err = NwGetConnectionStatus( pszName,
|
|
&ResumeKey,
|
|
&pBuffer,
|
|
&EntriesRead );
|
|
}
|
|
|
|
if ( err == NO_ERROR && EntriesRead > 0 )
|
|
// For trees, we'll get more than one entry
|
|
{
|
|
pConnStatus = (PCONN_STATUS) pBuffer;
|
|
|
|
if ( EntriesRead > 1 && pszName[0] == TREECHAR )
|
|
{
|
|
// If there is more than one entry for trees,
|
|
// then we need to find one entry where username is not null.
|
|
// If we cannot find one, then just use the first one.
|
|
|
|
pConnStatusTmp = pConnStatus;
|
|
pConnStatusUser = NULL;
|
|
pConnStatusNoUser = NULL;
|
|
|
|
for ( i = 0; i < EntriesRead ; i++ )
|
|
{
|
|
if ( pConnStatusTmp->fNds )
|
|
{
|
|
pConnStatusNoUser = pConnStatusTmp;
|
|
|
|
if ( ( pConnStatusTmp->pszUserName != NULL )
|
|
&& ( ( pConnStatusTmp->dwConnType
|
|
== NW_CONN_NDS_AUTHENTICATED_NO_LICENSE )
|
|
|| ( pConnStatusTmp->dwConnType
|
|
== NW_CONN_NDS_AUTHENTICATED_LICENSED )
|
|
)
|
|
)
|
|
{
|
|
// Found it
|
|
pConnStatusUser = pConnStatusTmp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Continue with the next item
|
|
pConnStatusTmp = (PCONN_STATUS)
|
|
( (DWORD_PTR) pConnStatusTmp
|
|
+ pConnStatusTmp->dwTotalLength);
|
|
}
|
|
|
|
if ( pConnStatusUser )
|
|
{
|
|
// found one nds entry with a user name
|
|
pConnStatus = pConnStatusUser;
|
|
}
|
|
else if ( pConnStatusNoUser )
|
|
{
|
|
// use an nds entry with no user name
|
|
pConnStatus = pConnStatusNoUser;
|
|
}
|
|
// else use the first entry
|
|
}
|
|
|
|
if ( ( pConnStatus->pszUserName )
|
|
&& ( pConnStatus->pszUserName[0] != 0 )
|
|
)
|
|
{
|
|
NwAbbreviateUserName( pConnStatus->pszUserName,
|
|
szUserName);
|
|
|
|
NwMakePrettyDisplayName( szUserName );
|
|
|
|
if ( pszName[0] != TREECHAR )
|
|
{
|
|
dwMessageId = NW_MESSAGE_LOGGED_IN_SERVER;
|
|
}
|
|
else
|
|
{
|
|
dwMessageId = NW_MESSAGE_LOGGED_IN_TREE;
|
|
}
|
|
}
|
|
|
|
if ( pszName[0] == TREECHAR )
|
|
{
|
|
// For trees, we need to get the current context
|
|
|
|
// Open a handle to the redirector
|
|
handleRdr = NULL;
|
|
err = RtlNtStatusToDosError(
|
|
NwNdsOpenRdrHandle( &handleRdr ));
|
|
|
|
if ( err == NO_ERROR )
|
|
{
|
|
UNICODE_STRING uTree;
|
|
RtlInitUnicodeString( &uTree, pszName+1 ); // get past '*'
|
|
|
|
// Get the current context in the default tree
|
|
err = RtlNtStatusToDosError(
|
|
NwNdsGetTreeContext( handleRdr,
|
|
&uTree,
|
|
&uContext));
|
|
}
|
|
|
|
if ( handleRdr != NULL )
|
|
NtClose( handleRdr );
|
|
}
|
|
}
|
|
|
|
if ( !err )
|
|
{
|
|
switch (dwMessageId)
|
|
{
|
|
case NW_MESSAGE_NOT_LOGGED_IN_TREE:
|
|
// "You are not logged in to the directory tree %s. "
|
|
AddMessageToList(&pResults->Netware.lmsgOutput,
|
|
Nd_Quiet,
|
|
IDS_NETWARE_NOT_LOGGED_IN_TREE,
|
|
pszName[0] == TREECHAR ? pszName + 1: pszName);
|
|
hr = S_FALSE;
|
|
break;
|
|
case NW_MESSAGE_NOT_LOGGED_IN_SERVER:
|
|
// "You are not logged in to your preferred server %s.\n"
|
|
AddMessageToList(&pResults->Netware.lmsgOutput,
|
|
Nd_Quiet,
|
|
IDS_NETWARE_NOT_LOGGED_IN_SERVER,
|
|
pszName[0] == TREECHAR ? pszName + 1: pszName);
|
|
hr = S_FALSE;
|
|
break;
|
|
case NW_MESSAGE_LOGGED_IN_SERVER:
|
|
// "You are logged in to the server %s with user name %s.\n"
|
|
AddMessageToList(&pResults->Netware.lmsgOutput,
|
|
Nd_Verbose,
|
|
IDS_NETWARE_LOGGED_IN_SERVER,
|
|
pszName[0] == TREECHAR ? pszName + 1: pszName,
|
|
szUserName);
|
|
pResults->Netware.pszServer = StrDupTFromW(pszName[0] == TREECHAR ?
|
|
pszName + 1 : pszName);
|
|
pResults->Netware.pszUser = StrDupTFromW(szUserName);
|
|
pResults->Netware.pszTree = StrDup(_T(""));
|
|
pResults->Netware.pszContext = StrDup(_T(""));
|
|
break;
|
|
case NW_MESSAGE_LOGGED_IN_TREE:
|
|
// "You are logged in to the directory tree %s with user name %s.\nThe current workstation name context is %s.\n"
|
|
AddMessageToList(&pResults->Netware.lmsgOutput,
|
|
Nd_Verbose,
|
|
IDS_NETWARE_LOGGED_IN_TREE,
|
|
pszName[0] == TREECHAR ? pszName + 1: pszName,
|
|
szUserName,
|
|
szContext);
|
|
pResults->Netware.pszTree = StrDupTFromW(pszName[0] == TREECHAR ?
|
|
pszName + 1 : pszName);
|
|
pResults->Netware.pszUser = StrDupTFromW(szUserName);
|
|
pResults->Netware.pszContext = StrDupTFromW(szContext);
|
|
pResults->Netware.pszServer = StrDup(_T(""));
|
|
}
|
|
|
|
// Read from the conn status if possible
|
|
if (pConnStatus)
|
|
{
|
|
pResults->Netware.fConnStatus = TRUE;
|
|
|
|
if (pConnStatus->pszUserName)
|
|
{
|
|
Free(pResults->Netware.pszUser);
|
|
pResults->Netware.pszUser =
|
|
StrDupTFromW(pConnStatus->pszUserName);
|
|
}
|
|
|
|
if (pConnStatus->pszServerName)
|
|
{
|
|
Free(pResults->Netware.pszServer);
|
|
pResults->Netware.pszServer =
|
|
StrDupTFromW(pConnStatus->pszServerName);
|
|
}
|
|
|
|
if (pConnStatus->pszTreeName)
|
|
{
|
|
Free(pResults->Netware.pszTree);
|
|
pResults->Netware.pszTree =
|
|
StrDupTFromW(pConnStatus->pszTreeName);
|
|
}
|
|
|
|
pResults->Netware.fNds = pConnStatus->fNds;
|
|
pResults->Netware.dwConnType = pConnStatus->dwConnType;
|
|
}
|
|
else
|
|
pResults->Netware.fConnStatus = FALSE;
|
|
|
|
}
|
|
|
|
if ( pBuffer != NULL )
|
|
{
|
|
LocalFree( pBuffer );
|
|
pBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
if ( pszCurrentContext != NULL )
|
|
{
|
|
LocalFree( pszCurrentContext );
|
|
pszCurrentContext = NULL;
|
|
}
|
|
|
|
if ( err != NO_ERROR )
|
|
{
|
|
// if (DebugVerbose)
|
|
// printf("Error %s occurred while trying to get connection information.\n",err);
|
|
// printf("Error getting connection information\n");
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WORD
|
|
NwParseNdsUncPath(
|
|
IN OUT LPWSTR * Result,
|
|
IN LPWSTR ContainerName,
|
|
IN ULONG flag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is used to extract either the tree name, fully distinguished
|
|
name path to an object, or object name, out of a complete NDS UNC path.
|
|
|
|
Arguments:
|
|
|
|
Result - parsed result buffer.
|
|
ContainerName - Complete NDS UNC path that is to be parsed.
|
|
flag - Flag indicating operation to be performed:
|
|
|
|
PARSE_NDS_GET_TREE_NAME
|
|
PARSE_NDS_GET_PATH_NAME
|
|
PARSE_NDS_GET_OBJECT_NAME
|
|
|
|
|
|
Return Value:
|
|
|
|
Length of string in result buffer. If error occured, 0 is returned.
|
|
|
|
--*/ // NwParseNdsUncPath
|
|
{
|
|
USHORT length = 2;
|
|
USHORT totalLength = (USHORT) wcslen( ContainerName );
|
|
|
|
if ( totalLength < 2 )
|
|
return 0;
|
|
|
|
//
|
|
// First get length to indicate the character in the string that indicates the
|
|
// "\" in between the tree name and the rest of the UNC path.
|
|
//
|
|
// Example: \\<tree name>\<path to object>[\|.]<object>
|
|
// ^
|
|
// |
|
|
//
|
|
while ( length < totalLength && ContainerName[length] != L'\\' )
|
|
{
|
|
length++;
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_TREE_NAME )
|
|
{
|
|
*Result = (LPWSTR) ( ContainerName + 2 );
|
|
|
|
return ( length - 2 ) * sizeof( WCHAR ); // Take off 2 for the two \\'s
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_PATH_NAME && length == totalLength )
|
|
{
|
|
*Result = ContainerName;
|
|
|
|
return 0;
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_PATH_NAME )
|
|
{
|
|
*Result = ContainerName + length + 1;
|
|
|
|
return ( totalLength - length - 1 ) * sizeof( WCHAR );
|
|
}
|
|
|
|
*Result = ContainerName + totalLength - 1;
|
|
length = 1;
|
|
|
|
while ( **Result != L'\\' )
|
|
{
|
|
*Result--;
|
|
length++;
|
|
}
|
|
|
|
*Result++;
|
|
length--;
|
|
|
|
return length * sizeof( WCHAR );
|
|
}
|
|
|
|
|
|
NTSTATUS NwNdsOpenRdrHandle(
|
|
OUT PHANDLE phNwRdrHandle
|
|
)
|
|
{
|
|
|
|
NTSTATUS ntstatus;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
ACCESS_MASK DesiredAccess = SYNCHRONIZE | GENERIC_READ;
|
|
|
|
WCHAR NameStr[] = L"\\Device\\NwRdr\\*";
|
|
UNICODE_STRING uOpenName;
|
|
|
|
//
|
|
// Prepare the open name.
|
|
//
|
|
|
|
RtlInitUnicodeString( &uOpenName, NameStr );
|
|
|
|
//
|
|
// Set up the object attributes.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&uOpenName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
|
|
ntstatus = NtOpenFile(
|
|
phNwRdrHandle,
|
|
DesiredAccess,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
FILE_SHARE_VALID_FLAGS,
|
|
FILE_SYNCHRONOUS_IO_NONALERT );
|
|
|
|
if ( !NT_ERROR(ntstatus) &&
|
|
!NT_INFORMATION(ntstatus) &&
|
|
!NT_WARNING(ntstatus)) {
|
|
|
|
return IoStatusBlock.Status;
|
|
|
|
}
|
|
|
|
return ntstatus;
|
|
}
|
|
|
|
NTSTATUS
|
|
NwNdsGetTreeContext (
|
|
IN HANDLE hNdsRdr,
|
|
IN PUNICODE_STRING puTree,
|
|
OUT PUNICODE_STRING puContext
|
|
)
|
|
/*+++
|
|
|
|
This gets the current context of the requested tree.
|
|
|
|
---*/
|
|
{
|
|
|
|
NTSTATUS ntstatus;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
PNWR_NDS_REQUEST_PACKET Rrp;
|
|
DWORD RrpSize;
|
|
|
|
//
|
|
// Set up the request.
|
|
//
|
|
|
|
RrpSize = sizeof( NWR_NDS_REQUEST_PACKET ) + puTree->Length;
|
|
|
|
Rrp = LocalAlloc( LMEM_ZEROINIT, RrpSize );
|
|
|
|
if ( !Rrp ) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
try {
|
|
|
|
(Rrp->Parameters).GetContext.TreeNameLen = puTree->Length;
|
|
|
|
RtlCopyMemory( (BYTE *)(Rrp->Parameters).GetContext.TreeNameString,
|
|
puTree->Buffer,
|
|
puTree->Length );
|
|
|
|
(Rrp->Parameters).GetContext.Context.MaximumLength = puContext->MaximumLength;
|
|
(Rrp->Parameters).GetContext.Context.Length = 0;
|
|
(Rrp->Parameters).GetContext.Context.Buffer = puContext->Buffer;
|
|
|
|
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|
|
|
ntstatus = STATUS_INVALID_PARAMETER;
|
|
goto ExitWithCleanup;
|
|
}
|
|
|
|
try {
|
|
|
|
ntstatus = NtFsControlFile( hNdsRdr,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
FSCTL_NWR_NDS_GETCONTEXT,
|
|
(PVOID) Rrp,
|
|
RrpSize,
|
|
NULL,
|
|
0 );
|
|
|
|
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|
|
|
ntstatus = GetExceptionCode();
|
|
goto ExitWithCleanup;
|
|
}
|
|
|
|
//
|
|
// Copy out the length; the buffer has already been written.
|
|
//
|
|
|
|
puContext->Length = (Rrp->Parameters).GetContext.Context.Length;
|
|
|
|
ExitWithCleanup:
|
|
|
|
LocalFree( Rrp );
|
|
return ntstatus;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwGetConnectionStatus(
|
|
IN LPWSTR pszRemoteName,
|
|
OUT PDWORD_PTR ResumeKey,
|
|
OUT LPBYTE *Buffer,
|
|
OUT PDWORD EntriesRead
|
|
)
|
|
{
|
|
DWORD err = NO_ERROR;
|
|
DWORD dwBytesNeeded = 0;
|
|
DWORD dwBufferSize = TWO_KB;
|
|
|
|
*Buffer = NULL;
|
|
*EntriesRead = 0;
|
|
|
|
do {
|
|
|
|
*Buffer = (LPBYTE) LocalAlloc( LMEM_ZEROINIT, dwBufferSize );
|
|
|
|
if ( *Buffer == NULL )
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
err = NWPGetConnectionStatus( pszRemoteName,
|
|
ResumeKey,
|
|
*Buffer,
|
|
dwBufferSize,
|
|
&dwBytesNeeded,
|
|
EntriesRead );
|
|
|
|
if ( err == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
dwBufferSize = dwBytesNeeded + EXTRA_BYTES;
|
|
LocalFree( *Buffer );
|
|
*Buffer = NULL;
|
|
}
|
|
|
|
} while ( err == ERROR_INSUFFICIENT_BUFFER );
|
|
|
|
if ( err == ERROR_INVALID_PARAMETER ) // not attached
|
|
{
|
|
err = NO_ERROR;
|
|
*EntriesRead = 0;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
VOID
|
|
NwAbbreviateUserName(
|
|
IN LPWSTR pszFullName,
|
|
OUT LPWSTR pszUserName
|
|
)
|
|
{
|
|
LPWSTR pszTemp;
|
|
LPWSTR pszLast;
|
|
WCHAR NextChar;
|
|
|
|
if ( pszUserName == NULL )
|
|
return;
|
|
|
|
pszTemp = pszFullName;
|
|
pszLast = pszTemp;
|
|
|
|
*pszUserName = 0;
|
|
|
|
while ( pszTemp = wcschr( pszTemp, L'='))
|
|
{
|
|
|
|
NextChar = *(++pszTemp);
|
|
|
|
while ( NextChar != 0 && NextChar != L'.' )
|
|
{
|
|
*(pszUserName++) = *pszTemp;
|
|
NextChar = *(++pszTemp);
|
|
}
|
|
|
|
if ( NextChar == 0 )
|
|
{
|
|
pszLast = NULL;
|
|
break;
|
|
}
|
|
|
|
*(pszUserName++) = *pszTemp; // put back the '.'
|
|
pszLast = ++pszTemp;
|
|
}
|
|
|
|
if ( pszLast != NULL )
|
|
{
|
|
while ( *pszLast != 0 )
|
|
*(pszUserName++) = *(pszLast++);
|
|
}
|
|
|
|
*pszUserName = 0;
|
|
}
|
|
|
|
VOID
|
|
NwMakePrettyDisplayName(
|
|
IN LPWSTR pszName
|
|
)
|
|
{
|
|
|
|
if ( pszName )
|
|
{
|
|
CharLower((LPSTR)pszName );
|
|
CharUpperBuff( (LPSTR)pszName, 1);
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
NWPGetConnectionStatus(
|
|
IN LPWSTR pszRemoteName,
|
|
IN OUT PDWORD_PTR ResumeKey,
|
|
OUT LPBYTE Buffer,
|
|
IN DWORD BufferSize,
|
|
OUT PDWORD BytesNeeded,
|
|
OUT PDWORD EntriesRead
|
|
)
|
|
{
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
HANDLE handleRdr = NULL;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
UNICODE_STRING uRdrName;
|
|
WCHAR RdrPrefix[] = L"\\Device\\NwRdr\\*";
|
|
|
|
PNWR_REQUEST_PACKET RequestPacket = NULL;
|
|
DWORD RequestPacketSize = 0;
|
|
DWORD dwRemoteNameLen = 0;
|
|
|
|
//
|
|
// Set up the object attributes.
|
|
//
|
|
|
|
RtlInitUnicodeString( &uRdrName, RdrPrefix );
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&uRdrName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
|
|
ntstatus = NtOpenFile( &handleRdr,
|
|
SYNCHRONIZE | FILE_LIST_DIRECTORY,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
FILE_SHARE_VALID_FLAGS,
|
|
FILE_SYNCHRONOUS_IO_NONALERT );
|
|
|
|
if ( !NT_SUCCESS(ntstatus) )
|
|
goto CleanExit;
|
|
|
|
dwRemoteNameLen = pszRemoteName? wcslen(pszRemoteName)*sizeof(WCHAR) : 0;
|
|
|
|
RequestPacketSize = sizeof( NWR_REQUEST_PACKET ) + dwRemoteNameLen;
|
|
|
|
RequestPacket = (PNWR_REQUEST_PACKET) LocalAlloc( LMEM_ZEROINIT,
|
|
RequestPacketSize );
|
|
|
|
if ( RequestPacket == NULL )
|
|
{
|
|
ntstatus = STATUS_NO_MEMORY;
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Fill out the request packet for FSCTL_NWR_GET_CONN_STATUS.
|
|
//
|
|
|
|
RequestPacket->Parameters.GetConnStatus.ResumeKey = *ResumeKey;
|
|
|
|
RequestPacket->Version = REQUEST_PACKET_VERSION;
|
|
RequestPacket->Parameters.GetConnStatus.ConnectionNameLength = dwRemoteNameLen;
|
|
|
|
RtlCopyMemory( &(RequestPacket->Parameters.GetConnStatus.ConnectionName[0]),
|
|
pszRemoteName,
|
|
dwRemoteNameLen );
|
|
|
|
ntstatus = NtFsControlFile( handleRdr,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
FSCTL_NWR_GET_CONN_STATUS,
|
|
(PVOID) RequestPacket,
|
|
RequestPacketSize,
|
|
(PVOID) Buffer,
|
|
BufferSize );
|
|
|
|
if ( NT_SUCCESS( ntstatus ))
|
|
ntstatus = IoStatusBlock.Status;
|
|
|
|
*EntriesRead = RequestPacket->Parameters.GetConnStatus.EntriesReturned;
|
|
*ResumeKey = RequestPacket->Parameters.GetConnStatus.ResumeKey;
|
|
*BytesNeeded = RequestPacket->Parameters.GetConnStatus.BytesNeeded;
|
|
|
|
CleanExit:
|
|
|
|
if ( handleRdr != NULL )
|
|
NtClose( handleRdr );
|
|
|
|
if ( RequestPacket != NULL )
|
|
LocalFree( RequestPacket );
|
|
|
|
return RtlNtStatusToDosError( ntstatus );
|
|
}
|
|
|
|
|
|
BOOL
|
|
NwIsNdsSyntax(
|
|
IN LPWSTR lpstrUnc
|
|
)
|
|
{
|
|
HANDLE hTreeConn;
|
|
DWORD dwOid;
|
|
DWORD status = NO_ERROR;
|
|
|
|
if ( lpstrUnc == NULL )
|
|
return FALSE;
|
|
|
|
status = NwOpenAndGetTreeInfo( lpstrUnc, &hTreeConn, &dwOid );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle( hTreeConn );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
NwOpenAndGetTreeInfo(
|
|
LPWSTR pszNdsUNCPath,
|
|
HANDLE *phTreeConn,
|
|
DWORD *pdwOid
|
|
)
|
|
{
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
WCHAR lpServerName[NW_MAX_SERVER_LEN];
|
|
UNICODE_STRING ServerName;
|
|
|
|
UNICODE_STRING ObjectName;
|
|
|
|
*phTreeConn = NULL;
|
|
|
|
ServerName.Length = 0;
|
|
ServerName.MaximumLength = sizeof( lpServerName );
|
|
ServerName.Buffer = lpServerName;
|
|
|
|
ObjectName.Buffer = NULL;
|
|
ObjectName.MaximumLength = ( wcslen( pszNdsUNCPath) + 1 ) * sizeof( WCHAR );
|
|
|
|
ObjectName.Length = NwParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer,
|
|
pszNdsUNCPath,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
if ( ObjectName.Length == 0 || ObjectName.Buffer == NULL )
|
|
{
|
|
return ERROR_PATH_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Open a NDS tree connection handle to \\treename
|
|
//
|
|
ntstatus = NwNdsOpenTreeHandle( &ObjectName, phTreeConn );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ))
|
|
{
|
|
return RtlNtStatusToDosError( ntstatus );
|
|
}
|
|
|
|
//
|
|
// Get the path to the container to open.
|
|
//
|
|
ObjectName.Length = NwParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer,
|
|
pszNdsUNCPath,
|
|
PARSE_NDS_GET_PATH_NAME );
|
|
|
|
if ( ObjectName.Length == 0 )
|
|
{
|
|
UNICODE_STRING Root;
|
|
|
|
RtlInitUnicodeString(&Root, L"[Root]");
|
|
|
|
//
|
|
// Resolve the path to get a NDS object id.
|
|
//
|
|
ntstatus = NwNdsResolveName( *phTreeConn,
|
|
&Root,
|
|
pdwOid,
|
|
&ServerName,
|
|
NULL,
|
|
0 );
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Resolve the path to get a NDS object id.
|
|
//
|
|
ntstatus = NwNdsResolveName( *phTreeConn,
|
|
&ObjectName,
|
|
pdwOid,
|
|
&ServerName,
|
|
NULL,
|
|
0 );
|
|
|
|
}
|
|
|
|
if ( ntstatus == STATUS_SUCCESS && ServerName.Length )
|
|
{
|
|
DWORD dwHandleType;
|
|
|
|
//
|
|
// NwNdsResolveName succeeded, but we were referred to
|
|
// another server, though pdwOid is still valid.
|
|
|
|
if ( *phTreeConn )
|
|
CloseHandle( *phTreeConn );
|
|
|
|
*phTreeConn = NULL;
|
|
|
|
//
|
|
// Open a NDS generic connection handle to \\ServerName
|
|
//
|
|
ntstatus = NwNdsOpenGenericHandle( &ServerName,
|
|
&dwHandleType,
|
|
phTreeConn );
|
|
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
return RtlNtStatusToDosError(ntstatus);
|
|
}
|
|
|
|
ASSERT( dwHandleType != HANDLE_TYPE_NCP_SERVER );
|
|
}
|
|
|
|
if ( !NT_SUCCESS( ntstatus ))
|
|
{
|
|
|
|
if ( *phTreeConn != NULL )
|
|
{
|
|
CloseHandle( *phTreeConn );
|
|
*phTreeConn = NULL;
|
|
}
|
|
return RtlNtStatusToDosError(ntstatus);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
static
|
|
DWORD
|
|
NwRegQueryValueExW(
|
|
IN HKEY hKey,
|
|
IN LPWSTR lpValueName,
|
|
OUT LPDWORD lpReserved,
|
|
OUT LPDWORD lpType,
|
|
OUT LPBYTE lpData,
|
|
IN OUT LPDWORD lpcbData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine supports the same functionality as Win32 RegQueryValueEx
|
|
API, except that it works. It returns the correct lpcbData value when
|
|
a NULL output buffer is specified.
|
|
|
|
This code is stolen from the service controller.
|
|
|
|
Arguments:
|
|
|
|
same as RegQueryValueEx
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR or reason for failure.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
UNICODE_STRING ValueName;
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInfo;
|
|
DWORD BufSize;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(lpReserved);
|
|
|
|
//
|
|
// Make sure we have a buffer size if the buffer is present.
|
|
//
|
|
if ((ARGUMENT_PRESENT(lpData)) && (! ARGUMENT_PRESENT(lpcbData))) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
RtlInitUnicodeString(&ValueName, lpValueName);
|
|
|
|
//
|
|
// Allocate memory for the ValueKeyInfo
|
|
//
|
|
BufSize = *lpcbData + sizeof(KEY_VALUE_FULL_INFORMATION) +
|
|
ValueName.Length
|
|
- sizeof(WCHAR); // subtract memory for 1 char because it's included
|
|
// in the sizeof(KEY_VALUE_FULL_INFORMATION).
|
|
|
|
KeyValueInfo = (PKEY_VALUE_FULL_INFORMATION) LocalAlloc(
|
|
LMEM_ZEROINIT,
|
|
(UINT) BufSize
|
|
);
|
|
|
|
if (KeyValueInfo == NULL) {
|
|
// if (DebugVerbose)
|
|
// printf("NWWORKSTATION: NwRegQueryValueExW: LocalAlloc failed %lu\n",
|
|
// GetLastError());
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
ntstatus = NtQueryValueKey(
|
|
hKey,
|
|
&ValueName,
|
|
KeyValueFullInformation,
|
|
(PVOID) KeyValueInfo,
|
|
(ULONG) BufSize,
|
|
(PULONG) &BufSize
|
|
);
|
|
|
|
if ((NT_SUCCESS(ntstatus) || (ntstatus == STATUS_BUFFER_OVERFLOW))
|
|
&& ARGUMENT_PRESENT(lpcbData)) {
|
|
|
|
*lpcbData = KeyValueInfo->DataLength;
|
|
}
|
|
|
|
if (NT_SUCCESS(ntstatus)) {
|
|
|
|
if (ARGUMENT_PRESENT(lpType)) {
|
|
*lpType = KeyValueInfo->Type;
|
|
}
|
|
|
|
|
|
if (ARGUMENT_PRESENT(lpData)) {
|
|
memcpy(
|
|
lpData,
|
|
(LPBYTE)KeyValueInfo + KeyValueInfo->DataOffset,
|
|
KeyValueInfo->DataLength
|
|
);
|
|
}
|
|
}
|
|
|
|
(void) LocalFree((HLOCAL) KeyValueInfo);
|
|
|
|
return RtlNtStatusToDosError(ntstatus);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwReadRegValue(
|
|
IN HKEY Key,
|
|
IN LPWSTR ValueName,
|
|
OUT LPWSTR *Value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function allocates the output buffer and reads the requested
|
|
value from the registry into it.
|
|
|
|
Arguments:
|
|
|
|
Key - Supplies opened handle to the key to read from.
|
|
|
|
ValueName - Supplies name of the value to retrieve data.
|
|
|
|
Value - Returns a pointer to the output buffer which points to
|
|
the memory allocated and contains the data read in from the
|
|
registry. This pointer must be freed with LocalFree when done.
|
|
|
|
Return Value:
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Failed to create buffer to read value into.
|
|
|
|
Error from registry call.
|
|
|
|
--*/
|
|
{
|
|
LONG RegError;
|
|
DWORD NumRequired = 0;
|
|
DWORD ValueType;
|
|
|
|
|
|
//
|
|
// Set returned buffer pointer to NULL.
|
|
//
|
|
*Value = NULL;
|
|
|
|
RegError = NwRegQueryValueExW(
|
|
Key,
|
|
ValueName,
|
|
NULL,
|
|
&ValueType,
|
|
(LPBYTE) NULL,
|
|
&NumRequired
|
|
);
|
|
|
|
if (RegError != ERROR_SUCCESS && NumRequired > 0) {
|
|
|
|
if ((*Value = (LPWSTR) LocalAlloc(
|
|
LMEM_ZEROINIT,
|
|
(UINT) NumRequired
|
|
)) == NULL) {
|
|
|
|
// if (DebugVerbose)
|
|
// printf("NWWORKSTATION: NwReadRegValue: LocalAlloc of size %lu failed %lu\n", NumRequired, GetLastError());
|
|
//
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
RegError = NwRegQueryValueExW(
|
|
Key,
|
|
ValueName,
|
|
NULL,
|
|
&ValueType,
|
|
(LPBYTE) *Value,
|
|
&NumRequired
|
|
);
|
|
}
|
|
else if (RegError == ERROR_SUCCESS) {
|
|
// if (DebugVerbose)
|
|
// printf("NWWORKSTATION: NwReadRegValue got SUCCESS with NULL buffer.");
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
if (RegError != ERROR_SUCCESS) {
|
|
|
|
if (*Value != NULL) {
|
|
(void) LocalFree((HLOCAL) *Value);
|
|
*Value = NULL;
|
|
}
|
|
|
|
return (DWORD) RegError;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwpGetCurrentUserRegKey(
|
|
IN DWORD DesiredAccess,
|
|
OUT HKEY *phKeyCurrentUser
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine opens the current user's registry key under
|
|
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NWCWorkstation\Parameters
|
|
|
|
Arguments:
|
|
|
|
DesiredAccess - The access mask to open the key with
|
|
|
|
phKeyCurrentUser - Receives the opened key handle
|
|
|
|
Return Value:
|
|
|
|
Returns the appropriate Win32 error.
|
|
|
|
--*/
|
|
{
|
|
DWORD err;
|
|
HKEY hkeyWksta;
|
|
LPWSTR CurrentUser;
|
|
DWORD Disposition;
|
|
|
|
//
|
|
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
|
// \NWCWorkstation\Parameters
|
|
//
|
|
err = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
NW_WORKSTATION_REGKEY,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
&hkeyWksta
|
|
);
|
|
|
|
if ( err ) {
|
|
// if (DebugVerbose)
|
|
// printf("NWPROVAU: NwGetCurrentUserRegKey open Paramters key unexpected error %lu!\n",err);
|
|
return err;
|
|
}
|
|
//
|
|
// Get the current user's SID string.
|
|
//
|
|
err = NwReadRegValue(
|
|
hkeyWksta,
|
|
NW_CURRENTUSER_VALUENAME,
|
|
&CurrentUser
|
|
);
|
|
|
|
|
|
if ( err ) {
|
|
// if (DebugVerbose)
|
|
// printf("NWPROVAU: NwGetCurrentUserRegKey read CurrentUser value unexpected error %lu !\n", err);
|
|
(void) RegCloseKey( hkeyWksta );
|
|
return err;
|
|
}
|
|
|
|
(void) RegCloseKey( hkeyWksta );
|
|
|
|
//
|
|
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
|
|
// \NWCWorkstation\Parameters\Option
|
|
//
|
|
err = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
NW_WORKSTATION_OPTION_REGKEY,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
&hkeyWksta
|
|
);
|
|
if ( err ) {
|
|
// if (DebugVerbose)
|
|
// printf("NWPROVAU: NwGetCurrentUserRegKey open Parameters\\Option key unexpected error %lu!\n", err);
|
|
return err;
|
|
}
|
|
|
|
//
|
|
// Open current user's key
|
|
//
|
|
err = RegOpenKeyExW(
|
|
hkeyWksta,
|
|
CurrentUser,
|
|
REG_OPTION_NON_VOLATILE,
|
|
DesiredAccess,
|
|
phKeyCurrentUser
|
|
);
|
|
|
|
if ( err == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
|
|
//
|
|
// Create <NewUser> key under NWCWorkstation\Parameters\Option
|
|
//
|
|
err = RegCreateKeyExW(
|
|
hkeyWksta,
|
|
CurrentUser,
|
|
0,
|
|
WIN31_CLASS,
|
|
REG_OPTION_NON_VOLATILE,
|
|
DesiredAccess,
|
|
NULL, // security attr
|
|
phKeyCurrentUser,
|
|
&Disposition
|
|
);
|
|
|
|
}
|
|
|
|
if ( err ) {
|
|
// if (DebugVerbose)
|
|
// printf("NWPROVAU: NwGetCurrentUserRegKey open or create of Parameters\\Option\\%ws key failed %lu\n", CurrentUser, err);
|
|
}
|
|
|
|
(void) RegCloseKey( hkeyWksta );
|
|
(void) LocalFree((HLOCAL)CurrentUser) ;
|
|
return err;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwQueryInfo(
|
|
OUT PDWORD pnPrintOptions,
|
|
OUT LPWSTR *ppszPreferredSrv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine gets the user's preferred server and print options from
|
|
the registry.
|
|
|
|
Arguments:
|
|
|
|
pnPrintOptions - Receives the user's print option
|
|
|
|
ppszPreferredSrv - Receives the user's preferred server
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns the appropriate Win32 error.
|
|
|
|
--*/
|
|
{
|
|
|
|
HKEY hKeyCurrentUser = NULL;
|
|
DWORD BufferSize;
|
|
DWORD BytesNeeded;
|
|
DWORD PrintOption;
|
|
DWORD ValueType;
|
|
LPWSTR PreferredServer ;
|
|
DWORD err ;
|
|
|
|
//
|
|
// get to right place in registry and allocate dthe buffer
|
|
//
|
|
if (err = NwpGetCurrentUserRegKey( KEY_READ, &hKeyCurrentUser))
|
|
{
|
|
//
|
|
// If somebody mess around with the registry and we can't find
|
|
// the registry, just use the defaults.
|
|
//
|
|
*ppszPreferredSrv = NULL;
|
|
// *pnPrintOptions = NW_PRINT_OPTION_DEFAULT;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
BufferSize = sizeof(WCHAR) * (MAX_PATH + 2) ;
|
|
PreferredServer = (LPWSTR) LocalAlloc(LPTR, BufferSize) ;
|
|
if (!PreferredServer)
|
|
return (GetLastError()) ;
|
|
|
|
//
|
|
// Read PreferredServer value into Buffer.
|
|
//
|
|
BytesNeeded = BufferSize ;
|
|
|
|
err = RegQueryValueExW( hKeyCurrentUser,
|
|
NW_SERVER_VALUENAME,
|
|
NULL,
|
|
&ValueType,
|
|
(LPBYTE) PreferredServer,
|
|
&BytesNeeded );
|
|
|
|
if (err != NO_ERROR)
|
|
{
|
|
//
|
|
// set to empty and carry on
|
|
//
|
|
PreferredServer[0] = 0;
|
|
}
|
|
|
|
|
|
if (hKeyCurrentUser != NULL)
|
|
(void) RegCloseKey(hKeyCurrentUser) ;
|
|
|
|
*ppszPreferredSrv = PreferredServer ;
|
|
return NO_ERROR ;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
NetwareGlobalPrint
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void NetwareGlobalPrint( NETDIAG_PARAMS* pParams,
|
|
NETDIAG_RESULT* pResults)
|
|
{
|
|
int ids;
|
|
LPTSTR pszConnType;
|
|
|
|
if (!pResults->Ipx.fEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (pParams->fVerbose || !FHrOK(pResults->Netware.hr))
|
|
{
|
|
BOOL fVerboseT, fReallyVerboseT;
|
|
|
|
PrintNewLine(pParams, 2);
|
|
PrintMessage(pParams, IDS_NETWARE_TITLE_MSG);
|
|
|
|
fVerboseT = pParams->fVerbose;
|
|
fReallyVerboseT = pParams->fReallyVerbose;
|
|
pParams->fReallyVerbose = TRUE;
|
|
|
|
PrintMessageList(pParams, &pResults->Netware.lmsgOutput);
|
|
|
|
pParams->fReallyVerbose = fReallyVerboseT;
|
|
pParams->fVerbose = fVerboseT;
|
|
|
|
|
|
// Now print out the results
|
|
if (FHrOK(pResults->Netware.hr))
|
|
{
|
|
// Print out the user name, server name, tree and context
|
|
PrintMessage(pParams,
|
|
IDS_NETWARE_USER_NAME,
|
|
pResults->Netware.pszUser == 0 ? _T("") : pResults->Netware.pszUser);
|
|
PrintMessage(pParams,
|
|
IDS_NETWARE_SERVER_NAME,
|
|
pResults->Netware.pszServer == 0 ? _T("") : pResults->Netware.pszServer);
|
|
PrintMessage(pParams,
|
|
IDS_NETWARE_TREE_NAME,
|
|
pResults->Netware.pszTree == 0 ? _T("") : pResults->Netware.pszTree);
|
|
PrintMessage(pParams,
|
|
IDS_NETWARE_CONTEXT,
|
|
pResults->Netware.pszContext == 0 ? _T("") : pResults->Netware.pszContext);
|
|
|
|
// Print out the connection type and nds
|
|
if (pResults->Netware.fConnStatus)
|
|
{
|
|
PrintMessage(pParams,
|
|
IDS_NETWARE_NDS,
|
|
MAP_YES_NO(pResults->Netware.fNds));
|
|
|
|
switch (pResults->Netware.dwConnType)
|
|
{
|
|
case NW_CONN_NOT_AUTHENTICATED:
|
|
ids = IDS_NETWARE_CONN_NOT_AUTHENTICATED;
|
|
break;
|
|
case NW_CONN_BINDERY_LOGIN:
|
|
ids = IDS_NETWARE_CONN_BINDERY_LOGIN;
|
|
break;
|
|
case NW_CONN_NDS_AUTHENTICATED_NO_LICENSE:
|
|
ids = IDS_NETWARE_CONN_NDS_AUTHENTICATED_NO_LICENSE;
|
|
break;
|
|
case NW_CONN_NDS_AUTHENTICATED_LICENSED:
|
|
ids = IDS_NETWARE_CONN_NDS_AUTHENTICATED_LICENSED;
|
|
break;
|
|
case NW_CONN_DISCONNECTED:
|
|
ids = IDS_NETWARE_CONN_DISCONNECTED;
|
|
break;
|
|
default:
|
|
ids = IDS_NETWARE_CONN_UNKNOWN;
|
|
break;
|
|
}
|
|
PrintMessage(pParams,
|
|
ids,
|
|
pResults->Netware.dwConnType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
NetwarePerInterfacePrint
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void NetwarePerInterfacePrint( NETDIAG_PARAMS* pParams,
|
|
NETDIAG_RESULT* pResults,
|
|
INTERFACE_RESULT *pInterfaceResults)
|
|
{
|
|
// no per-interface results
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
NetwareCleanup
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void NetwareCleanup( NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
|
|
{
|
|
Free(pResults->Netware.pszUser);
|
|
pResults->Netware.pszUser = NULL;
|
|
|
|
Free(pResults->Netware.pszServer);
|
|
pResults->Netware.pszServer = NULL;
|
|
|
|
Free(pResults->Netware.pszTree);
|
|
pResults->Netware.pszTree = NULL;
|
|
|
|
Free(pResults->Netware.pszContext);
|
|
pResults->Netware.pszContext = NULL;
|
|
|
|
MessageListCleanUp(&pResults->Netware.lmsgOutput);
|
|
}
|
|
|
|
|