384 lines
8.3 KiB
C++
384 lines
8.3 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
netinfo.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Contains entry points for Winnet API supported by the
|
|||
|
Multi-Provider Router.
|
|||
|
Contains:
|
|||
|
WNetGetNetworkInformationW
|
|||
|
WNetGetProviderNameW
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Anirudh Sahni (anirudhs) 08-Jun-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode -Win32
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
08-Jun-1995 anirudhs
|
|||
|
Created
|
|||
|
|
|||
|
05-May-1999 jschwart
|
|||
|
Make provider addition/removal dynamic
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//
|
|||
|
// INCLUDES
|
|||
|
//
|
|||
|
|
|||
|
#include "precomp.hxx"
|
|||
|
#include <tstr.h> // WCSSIZE
|
|||
|
|
|||
|
//
|
|||
|
// EXTERNAL GLOBALS
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Defines
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Local Function Prototypes
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
WNetGetNetworkInformationW(
|
|||
|
IN LPCWSTR lpProvider,
|
|||
|
OUT LPNETINFOSTRUCT lpNetInfoStruct
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns extended information about a named network provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpProvider - Pointer to the name of the provider for which information is
|
|||
|
required.
|
|||
|
|
|||
|
lpNetInfoStruct - Pointer to a structure that describes the behavior of
|
|||
|
the network.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
WN_SUCCESS - Call is successful.
|
|||
|
|
|||
|
WN_BAD_PROVIDER - lpProvider does not match any active network provider.
|
|||
|
|
|||
|
WN_BAD_VALUE - lpProvider->cbStructure does not contain a valid structure
|
|||
|
size.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Win 95's implementation of this API will accept a structure smaller than
|
|||
|
a NETINFOSTRUCT, and will fill in as many elements of the structure as
|
|||
|
will fit. This strange feature is not documented and is not used in
|
|||
|
the shell, so we don't do it here. It may be useful for future versions
|
|||
|
of this API that add fields to the NETINFOSTRUCT.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD status = WN_SUCCESS;
|
|||
|
LPPROVIDER Provider;
|
|||
|
|
|||
|
if (!(ARGUMENT_PRESENT(lpProvider) &&
|
|||
|
ARGUMENT_PRESENT(lpNetInfoStruct)))
|
|||
|
{
|
|||
|
SetLastError(WN_BAD_POINTER);
|
|||
|
return WN_BAD_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
MprCheckProviders();
|
|||
|
|
|||
|
CProviderSharedLock PLock;
|
|||
|
|
|||
|
INIT_IF_NECESSARY(NETWORK_LEVEL,status);
|
|||
|
|
|||
|
__try
|
|||
|
{
|
|||
|
//
|
|||
|
// Validate the parameters that we can.
|
|||
|
//
|
|||
|
|
|||
|
if (lpNetInfoStruct->cbStructure < sizeof(NETINFOSTRUCT))
|
|||
|
{
|
|||
|
status = WN_BAD_VALUE;
|
|||
|
__leave;
|
|||
|
}
|
|||
|
|
|||
|
if (IsBadWritePtr(lpNetInfoStruct, lpNetInfoStruct->cbStructure))
|
|||
|
{
|
|||
|
status = WN_BAD_POINTER;
|
|||
|
__leave;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Look up the provider by name
|
|||
|
//
|
|||
|
DWORD i;
|
|||
|
if (!MprGetProviderIndex(lpProvider, &i))
|
|||
|
{
|
|||
|
status = WN_BAD_PROVIDER;
|
|||
|
__leave;
|
|||
|
}
|
|||
|
|
|||
|
Provider = & GlobalProviderInfo[i];
|
|||
|
}
|
|||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|||
|
{
|
|||
|
status = GetExceptionCode();
|
|||
|
if (status != EXCEPTION_ACCESS_VIOLATION)
|
|||
|
{
|
|||
|
MPR_LOG(ERROR,
|
|||
|
"WNetGetNetworkInformationW: Unexpected Exception %#lx\n",
|
|||
|
status);
|
|||
|
}
|
|||
|
status = WN_BAD_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
if (status != WN_SUCCESS)
|
|||
|
{
|
|||
|
SetLastError(status);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the fields of the structure
|
|||
|
//
|
|||
|
|
|||
|
lpNetInfoStruct->cbStructure = sizeof(NETINFOSTRUCT);
|
|||
|
|
|||
|
lpNetInfoStruct->dwProviderVersion = Provider->GetCaps(WNNC_DRIVER_VERSION);
|
|||
|
|
|||
|
switch (Provider->GetCaps(WNNC_START))
|
|||
|
{
|
|||
|
case 0x0:
|
|||
|
lpNetInfoStruct->dwStatus = WN_NO_NETWORK;
|
|||
|
break;
|
|||
|
|
|||
|
case 0x1:
|
|||
|
lpNetInfoStruct->dwStatus = WN_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
lpNetInfoStruct->dwStatus = WN_FUNCTION_BUSY;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// We don't support this field. The shell doesn't use it.
|
|||
|
// Win 95 gets it by looking at registry entries created by the
|
|||
|
// provider. If the registry entries don't exist it leaves the
|
|||
|
// dwCharacteristics field as 0, which means that the provider
|
|||
|
// doesn't require redirection of a local drive to make a connection.
|
|||
|
lpNetInfoStruct->dwCharacteristics = 0;
|
|||
|
|
|||
|
lpNetInfoStruct->dwHandle = (ULONG_PTR) Provider->Handle;
|
|||
|
|
|||
|
// Note, this is a WORD field, not a DWORD.
|
|||
|
// Why does Win 95 omit the LOWORD anyway?
|
|||
|
lpNetInfoStruct->wNetType = HIWORD(Provider->Type);
|
|||
|
|
|||
|
// We don't support these 2 fields. The shell doesn't use them.
|
|||
|
// Win 95 gets them by calling NPValidLocalDevices. If this entry
|
|||
|
// point doesn't exist it looks in the registry. If the registry
|
|||
|
// value doesn't exist it uses NPP_ALLVALID which is defined as
|
|||
|
// 0xffffffff.
|
|||
|
lpNetInfoStruct->dwPrinters = 0xffffffff;
|
|||
|
|
|||
|
lpNetInfoStruct->dwDrives = 0xffffffff;
|
|||
|
|
|||
|
return WN_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
WNetGetProviderNameW(
|
|||
|
IN DWORD dwNetType,
|
|||
|
OUT LPWSTR lpProviderName,
|
|||
|
IN OUT LPDWORD lpBufferSize
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns the provider name for a specified type of network.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwNetType - The network type unique to the network. Only the high word
|
|||
|
of the network type is used; the subtype in the low word is ignored.
|
|||
|
If two networks claim the same type, the first one loaded is returned.
|
|||
|
|
|||
|
lpProviderName - Pointer to a buffer in which to return the provider name.
|
|||
|
|
|||
|
lpBufferSize - On entry, size of the lpProviderName buffer in characters.
|
|||
|
On exit, iff the return code is WN_MORE_DATA, set to the required size
|
|||
|
to hold the provider name.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
WN_SUCCESS - Call is successful.
|
|||
|
|
|||
|
WN_MORE_DATA - The buffer is too small to hold the provider name.
|
|||
|
|
|||
|
WN_NO_NETWORK - lpProvider does not match any active network provider.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD status = WN_SUCCESS;
|
|||
|
|
|||
|
__try
|
|||
|
{
|
|||
|
//
|
|||
|
// Validate the parameters that we can.
|
|||
|
//
|
|||
|
if (IS_BAD_WCHAR_BUFFER(lpProviderName, lpBufferSize))
|
|||
|
{
|
|||
|
status = WN_BAD_POINTER;
|
|||
|
}
|
|||
|
}
|
|||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|||
|
{
|
|||
|
status = GetExceptionCode();
|
|||
|
if (status != EXCEPTION_ACCESS_VIOLATION)
|
|||
|
{
|
|||
|
MPR_LOG(ERROR,
|
|||
|
"WNetGetProviderNameW: Unexpected Exception %#lx\n",
|
|||
|
status);
|
|||
|
}
|
|||
|
status = WN_BAD_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
if (status != WN_SUCCESS)
|
|||
|
{
|
|||
|
SetLastError(status);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
MprCheckProviders();
|
|||
|
|
|||
|
CProviderSharedLock PLock;
|
|||
|
|
|||
|
INIT_IF_NECESSARY(NETWORK_LEVEL,status);
|
|||
|
|
|||
|
//
|
|||
|
// Loop through the list of providers to find one with the specified
|
|||
|
// net type.
|
|||
|
//
|
|||
|
LPPROVIDER provider = MprFindProviderByType(dwNetType);
|
|||
|
|
|||
|
if (provider == NULL)
|
|||
|
{
|
|||
|
status = WN_NO_NETWORK;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// Copy the provider name to the caller's buffer
|
|||
|
//
|
|||
|
DWORD dwReqSize = wcslen(provider->Resource.lpProvider) + 1;
|
|||
|
if (*lpBufferSize < dwReqSize)
|
|||
|
{
|
|||
|
status = WN_MORE_DATA;
|
|||
|
*lpBufferSize = dwReqSize;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = WN_SUCCESS;
|
|||
|
wcscpy(lpProviderName, provider->Resource.lpProvider);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (status != WN_SUCCESS)
|
|||
|
{
|
|||
|
SetLastError(status);
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
WNetGetProviderTypeW(
|
|||
|
IN LPCWSTR lpProvider,
|
|||
|
OUT LPDWORD lpdwNetType
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns the network type for a named network provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpProvider - Pointer to the name of the provider for which information is
|
|||
|
required.
|
|||
|
|
|||
|
lpdwNetType - Pointer to a network type value that is filled in.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
WN_SUCCESS - Call is successful.
|
|||
|
|
|||
|
WN_BAD_PROVIDER - lpProvider does not match any active network provider.
|
|||
|
|
|||
|
WN_BAD_POINTER - an illegal argument was passed in.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Since this is an internal, private API used only by the shell, we do
|
|||
|
minimal parameter validation, to make it as fast as possible.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD status = WN_SUCCESS;
|
|||
|
|
|||
|
if (!(ARGUMENT_PRESENT(lpProvider) &&
|
|||
|
ARGUMENT_PRESENT(lpdwNetType)))
|
|||
|
{
|
|||
|
SetLastError(WN_BAD_POINTER);
|
|||
|
return WN_BAD_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
MprCheckProviders();
|
|||
|
|
|||
|
CProviderSharedLock PLock;
|
|||
|
|
|||
|
INIT_IF_NECESSARY(NETWORK_LEVEL,status);
|
|||
|
|
|||
|
//
|
|||
|
// Look up the provider by name
|
|||
|
//
|
|||
|
LPPROVIDER provider = MprFindProviderByName(lpProvider);
|
|||
|
if (NULL == provider)
|
|||
|
{
|
|||
|
SetLastError(WN_BAD_PROVIDER);
|
|||
|
return WN_BAD_PROVIDER;
|
|||
|
}
|
|||
|
|
|||
|
*lpdwNetType = provider->Type;
|
|||
|
return WN_SUCCESS;
|
|||
|
}
|