1957 lines
50 KiB
C
1957 lines
50 KiB
C
/*
|
|
* cnrlink.c - CNRLink ADT module.
|
|
*/
|
|
|
|
|
|
/* Headers
|
|
**********/
|
|
|
|
#include "project.h"
|
|
#pragma hdrstop
|
|
|
|
#include "cnrlink.h"
|
|
#include "server.h"
|
|
|
|
|
|
/* Constants
|
|
************/
|
|
|
|
/* WNetUseConnection() flag combinations */
|
|
|
|
#define ALL_CONNECT_IN_FLAGS (CONNECT_UPDATE_PROFILE |\
|
|
CONNECT_UPDATE_RECENT |\
|
|
CONNECT_TEMPORARY |\
|
|
CONNECT_INTERACTIVE |\
|
|
CONNECT_PROMPT |\
|
|
CONNECT_REDIRECT)
|
|
|
|
#define ALL_CONNECT_OUT_FLAGS (CONNECT_REFCOUNT |\
|
|
CONNECT_LOCALDRIVE)
|
|
|
|
|
|
/* Macros
|
|
*********/
|
|
|
|
/* macros for accessing ICNRLINK data */
|
|
|
|
#define ICNRL_Remote_Name_PtrA(picnrl) \
|
|
((LPSTR)(((PBYTE)(picnrl)) + (picnrl)->ucbNetNameOffset))
|
|
|
|
#define ICNRL_Device_PtrA(picnrl) \
|
|
((LPSTR)(((PBYTE)(picnrl)) + (picnrl)->ucbDeviceOffset))
|
|
|
|
#define ICNRL_Remote_Name_PtrW(picnrl) \
|
|
((LPWSTR)(((PBYTE)(picnrl)) + (picnrl)->ucbNetNameOffsetW))
|
|
|
|
#define ICNRL_Device_PtrW(picnrl) \
|
|
((LPWSTR)(((PBYTE)(picnrl)) + (picnrl)->ucbDeviceOffsetW))
|
|
|
|
#define IS_ICNRL_ANSI(picnrl) \
|
|
((PBYTE)(picnrl) + ((PICNRLINKW)(picnrl))->ucbNetNameOffset) == (PBYTE)&(((PICNRLINKW)(picnrl))->ucbNetNameOffsetW)
|
|
|
|
#ifdef UNICODE
|
|
#define ICNRL_Remote_Name_Ptr(picnrl) ICNRL_Remote_Name_PtrW(picnrl)
|
|
#define ICNRL_Device_Ptr(picnrl) ICNRL_Device_PtrW(picnrl)
|
|
#else
|
|
#define ICNRL_Remote_Name_Ptr(picnrl) ICNRL_Remote_Name_PtrA(picnrl)
|
|
#define ICNRL_Device_Ptr(picnrl) ICNRL_Device_PtrA(picnrl)
|
|
#endif
|
|
|
|
/* Types
|
|
********/
|
|
|
|
/*
|
|
@doc INTERNAL
|
|
|
|
@enum ICNRLINKFLAGS | Internal CNRLink structure flags.
|
|
*/
|
|
|
|
typedef enum _icnrlinkflags
|
|
{
|
|
/*
|
|
@emem ICNRL_FL_VALID_DEVICE | If set, last redirected drive is valid. If
|
|
clear, last redirected drive is not valid.
|
|
*/
|
|
|
|
ICNRL_FL_VALID_DEVICE = 0x0001,
|
|
|
|
/*
|
|
@emem ICNRL_FL_VALID_NET_TYPE | If set, net type is valid. If clear, net
|
|
type is not valid.
|
|
*/
|
|
|
|
ICNRL_FL_VALID_NET_TYPE = 0x0002,
|
|
|
|
/* @emem ALL_ICNRL_FLAGS | All internal CNRLink structure flags. */
|
|
|
|
ALL_ICNRL_FLAGS = (ICNRL_FL_VALID_DEVICE |
|
|
ICNRL_FL_VALID_NET_TYPE)
|
|
}
|
|
ICNRLINKFLAGS;
|
|
|
|
/*
|
|
@doc INTERNAL
|
|
|
|
@struct ICNRLINK | Internal definition of relocatable connectable network
|
|
resource (CNR) link structure. An <t ILINKINFO> structure may contain an
|
|
ICNRLINK structure. An ICNRLINK structure consists of a header described as
|
|
below, followed by variable-length data.
|
|
*/
|
|
|
|
typedef struct _icnrlinkA
|
|
{
|
|
/*
|
|
@field UINT | ucbSize | Length of ICNRLINK structure in bytes, including
|
|
ucbSize field.
|
|
*/
|
|
|
|
UINT ucbSize;
|
|
|
|
/*
|
|
@field DWORD | dwFlags | A bit mask of flags from the <t ICNRLINKFLAGS>
|
|
enumeration.
|
|
*/
|
|
|
|
DWORD dwFlags;
|
|
|
|
/*
|
|
@field UINT | ucbNetNameOffset | Offset in bytes of CNR name string from
|
|
base of structure. The CNR name string may be passed to
|
|
WNetUseConnection() to add a connection to the CNR.<nl>
|
|
Example CNRLink name string: "\\\\fredbird\\work".
|
|
*/
|
|
|
|
UINT ucbNetNameOffset;
|
|
|
|
/*
|
|
@field UINT | ucbDeviceOffset | Offset in bytes of last redirected local
|
|
device string from base of structure. This field is only valid if
|
|
ICNRL_FL_VALID_DEVICE is set in dwFlags. The last redirected local
|
|
device string may be passed to WNetUseConnection() to add a redirected
|
|
device connection to the CNR.<nl>
|
|
Example last redirected local device string: "D:".
|
|
*/
|
|
|
|
UINT ucbDeviceOffset;
|
|
|
|
/*
|
|
@field DWORD | dwNetType | The network type as returned in a
|
|
NETINFOSTRUCT. This field is only valid if ICNRL_FL_VALID_NET_TYPE is
|
|
set in dwFlags. The net type is used to retrieve the host net resource's
|
|
host NP's name to use in calling WNetUseConnection().<nl>
|
|
Example net type: WNNC_NET_NETWARE.
|
|
*/
|
|
|
|
DWORD dwNetType;
|
|
}
|
|
ICNRLINKA;
|
|
DECLARE_STANDARD_TYPES(ICNRLINKA);
|
|
|
|
#ifdef UNICODE
|
|
typedef struct _icnrlinkW
|
|
{
|
|
/*
|
|
@field UINT | ucbSize | Length of ICNRLINK structure in bytes, including
|
|
ucbSize field.
|
|
*/
|
|
|
|
UINT ucbSize;
|
|
|
|
/*
|
|
@field DWORD | dwFlags | A bit mask of flags from the <t ICNRLINKFLAGS>
|
|
enumeration.
|
|
*/
|
|
|
|
DWORD dwFlags;
|
|
|
|
/*
|
|
@field UINT | ucbNetNameOffset | Offset in bytes of CNR name string from
|
|
base of structure. The CNR name string may be passed to
|
|
WNetUseConnection() to add a connection to the CNR.<nl>
|
|
Example CNRLink name string: "\\\\fredbird\\work".
|
|
*/
|
|
|
|
UINT ucbNetNameOffset;
|
|
|
|
/*
|
|
@field UINT | ucbDeviceOffset | Offset in bytes of last redirected local
|
|
device string from base of structure. This field is only valid if
|
|
ICNRL_FL_VALID_DEVICE is set in dwFlags. The last redirected local
|
|
device string may be passed to WNetUseConnection() to add a redirected
|
|
device connection to the CNR.<nl>
|
|
Example last redirected local device string: "D:".
|
|
*/
|
|
|
|
UINT ucbDeviceOffset;
|
|
|
|
/*
|
|
@field DWORD | dwNetType | The network type as returned in a
|
|
NETINFOSTRUCT. This field is only valid if ICNRL_FL_VALID_NET_TYPE is
|
|
set in dwFlags. The net type is used to retrieve the host net resource's
|
|
host NP's name to use in calling WNetUseConnection().<nl>
|
|
Example net type: WNNC_NET_NETWARE.
|
|
*/
|
|
|
|
DWORD dwNetType;
|
|
|
|
/*
|
|
These members are for storing the unicode version of the strings
|
|
*/
|
|
UINT ucbNetNameOffsetW;
|
|
UINT ucbDeviceOffsetW;
|
|
}
|
|
ICNRLINKW;
|
|
DECLARE_STANDARD_TYPES(ICNRLINKW);
|
|
#endif
|
|
|
|
#ifdef UNICODE
|
|
#define ICNRLINK ICNRLINKW
|
|
#define PICNRLINK PICNRLINKW
|
|
#define CICNRLINK CICNRLINKW
|
|
#define PCICNRLINK PCICNRLINKW
|
|
#else
|
|
#define ICNRLINK ICNRLINKA
|
|
#define PICNRLINK PICNRLINKA
|
|
#define CICNRLINK CICNRLINKA
|
|
#define PCICNRLINK PCICNRLINKA
|
|
#endif
|
|
|
|
/* Exported from MPR.DLL, but not in winnetwk.h
|
|
*/
|
|
#ifdef UNICODE
|
|
DWORD APIENTRY WNetGetResourceInformationW (LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPTSTR * lplpSystem);
|
|
#define WNetGetResourceInformation WNetGetResourceInformationW
|
|
#else
|
|
DWORD APIENTRY WNetGetResourceInformationA (LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPTSTR * lplpSystem);
|
|
#define WNetGetResourceInformation WNetGetResourceInformationA
|
|
#endif
|
|
|
|
|
|
/***************************** Private Functions *****************************/
|
|
|
|
/* Module Prototypes
|
|
********************/
|
|
|
|
PRIVATE_CODE BOOL GetNetPathFromLocalPath(LPCTSTR, LPTSTR, LPCTSTR *, PBOOL, PDWORD);
|
|
PRIVATE_CODE BOOL UnifyICNRLinkInfo(LPCTSTR, DWORD, LPCTSTR, DWORD, PICNRLINK *, PUINT);
|
|
PRIVATE_CODE BOOL GetNetType(LPCTSTR, PDWORD);
|
|
PRIVATE_CODE BOOL GetNetProviderName(PCICNRLINK, LPTSTR);
|
|
PRIVATE_CODE COMPARISONRESULT CompareNetNames(LPCTSTR, LPCTSTR);
|
|
PRIVATE_CODE BOOL SearchForRedirectedConnection(PCICNRLINK, LPTSTR);
|
|
|
|
#if defined(DEBUG) || defined (VSTF)
|
|
|
|
PRIVATE_CODE BOOL IsValidDevice(LPCTSTR);
|
|
PRIVATE_CODE BOOL IsValidNetType(DWORD);
|
|
PRIVATE_CODE BOOL IsValidPCICNRLINK(PCICNRLINK);
|
|
|
|
#endif
|
|
|
|
#if defined(DEBUG)
|
|
|
|
PRIVATE_CODE BOOL IsValidNetProviderName(LPCTSTR);
|
|
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
DWORD APIENTRY
|
|
WNetGetNetworkInformationW(
|
|
LPCWSTR lpProvider,
|
|
LPNETINFOSTRUCT lpNetInfoStruct
|
|
)
|
|
{
|
|
if (wcsicmp(lpProvider, L"Microsoft Windows Network") == 0)
|
|
{
|
|
lpNetInfoStruct->wNetType = (WORD)WNNC_NET_LANMAN;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else if (wcsicmp(lpProvider, L"Novell Network") == 0)
|
|
{
|
|
lpNetInfoStruct->wNetType = (WORD)WNNC_NET_NETWARE;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** GetNetPathFromLocalPath()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL GetNetPathFromLocalPath(LPCTSTR pcszLocalPath,
|
|
LPTSTR pszNetNameBuf,
|
|
LPCTSTR *ppcszCommonPathSuffix,
|
|
PBOOL pbIsShared, PDWORD pdwNetType)
|
|
{
|
|
BOOL bResult = TRUE;
|
|
PCSERVERVTABLE pcsvt;
|
|
|
|
ASSERT(IsDrivePath(pcszLocalPath));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszNetNameBuf, STR, MAX_PATH_LEN));
|
|
ASSERT(IS_VALID_WRITE_PTR(ppcszCommonPathSuffix, LPCTSTR));
|
|
ASSERT(IS_VALID_WRITE_PTR(pbIsShared, BOOL));
|
|
ASSERT(IS_VALID_WRITE_PTR(pdwNetType, DWORD));
|
|
|
|
*pbIsShared = FALSE;
|
|
|
|
if (GetServerVTable(&pcsvt))
|
|
{
|
|
TCHAR rgchSharedPath[MAX_PATH_LEN];
|
|
|
|
ASSERT(lstrlen(pcszLocalPath) < ARRAYSIZE(rgchSharedPath));
|
|
lstrcpy(rgchSharedPath, pcszLocalPath);
|
|
|
|
FOREVER
|
|
{
|
|
if ((pcsvt->GetNetResourceFromLocalPath)(rgchSharedPath,
|
|
pszNetNameBuf, MAX_PATH_LEN,
|
|
pdwNetType))
|
|
{
|
|
ASSERT(lstrlen(pszNetNameBuf) < MAX_PATH_LEN);
|
|
|
|
/* Determine common path suffix. */
|
|
|
|
*ppcszCommonPathSuffix = pcszLocalPath + lstrlen(rgchSharedPath);
|
|
|
|
/* Skip any leading slash. */
|
|
|
|
if (IS_SLASH(**ppcszCommonPathSuffix))
|
|
*ppcszCommonPathSuffix = CharNext(*ppcszCommonPathSuffix);
|
|
|
|
ASSERT(! IS_SLASH(**ppcszCommonPathSuffix));
|
|
|
|
// if it is terminated with a $ it is a hidden share, in that
|
|
// case don't consider this shared
|
|
*pbIsShared = pszNetNameBuf[lstrlen(pszNetNameBuf) -1] != TEXT('$');
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (! DeleteLastDrivePathElement(rgchSharedPath))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ASSERT(! bResult ||
|
|
! *pbIsShared ||
|
|
(EVAL(IsUNCPath(pszNetNameBuf)) &&
|
|
IS_VALID_STRING_PTR(*ppcszCommonPathSuffix, CSTR) &&
|
|
EVAL(*ppcszCommonPathSuffix >= pcszLocalPath) &&
|
|
EVAL(IsStringContained(pcszLocalPath, *ppcszCommonPathSuffix)) &&
|
|
EVAL(IsValidNetType(*pdwNetType))));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** UnifyICNRLinkInfo()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL UnifyICNRLinkInfo(LPCTSTR pcszNetName, DWORD dwFlags,
|
|
LPCTSTR pcszDevice, DWORD dwNetType,
|
|
PICNRLINK *ppicnrl, PUINT pucbICNRLinkLen)
|
|
{
|
|
BOOL bResult;
|
|
UINT ucbDataOffset;
|
|
#ifdef UNICODE
|
|
BOOL bUnicode;
|
|
UINT cchChars;
|
|
CHAR szAnsiNetName[MAX_PATH];
|
|
CHAR szAnsiDevice[MAX_PATH];
|
|
UINT cbAnsiNetName;
|
|
UINT cbWideNetName;
|
|
UINT cbAnsiDevice;
|
|
UINT cbWideDevice;
|
|
UINT cbChars;
|
|
#endif
|
|
|
|
ASSERT(IsUNCPath(pcszNetName));
|
|
ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_ICNRL_FLAGS));
|
|
ASSERT(IS_FLAG_CLEAR(dwFlags, ICNRL_FL_VALID_DEVICE) ||
|
|
IsValidDevice(pcszDevice));
|
|
ASSERT(IS_FLAG_CLEAR(dwFlags, ICNRL_FL_VALID_NET_TYPE) ||
|
|
IsValidNetType(dwNetType));
|
|
ASSERT(IS_VALID_WRITE_PTR(ppicnrl, PCNRLINK));
|
|
ASSERT(IS_VALID_WRITE_PTR(pucbICNRLinkLen, UINT));
|
|
|
|
#ifdef UNICODE
|
|
bUnicode = FALSE;
|
|
|
|
cbAnsiNetName = WideCharToMultiByte(CP_ACP, 0,
|
|
pcszNetName, -1,
|
|
szAnsiNetName, MAX_PATH,
|
|
0, 0);
|
|
if ( cbAnsiNetName == 0 )
|
|
{
|
|
bUnicode = FALSE;
|
|
}
|
|
else
|
|
{
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
|
|
cbChars = MultiByteToWideChar(CP_ACP, 0,
|
|
szAnsiNetName, -1,
|
|
szWideNetName, MAX_PATH);
|
|
if ( cbChars == 0 || lstrcmp(pcszNetName,szWideNetName) != 0 )
|
|
{
|
|
bUnicode = TRUE;
|
|
}
|
|
}
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
{
|
|
cbAnsiDevice = WideCharToMultiByte(CP_ACP, 0,
|
|
pcszDevice, -1,
|
|
szAnsiDevice, MAX_PATH,
|
|
0, 0);
|
|
if ( cbAnsiDevice == 0 )
|
|
{
|
|
bUnicode = FALSE;
|
|
}
|
|
else
|
|
{
|
|
WCHAR szWideDevice[MAX_PATH];
|
|
|
|
cchChars = MultiByteToWideChar(CP_ACP, 0,
|
|
szAnsiDevice, -1,
|
|
szWideDevice, MAX_PATH);
|
|
if ( cchChars == 0 || lstrcmp(pcszDevice,szWideDevice) != 0 )
|
|
{
|
|
bUnicode = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cbAnsiDevice = 0;
|
|
}
|
|
|
|
if ( bUnicode )
|
|
{
|
|
ucbDataOffset = SIZEOF(ICNRLINKW);
|
|
|
|
/* (+ 1) for null terminator. */
|
|
cbWideNetName = (lstrlen(pcszNetName) + 1) * sizeof(TCHAR);
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
cbWideDevice = (lstrlen(pcszDevice) + 1) * sizeof(TCHAR);
|
|
else
|
|
cbWideDevice = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
ucbDataOffset = SIZEOF(ICNRLINKA);
|
|
|
|
cbWideNetName = 0;
|
|
cbWideDevice = 0;
|
|
}
|
|
|
|
*pucbICNRLinkLen = ucbDataOffset +
|
|
cbAnsiNetName +
|
|
cbAnsiDevice;
|
|
if ( bUnicode )
|
|
{
|
|
*pucbICNRLinkLen = ALIGN_WORD_CNT(*pucbICNRLinkLen) +
|
|
cbWideNetName +
|
|
cbWideDevice;
|
|
}
|
|
|
|
#else
|
|
|
|
/* Assume we won't overflow *pucbICNRLinkLen here. */
|
|
|
|
/* (+ 1) for null terminator. */
|
|
|
|
*pucbICNRLinkLen = SIZEOF(**ppicnrl) +
|
|
(lstrlen(pcszNetName) + 1) * SIZEOF(TCHAR);
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
/* (+ 1) for null terminator. */
|
|
*pucbICNRLinkLen += (lstrlen(pcszDevice) + 1) * SIZEOF(TCHAR);
|
|
|
|
ucbDataOffset = SIZEOF(ICNRLINKA);
|
|
#endif
|
|
|
|
bResult = AllocateMemory(*pucbICNRLinkLen, ppicnrl);
|
|
|
|
if (bResult)
|
|
{
|
|
(*ppicnrl)->ucbSize = *pucbICNRLinkLen;
|
|
(*ppicnrl)->dwFlags = dwFlags;
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_NET_TYPE))
|
|
(*ppicnrl)->dwNetType = dwNetType;
|
|
else
|
|
(*ppicnrl)->dwNetType = 0;
|
|
|
|
/* Append remote name. */
|
|
|
|
(*ppicnrl)->ucbNetNameOffset = ucbDataOffset;
|
|
|
|
#ifdef UNICODE
|
|
lstrcpyA(ICNRL_Remote_Name_PtrA(*ppicnrl), szAnsiNetName);
|
|
ucbDataOffset += cbAnsiNetName;
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
{
|
|
/* Append device name. */
|
|
|
|
(*ppicnrl)->ucbDeviceOffset = ucbDataOffset;
|
|
lstrcpyA(ICNRL_Device_PtrA(*ppicnrl), szAnsiDevice);
|
|
|
|
ucbDataOffset += cbAnsiDevice;
|
|
}
|
|
else
|
|
{
|
|
(*ppicnrl)->ucbDeviceOffset = 0;
|
|
}
|
|
|
|
if ( bUnicode )
|
|
{
|
|
ucbDataOffset = ALIGN_WORD_CNT(ucbDataOffset);
|
|
|
|
(*ppicnrl)->ucbNetNameOffsetW = ucbDataOffset;
|
|
|
|
lstrcpy(ICNRL_Remote_Name_PtrW(*ppicnrl), pcszNetName);
|
|
ucbDataOffset += cbWideNetName;
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
{
|
|
/* Append device name. */
|
|
|
|
(*ppicnrl)->ucbDeviceOffsetW = ucbDataOffset;
|
|
lstrcpy(ICNRL_Device_Ptr(*ppicnrl), pcszDevice);
|
|
|
|
/* (+ 1) for null terminator. */
|
|
ucbDataOffset += cbWideDevice;
|
|
}
|
|
else
|
|
{
|
|
(*ppicnrl)->ucbDeviceOffsetW = 0;
|
|
}
|
|
|
|
}
|
|
#else
|
|
lstrcpy(ICNRL_Remote_Name_Ptr(*ppicnrl), pcszNetName);
|
|
/* (+ 1) for null terminator. */
|
|
ucbDataOffset += lstrlen(pcszNetName) + 1;
|
|
|
|
if (IS_FLAG_SET(dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
{
|
|
/* Append device name. */
|
|
|
|
(*ppicnrl)->ucbDeviceOffset = ucbDataOffset;
|
|
lstrcpy(ICNRL_Device_Ptr(*ppicnrl), pcszDevice);
|
|
#ifdef DEBUG
|
|
/* (+ 1) for null terminator. */
|
|
ucbDataOffset += (lstrlen(pcszDevice) + 1) * SIZEOF(TCHAR);
|
|
#endif
|
|
}
|
|
else
|
|
(*ppicnrl)->ucbDeviceOffset = 0;
|
|
#endif
|
|
|
|
/* Do all the calculated lengths match? */
|
|
|
|
ASSERT(ucbDataOffset == (*ppicnrl)->ucbSize);
|
|
ASSERT(ucbDataOffset == *pucbICNRLinkLen);
|
|
}
|
|
|
|
ASSERT(! bResult ||
|
|
(IS_VALID_STRUCT_PTR(*ppicnrl, CICNRLINK) &&
|
|
EVAL(*pucbICNRLinkLen == GetCNRLinkLen((PCCNRLINK)*ppicnrl))));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** GetNetType()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL GetNetType(LPCTSTR pcszCNRName, PDWORD pdwNetType)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
NETRESOURCE nrIn;
|
|
NETRESOURCEBUF nrbufOut;
|
|
DWORD dwcbBufLen = SIZEOF(nrbufOut);
|
|
LPTSTR pszFileSysPath;
|
|
DWORD dwNetResult;
|
|
#ifdef DEBUG
|
|
DWORD dwcmsTicks;
|
|
#endif
|
|
|
|
ASSERT(IsValidCNRName(pcszCNRName));
|
|
ASSERT(IS_VALID_WRITE_PTR(pdwNetType, DWORD));
|
|
|
|
/* RAIDRAID: (15691) We only support disk resource connections here. */
|
|
|
|
ZeroMemory(&nrIn, SIZEOF(nrIn));
|
|
nrIn.lpRemoteName = (LPTSTR)pcszCNRName;
|
|
nrIn.dwType = RESOURCETYPE_DISK;
|
|
|
|
#ifdef DEBUG
|
|
dwcmsTicks = GetTickCount();
|
|
#endif
|
|
|
|
dwNetResult = WNetGetResourceInformation(&nrIn, &(nrbufOut.rgbyte),
|
|
&dwcbBufLen, &pszFileSysPath);
|
|
|
|
#ifdef DEBUG
|
|
|
|
dwcmsTicks = GetTickCount() - dwcmsTicks;
|
|
|
|
TRACE_OUT((TEXT("GetRemotePathInfo(): WNetGetResourceInformation() on net resource %s took %lu.%03lu seconds."),
|
|
pcszCNRName,
|
|
(dwcmsTicks / 1000),
|
|
(dwcmsTicks % 1000)));
|
|
|
|
#endif
|
|
|
|
if (dwNetResult == ERROR_SUCCESS)
|
|
{
|
|
if (nrbufOut.nr.lpProvider)
|
|
{
|
|
NETINFOSTRUCT nis;
|
|
|
|
ASSERT(IS_VALID_STRING_PTR(nrbufOut.nr.lpProvider, STR));
|
|
|
|
nis.cbStructure = SIZEOF(nis);
|
|
|
|
dwNetResult = WNetGetNetworkInformation(nrbufOut.nr.lpProvider, &nis);
|
|
|
|
if (dwNetResult == ERROR_SUCCESS)
|
|
{
|
|
*pdwNetType = ((nis.wNetType) << 16);
|
|
bResult = TRUE;
|
|
|
|
TRACE_OUT((TEXT("GetNetType(): Net type for CNR %s is %#08lx."),
|
|
pcszCNRName,
|
|
*pdwNetType));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("GetNetType(): WNetGetNetworkInformation() failed for %s NP, returning %lu."),
|
|
nrbufOut.nr.lpProvider,
|
|
dwNetResult));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("GetNetType(): WNetGetResourceInformation() was unable to determine the NP for CNR %s."),
|
|
pcszCNRName));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("GetNetType(): WNetGetResourceInformation() failed for CNR %s, returning %lu."),
|
|
pcszCNRName,
|
|
dwNetResult));
|
|
|
|
ASSERT(! bResult ||
|
|
IsValidNetType(*pdwNetType));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** GetNetProviderName()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL GetNetProviderName(PCICNRLINK pcicnrl, LPTSTR pszNPNameBuf)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pcicnrl, CICNRLINK));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszNPNameBuf, STR, MAX_PATH_LEN));
|
|
|
|
if (IS_FLAG_SET(pcicnrl->dwFlags, ICNRL_FL_VALID_NET_TYPE))
|
|
{
|
|
DWORD dwcbNPNameBufLen;
|
|
DWORD dwNetResult;
|
|
|
|
dwcbNPNameBufLen = MAX_PATH_LEN;
|
|
|
|
dwNetResult = WNetGetProviderName(pcicnrl->dwNetType, pszNPNameBuf,
|
|
&dwcbNPNameBufLen);
|
|
|
|
if (dwNetResult == ERROR_SUCCESS)
|
|
{
|
|
bResult = TRUE;
|
|
|
|
#ifdef UNICODE
|
|
//
|
|
// Unicode builds need to accept both ansi and unicode ICNRLINK structures.
|
|
// Note the use of '%S' (upper case). This will accept an ANSI string
|
|
// in a UNICODE build environment.
|
|
//
|
|
if (IS_ICNRL_ANSI(pcicnrl))
|
|
TRACE_OUT((TEXT("GetNetProviderName(): NP for CNR %S is %s."),
|
|
ICNRL_Remote_Name_PtrA(pcicnrl),
|
|
pszNPNameBuf));
|
|
else
|
|
#endif
|
|
TRACE_OUT((TEXT("GetNetProviderName(): NP for CNR %s is %s."),
|
|
ICNRL_Remote_Name_Ptr(pcicnrl),
|
|
pszNPNameBuf));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("GetNetProviderName(): WNetGetProviderName() failed for CNR %s's net type %#08lx, returning %lu."),
|
|
TEXT("<Remote Name>"), // ICNRL_Remote_Name_Ptr(pcicnrl),
|
|
pcicnrl->dwNetType,
|
|
dwNetResult));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("GetNetProviderName(): Net type for CNR %s is not known. Unable to determine NP name."),
|
|
TEXT("<Remote Name>"))); // ICNRL_Remote_Name_Ptr(pcicnrl)));
|
|
|
|
ASSERT(! bResult ||
|
|
IsValidNetProviderName(pszNPNameBuf));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** CompareNetNames()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE COMPARISONRESULT CompareNetNames(LPCTSTR pcszFirstNetName,
|
|
LPCTSTR pcszSecondNetName)
|
|
{
|
|
ASSERT(IS_VALID_STRING_PTR(pcszFirstNetName, CSTR));
|
|
ASSERT(IS_VALID_STRING_PTR(pcszSecondNetName, CSTR));
|
|
|
|
return(MapIntToComparisonResult(lstrcmp(pcszFirstNetName,
|
|
pcszSecondNetName)));
|
|
}
|
|
|
|
|
|
/*
|
|
** SearchForRedirectedConnection()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL SearchForRedirectedConnection(PCICNRLINK pcicnrl,
|
|
LPTSTR pszRootPathBuf)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
HANDLE henum;
|
|
DWORD dwNetResult;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pcicnrl, CICNRLINK));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRootPathBuf, STR, MAX_PATH_LEN));
|
|
|
|
#ifdef DEBUG
|
|
#ifdef UNICODE
|
|
{
|
|
LPWSTR pszWideNetName;
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
|
|
if (IS_ICNRL_ANSI(pcicnrl))
|
|
{
|
|
pszWideNetName = szWideNetName;
|
|
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA(pcicnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
} else {
|
|
pszWideNetName = ICNRL_Remote_Name_PtrW(pcicnrl);
|
|
}
|
|
|
|
WARNING_OUT((TEXT("SearchForRedirectedConnection(): Enumerating local connections searching for redirected connection to CNR \"%s\"."),
|
|
pszWideNetName));
|
|
}
|
|
#else
|
|
WARNING_OUT((TEXT("SearchForRedirectedConnection(): Enumerating local connections searching for redirected connection to CNR \"%s\"."),
|
|
ICNRL_Remote_Name_Ptr(pcicnrl)));
|
|
#endif
|
|
#endif
|
|
|
|
/* RAIDRAID: (15691) We only support container resources here. */
|
|
|
|
dwNetResult = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_DISK,
|
|
RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED,
|
|
NULL, &henum);
|
|
|
|
if (dwNetResult == WN_SUCCESS)
|
|
{
|
|
DWORD dwc = 1;
|
|
NETRESOURCEBUF nrbuf;
|
|
DWORD dwcbBufLen = SIZEOF(nrbuf);
|
|
|
|
while ((dwNetResult = WNetEnumResource(henum, &dwc, &(nrbuf.rgbyte),
|
|
&dwcbBufLen))
|
|
== WN_SUCCESS)
|
|
{
|
|
/* Is this a redirected connection? */
|
|
|
|
if (nrbuf.nr.lpRemoteName != NULL)
|
|
{
|
|
if (nrbuf.nr.lpLocalName != NULL)
|
|
{
|
|
/* Yes. Is it a redirected connection to the desired CNR? */
|
|
|
|
#ifdef UNICODE
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
LPWSTR pszWideNetName;
|
|
|
|
if (IS_ICNRL_ANSI(pcicnrl))
|
|
{
|
|
pszWideNetName = szWideNetName;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA(pcicnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
}
|
|
else
|
|
{
|
|
pszWideNetName = ICNRL_Remote_Name_Ptr(pcicnrl);
|
|
}
|
|
if (CompareNetNames(pszWideNetName,
|
|
nrbuf.nr.lpRemoteName)
|
|
== CR_EQUAL)
|
|
#else
|
|
if (CompareNetNames(ICNRL_Remote_Name_Ptr(pcicnrl),
|
|
nrbuf.nr.lpRemoteName)
|
|
== CR_EQUAL)
|
|
#endif
|
|
{
|
|
/* Yes. */
|
|
|
|
ASSERT(lstrlen(nrbuf.nr.lpLocalName) < MAX_PATH_LEN);
|
|
|
|
lstrcpy(pszRootPathBuf, nrbuf.nr.lpLocalName);
|
|
bResult = TRUE;
|
|
|
|
TRACE_OUT((TEXT("SearchForRedirectedConnection(): Found CNR \"%s\" connected to %s."),
|
|
nrbuf.nr.lpRemoteName,
|
|
pszRootPathBuf));
|
|
|
|
break;
|
|
}
|
|
else
|
|
/* No. */
|
|
TRACE_OUT((TEXT("SearchForRedirectedConnection(): Skipping unmatched enumerated connection to CNR \"%s\" on %s."),
|
|
nrbuf.nr.lpRemoteName,
|
|
nrbuf.nr.lpLocalName));
|
|
}
|
|
else
|
|
/* No. */
|
|
TRACE_OUT((TEXT("SearchForRedirectedConnection(): Skipping enumerated deviceless connection to CNR \"%s\"."),
|
|
nrbuf.nr.lpRemoteName));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("SearchForRedirectedConnection(): Skipping enumerated connection with no CNR name.")));
|
|
}
|
|
|
|
if (! bResult && dwNetResult != WN_NO_MORE_ENTRIES)
|
|
WARNING_OUT((TEXT("SearchForRedirectedConnection(): WNetEnumResource() failed, returning %lu."),
|
|
dwNetResult));
|
|
|
|
dwNetResult = WNetCloseEnum(henum);
|
|
|
|
if (dwNetResult != WN_SUCCESS)
|
|
WARNING_OUT((TEXT("SearchForRedirectedConnection(): WNetCloseEnum() failed, returning %lu."),
|
|
dwNetResult));
|
|
}
|
|
else
|
|
WARNING_OUT((TEXT("SearchForRedirectedConnection(): WNetOpenEnum() failed, returning %lu."),
|
|
dwNetResult));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
#if defined(DEBUG) || defined (VSTF)
|
|
|
|
/*
|
|
** IsValidDevice()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL IsValidDevice(LPCTSTR pcszDevice)
|
|
{
|
|
/* Any valid string < MAX_PATH_LEN bytes long is a valid device name. */
|
|
|
|
return(IS_VALID_STRING_PTR(pcszDevice, CSTR) &&
|
|
EVAL(lstrlen(pcszDevice) < MAX_PATH_LEN));
|
|
}
|
|
|
|
|
|
/*
|
|
** IsValidNetType()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL IsValidNetType(DWORD dwNetType)
|
|
{
|
|
BOOL bResult;
|
|
|
|
switch (dwNetType & 0xffff0000)
|
|
{
|
|
default:
|
|
WARNING_OUT((TEXT("IsValidNetType(): Unexpected net type %#08lx is neither NetWare nor LANMan."),
|
|
dwNetType));
|
|
/* Fall through... */
|
|
|
|
case WNNC_NET_LANMAN:
|
|
case WNNC_NET_NETWARE:
|
|
bResult = TRUE;
|
|
break;
|
|
|
|
}
|
|
|
|
if (dwNetType & 0x0000ffff)
|
|
WARNING_OUT((TEXT("IsValidNetType(): Low word of net type %#08lx is non-zero."),
|
|
dwNetType));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** IsValidPCICNRLINK()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL IsValidPCICNRLINK(PCICNRLINK pcicnrl)
|
|
{
|
|
BOOL bResult;
|
|
|
|
if (IS_VALID_READ_PTR(pcicnrl, CICNRLINK) &&
|
|
IS_VALID_READ_BUFFER_PTR(pcicnrl, CICNRLINK, pcicnrl->ucbSize) &&
|
|
FLAGS_ARE_VALID(pcicnrl->dwFlags, ALL_ICNRL_FLAGS) &&
|
|
EVAL(IsValidCNRName(ICNRL_Remote_Name_Ptr(pcicnrl))) &&
|
|
EVAL(IsContained(pcicnrl, pcicnrl->ucbSize,
|
|
ICNRL_Remote_Name_PtrA(pcicnrl),
|
|
lstrlenA(ICNRL_Remote_Name_PtrA(pcicnrl)))) &&
|
|
(IS_FLAG_CLEAR(pcicnrl->dwFlags, ICNRL_FL_VALID_NET_TYPE) ||
|
|
EVAL(IsValidNetType(pcicnrl->dwNetType))))
|
|
{
|
|
if (IS_FLAG_CLEAR(pcicnrl->dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
{
|
|
ASSERT(! pcicnrl->ucbDeviceOffset);
|
|
bResult = TRUE;
|
|
}
|
|
else
|
|
bResult = (EVAL(IsValidDevice(ICNRL_Device_Ptr(pcicnrl))) &&
|
|
EVAL(IsContained(pcicnrl, pcicnrl->ucbSize,
|
|
ICNRL_Device_PtrA(pcicnrl),
|
|
lstrlenA(ICNRL_Device_PtrA(pcicnrl)))));
|
|
}
|
|
else
|
|
bResult = FALSE;
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#if defined(DEBUG)
|
|
|
|
/*
|
|
** IsValidNetProviderName()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PRIVATE_CODE BOOL IsValidNetProviderName(LPCTSTR pcszNetProvider)
|
|
{
|
|
/* Any string < MAX_PATH_LEN characters long is a valid NP name. */
|
|
|
|
return(IS_VALID_STRING_PTR(pcszNetProvider, CSTR) &&
|
|
lstrlen(pcszNetProvider) < MAX_PATH_LEN);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/****************************** Public Functions *****************************/
|
|
|
|
|
|
/*
|
|
** CreateLocalCNRLink()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
**
|
|
** If TRUE is returned:
|
|
** 1) *ppcnrl is only valid if *pucbCNRLinkLen > 0.
|
|
** 2) pszLocalBasePathBuf is valid.
|
|
** 3) *ppcszCommonPathSuffix is valid.
|
|
**
|
|
** If *pucbCNRLinkLen == 0, pszLocalBasePathBuf is a copy of pcszLocalPath, and
|
|
** *ppcszCommonPathSuffix points at the null terminator of pcszLocalPath.
|
|
**
|
|
** If *pucbCNRLinkLen > 0, pszLocalBasePathBuf is the closest shared local base
|
|
** path, and *ppcszCommonPathSuffix points at that path's suffix in
|
|
** pcszLocalPath.
|
|
*/
|
|
PUBLIC_CODE BOOL CreateLocalCNRLink(LPCTSTR pcszLocalPath, PCNRLINK *ppcnrl,
|
|
PUINT pucbCNRLinkLen,
|
|
LPTSTR pszLocalBasePathBuf,
|
|
LPCTSTR *ppcszCommonPathSuffix)
|
|
{
|
|
BOOL bResult;
|
|
TCHAR rgchNetName[MAX_PATH_LEN];
|
|
BOOL bShared;
|
|
DWORD dwNetType;
|
|
|
|
ASSERT(IsDrivePath(pcszLocalPath));
|
|
ASSERT(IS_VALID_WRITE_PTR(ppcnrl, PCNRLINK));
|
|
ASSERT(IS_VALID_WRITE_PTR(pucbCNRLinkLen, UINT));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszLocalBasePathBuf, STR, MAX_PATH_LEN));
|
|
ASSERT(IS_VALID_WRITE_PTR(ppcszCommonPathSuffix, LPCTSTR));
|
|
|
|
bResult = GetNetPathFromLocalPath(pcszLocalPath, rgchNetName,
|
|
ppcszCommonPathSuffix, &bShared,
|
|
&dwNetType);
|
|
|
|
if (bResult)
|
|
{
|
|
if (bShared)
|
|
{
|
|
bResult = UnifyICNRLinkInfo(rgchNetName, ICNRL_FL_VALID_NET_TYPE,
|
|
NULL, dwNetType, (PICNRLINK *)ppcnrl,
|
|
pucbCNRLinkLen);
|
|
|
|
if (bResult)
|
|
{
|
|
UINT ucbLocalBasePathLen;
|
|
|
|
/* Copy local base path into output buffer. */
|
|
|
|
ASSERT(*ppcszCommonPathSuffix >= pcszLocalPath);
|
|
ucbLocalBasePathLen = (UINT)(*ppcszCommonPathSuffix - pcszLocalPath);
|
|
|
|
CopyMemory(pszLocalBasePathBuf, pcszLocalPath, ucbLocalBasePathLen * sizeof(TCHAR));
|
|
pszLocalBasePathBuf[ucbLocalBasePathLen] = TEXT('\0');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Not shared. No CNRLink. */
|
|
|
|
*pucbCNRLinkLen = 0;
|
|
|
|
/* Copy entire local path into output buffer. */
|
|
|
|
lstrcpy(pszLocalBasePathBuf, pcszLocalPath);
|
|
|
|
/* Common path suffix is the empty string. */
|
|
|
|
*ppcszCommonPathSuffix = pcszLocalPath + lstrlen(pcszLocalPath);
|
|
}
|
|
}
|
|
|
|
ASSERT(! bResult ||
|
|
(EVAL(IsDrivePath(pszLocalBasePathBuf)) &&
|
|
IS_VALID_STRING_PTR(*ppcszCommonPathSuffix, CSTR) &&
|
|
EVAL(IsStringContained(pcszLocalPath, *ppcszCommonPathSuffix)) &&
|
|
(! *pucbCNRLinkLen ||
|
|
(IS_VALID_STRUCT_PTR((PCICNRLINK)*ppcnrl, CICNRLINK) &&
|
|
EVAL(*pucbCNRLinkLen == GetCNRLinkLen(*ppcnrl))))));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** CreateRemoteCNRLink()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL CreateRemoteCNRLink(LPCTSTR pcszRemotePath, LPCTSTR pcszCNRName,
|
|
PCNRLINK *ppcnrl, PUINT pucbCNRLinkLen)
|
|
{
|
|
BOOL bResult;
|
|
/* "D:" + null terminator. */
|
|
TCHAR rgchDrive[3];
|
|
DWORD dwNetType;
|
|
|
|
ASSERT(IsCanonicalPath(pcszRemotePath));
|
|
ASSERT(IsValidCNRName(pcszCNRName));
|
|
ASSERT(IS_VALID_WRITE_PTR(ppcnrl, PCNRLINK));
|
|
ASSERT(IS_VALID_WRITE_PTR(pucbCNRLinkLen, UINT));
|
|
|
|
/* Determine net provider. */
|
|
|
|
bResult = GetNetType(pcszCNRName, &dwNetType);
|
|
|
|
if (bResult)
|
|
{
|
|
DWORD dwFlags = ICNRL_FL_VALID_NET_TYPE;
|
|
|
|
/* Determine last redirected drive, if any. */
|
|
|
|
if (IsDrivePath(pcszRemotePath))
|
|
{
|
|
MyLStrCpyN(rgchDrive, pcszRemotePath, ARRAYSIZE(rgchDrive));
|
|
SET_FLAG(dwFlags, ICNRL_FL_VALID_DEVICE);
|
|
}
|
|
else
|
|
rgchDrive[0] = TEXT('\0');
|
|
|
|
bResult = UnifyICNRLinkInfo(pcszCNRName, dwFlags, rgchDrive, dwNetType,
|
|
(PICNRLINK *)ppcnrl, pucbCNRLinkLen);
|
|
}
|
|
|
|
ASSERT(! bResult ||
|
|
(IS_VALID_STRUCT_PTR((PCICNRLINK)*ppcnrl, CICNRLINK) &&
|
|
EVAL(*pucbCNRLinkLen == GetCNRLinkLen(*ppcnrl))));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** DestroyCNRLink()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE void DestroyCNRLink(PCNRLINK pcnrl)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pcnrl, CCNRLINK));
|
|
|
|
FreeMemory(pcnrl);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
** CompareCNRLinks()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
**
|
|
** CNR link data is compared in the following order:
|
|
**
|
|
** 1) net name
|
|
**
|
|
** N.b., net types are ignored when comparing CNRLinks.
|
|
*/
|
|
PUBLIC_CODE COMPARISONRESULT CompareCNRLinks(PCCNRLINK pccnrlFirst,
|
|
PCCNRLINK pccnrlSecond)
|
|
{
|
|
#ifdef UNICODE
|
|
WCHAR szWideNetNameFirst[MAX_PATH];
|
|
LPWSTR pszWideNetNameFirst;
|
|
WCHAR szWideNetNameSecond[MAX_PATH];
|
|
LPWSTR pszWideNetNameSecond;
|
|
#endif
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrlFirst, CCNRLINK));
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrlSecond, CCNRLINK));
|
|
|
|
#ifdef UNICODE
|
|
if (IS_ICNRL_ANSI(pccnrlFirst))
|
|
{
|
|
pszWideNetNameFirst = szWideNetNameFirst;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrlFirst), -1,
|
|
szWideNetNameFirst, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszWideNetNameFirst = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrlFirst);
|
|
}
|
|
|
|
if (IS_ICNRL_ANSI(pccnrlSecond))
|
|
{
|
|
pszWideNetNameSecond = szWideNetNameSecond;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrlSecond), -1,
|
|
szWideNetNameSecond, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszWideNetNameSecond = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrlSecond);
|
|
}
|
|
|
|
return(CompareNetNames(pszWideNetNameFirst,pszWideNetNameSecond));
|
|
#else
|
|
return(CompareNetNames(ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrlFirst),
|
|
ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrlSecond)));
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
** GetLocalPathFromCNRLink()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL GetLocalPathFromCNRLink(PCCNRLINK pccnrl,
|
|
LPTSTR pszLocalPathBuf,
|
|
PDWORD pdwOutFlags)
|
|
{
|
|
BOOL bResult;
|
|
PCSERVERVTABLE pcsvt;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszLocalPathBuf, STR, MAX_PATH_LEN));
|
|
ASSERT(IS_VALID_WRITE_PTR(pdwOutFlags, DWORD));
|
|
|
|
*pdwOutFlags = 0;
|
|
|
|
bResult = GetServerVTable(&pcsvt);
|
|
|
|
if (bResult)
|
|
{
|
|
DWORD dwNetType;
|
|
BOOL bIsLocal;
|
|
|
|
/*
|
|
* Get local path for share. N.b., the share name must be in upper case
|
|
* here for MSSHRUI.DLL.
|
|
*/
|
|
|
|
dwNetType = (IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags,
|
|
ICNRL_FL_VALID_NET_TYPE) ?
|
|
((PCICNRLINK)pccnrl)->dwNetType :
|
|
0);
|
|
|
|
#ifdef UNICODE
|
|
{
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
LPWSTR pszWideNetName = szWideNetName;
|
|
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
{
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszWideNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
}
|
|
bResult = (pcsvt->GetLocalPathFromNetResource)(
|
|
pszWideNetName, dwNetType,
|
|
pszLocalPathBuf, MAX_PATH_LEN, &bIsLocal);
|
|
}
|
|
#else
|
|
bResult = (pcsvt->GetLocalPathFromNetResource)(
|
|
ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl), dwNetType,
|
|
pszLocalPathBuf, MAX_PATH_LEN, &bIsLocal);
|
|
#endif
|
|
|
|
if (bIsLocal)
|
|
SET_FLAG(*pdwOutFlags, CNR_FL_LOCAL);
|
|
}
|
|
|
|
ASSERT(FLAGS_ARE_VALID(*pdwOutFlags, ALL_CNR_FLAGS) &&
|
|
(! bResult ||
|
|
(EVAL(IS_FLAG_SET(*pdwOutFlags, CNR_FL_LOCAL)) &&
|
|
EVAL(IsLocalDrivePath(pszLocalPathBuf)))));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** GetRemotePathFromCNRLink()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE void GetRemotePathFromCNRLink(PCCNRLINK pccnrl,
|
|
LPTSTR pszRemotePathBuf)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRemotePathBuf, STR, MAX_PATH_LEN));
|
|
|
|
/* It's ok that this is broken for non-UNC CNR names. */
|
|
|
|
/* (- 1) for trailing slash. */
|
|
|
|
#ifdef UNICODE
|
|
ASSERT(IS_ICNRL_ANSI(pccnrl) ? (lstrlenA(ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl)) < MAX_PATH_LEN - 1) :
|
|
(lstrlenW(ICNRL_Remote_Name_PtrW((PCICNRLINK)pccnrl)) < MAX_PATH_LEN - 1));
|
|
#else
|
|
ASSERT(lstrlenA(ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl)) < MAX_PATH_LEN - 1);
|
|
#endif
|
|
|
|
#ifdef UNICODE
|
|
{
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
LPWSTR pszWideNetName;
|
|
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
{
|
|
pszWideNetName = szWideNetName;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszWideNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
}
|
|
lstrcpy(pszRemotePathBuf, pszWideNetName);
|
|
}
|
|
#else
|
|
lstrcpy(pszRemotePathBuf, ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl));
|
|
#endif
|
|
CatPath(pszRemotePathBuf, TEXT("\\"));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
** ConnectToCNR()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL ConnectToCNR(PCCNRLINK pccnrl, DWORD dwInFlags,
|
|
HWND hwndOwner, LPTSTR pszRootPathBuf,
|
|
PDWORD pdwOutFlags)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
BOOL bValidDevice;
|
|
BOOL bRedirect;
|
|
BOOL bTryLastDevice = FALSE;
|
|
DWORD dwcbRootPathBufLen;
|
|
LPTSTR pszNetName;
|
|
LPTSTR pszDevice;
|
|
#ifdef UNICODE
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
WCHAR szWideDevice[MAX_PATH];
|
|
#endif
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_CONNECT_IN_FLAGS));
|
|
ASSERT(IS_FLAG_CLEAR(dwInFlags, CONNECT_INTERACTIVE) ||
|
|
IS_VALID_HANDLE(hwndOwner, WND));
|
|
ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRootPathBuf, STR, MAX_PATH_LEN));
|
|
ASSERT(IS_VALID_WRITE_PTR(pdwOutFlags, DWORD));
|
|
|
|
*pdwOutFlags = 0;
|
|
|
|
#ifdef UNICODE
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
{
|
|
pszNetName = szWideNetName;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
}
|
|
#else
|
|
pszNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
#endif
|
|
|
|
/* Do we have an old redirected device to try? */
|
|
|
|
bValidDevice = IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags,
|
|
ICNRL_FL_VALID_DEVICE);
|
|
|
|
#ifdef UNICODE
|
|
if ( bValidDevice )
|
|
{
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
{
|
|
pszDevice = szWideDevice;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Device_PtrA((PCICNRLINK)pccnrl), -1,
|
|
szWideDevice, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszDevice = ICNRL_Device_Ptr((PCICNRLINK)pccnrl);
|
|
}
|
|
}
|
|
#else
|
|
pszDevice = ICNRL_Device_Ptr((PCICNRLINK)pccnrl);
|
|
#endif
|
|
|
|
bRedirect = (bValidDevice || IS_FLAG_SET(dwInFlags, CONNECT_REDIRECT));
|
|
|
|
if (bRedirect)
|
|
{
|
|
if (bValidDevice)
|
|
{
|
|
DWORD dwNetResult;
|
|
/* "X:" + null terminator */
|
|
TCHAR rgchDrive[2 + 1];
|
|
|
|
/* Yes. Is it already connected to the desired CNR? */
|
|
|
|
TRACE_OUT((TEXT("ConnectToCNR(): Calling WNetGetConnection() to check %s for CNR \"%s\"."),
|
|
pszDevice, pszNetName));
|
|
|
|
dwcbRootPathBufLen = MAX_PATH_LEN;
|
|
|
|
/* WNetGetConnection requires the device name to have no trailing
|
|
** backslash.
|
|
*/
|
|
MyLStrCpyN(rgchDrive, pszDevice, ARRAYSIZE(rgchDrive));
|
|
dwNetResult = WNetGetConnection(rgchDrive, pszRootPathBuf, &dwcbRootPathBufLen);
|
|
|
|
if (dwNetResult == WN_SUCCESS)
|
|
{
|
|
if (CompareNetNames(pszNetName, pszRootPathBuf)
|
|
== CR_EQUAL)
|
|
{
|
|
TRACE_OUT((TEXT("ConnectToCNR(): Found matching CNR \"%s\" on %s."),
|
|
pszRootPathBuf,
|
|
pszDevice));
|
|
|
|
ASSERT(lstrlenA(ICNRL_Device_PtrA((PCICNRLINK)pccnrl)) < MAX_PATH_LEN);
|
|
lstrcpy(pszRootPathBuf, pszDevice);
|
|
|
|
bResult = TRUE;
|
|
}
|
|
else
|
|
TRACE_OUT((TEXT("ConnectToCNR(): Found unmatched CNR \"%s\" on %s."),
|
|
pszRootPathBuf,
|
|
pszDevice));
|
|
}
|
|
else
|
|
{
|
|
TRACE_OUT((TEXT("ConnectToCNR(): WNetGetConnection() failed on %s."),
|
|
pszDevice));
|
|
|
|
/*
|
|
* Only attempt a connection to the last redirected device if that
|
|
* device is not already in use.
|
|
*/
|
|
|
|
bTryLastDevice = (GetDriveType(pszDevice)
|
|
== DRIVE_NO_ROOT_DIR);
|
|
}
|
|
}
|
|
|
|
if (! bResult)
|
|
/* See if the desired CNR is connected to any local device. */
|
|
bResult = SearchForRedirectedConnection((PCICNRLINK)pccnrl,
|
|
pszRootPathBuf);
|
|
/*
|
|
* Assume that no reference count is maintained for redirected device
|
|
* connections, so we do not have to add a found redirected device
|
|
* connection again.
|
|
*/
|
|
}
|
|
|
|
if (! bResult)
|
|
{
|
|
NETRESOURCE nr;
|
|
TCHAR rgchNPName[MAX_PATH_LEN];
|
|
|
|
/* RAIDRAID: (15691) We only support disk resource connections here. */
|
|
|
|
ZeroMemory(&nr, SIZEOF(nr));
|
|
nr.lpRemoteName = pszNetName;
|
|
nr.dwType = RESOURCETYPE_DISK;
|
|
if (GetNetProviderName((PCICNRLINK)pccnrl, rgchNPName))
|
|
nr.lpProvider = rgchNPName;
|
|
|
|
/* Shall we try the old device? */
|
|
|
|
if (bTryLastDevice)
|
|
{
|
|
/* Yes. */
|
|
|
|
ASSERT(bValidDevice);
|
|
|
|
nr.lpLocalName = pszDevice;
|
|
|
|
WARNING_OUT((TEXT("ConnectToCNR(): Calling WNetUseConnection() to attempt to connect %s to CNR \"%s\"."),
|
|
nr.lpLocalName,
|
|
nr.lpRemoteName));
|
|
}
|
|
else
|
|
{
|
|
/* No. Shall we attempt to force a redirected connection? */
|
|
|
|
if (bValidDevice)
|
|
{
|
|
/*
|
|
* Yes. N.b., the caller may already have set CONNECT_REDIRECT in
|
|
* dwInFlags here.
|
|
*/
|
|
|
|
SET_FLAG(dwInFlags, CONNECT_REDIRECT);
|
|
|
|
WARNING_OUT((TEXT("ConnectToCNR(): Calling WNetUseConnection() to establish auto-picked redirected connection to CNR \"%s\"."),
|
|
nr.lpRemoteName));
|
|
}
|
|
else
|
|
/* No. */
|
|
WARNING_OUT((TEXT("ConnectToCNR(): Calling WNetUseConnection() to establish connection to CNR \"%s\"."),
|
|
TEXT("<nr.lpRemoteName>"))); // nr.lpRemoteName));
|
|
|
|
ASSERT(! nr.lpLocalName);
|
|
}
|
|
|
|
dwcbRootPathBufLen = MAX_PATH_LEN;
|
|
|
|
bResult = (WNetUseConnection(hwndOwner, &nr, NULL, NULL, dwInFlags,
|
|
pszRootPathBuf, &dwcbRootPathBufLen,
|
|
pdwOutFlags)
|
|
== NO_ERROR);
|
|
}
|
|
|
|
if (bResult)
|
|
CatPath(pszRootPathBuf, TEXT("\\"));
|
|
|
|
ASSERT(! bResult ||
|
|
(IS_VALID_STRING_PTR(pszRootPathBuf, STR) &&
|
|
FLAGS_ARE_VALID(*pdwOutFlags, ALL_CONNECT_OUT_FLAGS)));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** DisconnectFromCNR()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL DisconnectFromCNR(PCCNRLINK pccnrl)
|
|
{
|
|
DWORD dwNetResult;
|
|
LPTSTR pszNetName;
|
|
#ifdef UNICODE
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
#endif
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
#ifdef UNICODE
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
{
|
|
pszNetName = szWideNetName;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
}
|
|
#else
|
|
pszNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
#endif
|
|
|
|
dwNetResult = WNetCancelConnection2(pszNetName,
|
|
CONNECT_REFCOUNT, FALSE);
|
|
|
|
if (dwNetResult == NO_ERROR)
|
|
WARNING_OUT((TEXT("DisconnectFromCNR(): Reduced connection reference count on CNR \"%s\"."),
|
|
pszNetName));
|
|
else
|
|
WARNING_OUT((TEXT("DisconnectFromCNR(): Failed to reduce connection reference count on CNR \"%s\". WNetCancelConnection2() returned %lu."),
|
|
pszNetName));
|
|
|
|
return(dwNetResult == NO_ERROR);
|
|
}
|
|
|
|
|
|
/*
|
|
** IsCNRAvailable()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL IsCNRAvailable(PCCNRLINK pccnrl)
|
|
{
|
|
TCHAR rgchCNRRoot[MAX_PATH_LEN];
|
|
LPTSTR pszNetName;
|
|
#ifdef UNICODE
|
|
WCHAR szWideNetName[MAX_PATH];
|
|
#endif
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
#ifdef UNICODE
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
{
|
|
pszNetName = szWideNetName;
|
|
MultiByteToWideChar(CP_ACP, 0,
|
|
ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl), -1,
|
|
szWideNetName, MAX_PATH);
|
|
|
|
}
|
|
else
|
|
{
|
|
pszNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
}
|
|
#else
|
|
pszNetName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
#endif
|
|
|
|
ASSERT(lstrlen(pszNetName) < ARRAYSIZE(rgchCNRRoot) - 1);
|
|
lstrcpy(rgchCNRRoot, pszNetName);
|
|
CatPath(rgchCNRRoot, TEXT("\\"));
|
|
|
|
return(PathExists(rgchCNRRoot));
|
|
}
|
|
|
|
|
|
/*
|
|
** GetCNRLinkLen()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE UINT GetCNRLinkLen(PCCNRLINK pccnrl)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
return(((PCICNRLINK)pccnrl)->ucbSize);
|
|
}
|
|
|
|
|
|
/*
|
|
** GetCNRNetType()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL GetCNRNetType(PCCNRLINK pccnrl, PCDWORD *ppcdwNetType)
|
|
{
|
|
BOOL bResult;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
bResult = IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags,
|
|
ICNRL_FL_VALID_NET_TYPE);
|
|
|
|
if (bResult)
|
|
*ppcdwNetType = &(((PCICNRLINK)pccnrl)->dwNetType);
|
|
|
|
ASSERT(! bResult ||
|
|
IsValidNetType(**ppcdwNetType));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*
|
|
** GetCNRName()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL GetCNRName(PCCNRLINK pccnrl, LPCSTR *ppcszCNRName)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
*ppcszCNRName = ICNRL_Remote_Name_PtrA((PCICNRLINK)pccnrl);
|
|
|
|
ASSERT(IS_VALID_STRING_PTRA(*ppcszCNRName, CSTR));
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
/*
|
|
** GetCNRNameW()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL GetCNRNameW(PCCNRLINK pccnrl, LPCWSTR *ppcszCNRName)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
*ppcszCNRName = NULL;
|
|
else
|
|
{
|
|
*ppcszCNRName = ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl);
|
|
ASSERT(IS_VALID_STRING_PTR(*ppcszCNRName, CSTR));
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** GetLastRedirectedDevice()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL GetLastRedirectedDevice(PCCNRLINK pccnrl, LPCSTR *ppcszDevice)
|
|
{
|
|
BOOL bResult;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
bResult = IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags, ICNRL_FL_VALID_DEVICE);
|
|
|
|
if (bResult)
|
|
*ppcszDevice = ICNRL_Device_PtrA((PCICNRLINK)pccnrl);
|
|
|
|
ASSERT(! bResult ||
|
|
IS_VALID_STRING_PTRA(*ppcszDevice, CSTR));
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
/*
|
|
** GetLastRedirectedDeviceW()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL GetLastRedirectedDeviceW(PCCNRLINK pccnrl, LPCWSTR *ppcszDevice)
|
|
{
|
|
BOOL bResult;
|
|
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
bResult = IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags, ICNRL_FL_VALID_DEVICE);
|
|
|
|
if (bResult)
|
|
if (IS_ICNRL_ANSI(pccnrl))
|
|
*ppcszDevice = NULL;
|
|
else
|
|
{
|
|
*ppcszDevice = ICNRL_Device_Ptr((PCICNRLINK)pccnrl);
|
|
ASSERT(! bResult ||
|
|
IS_VALID_STRING_PTR(*ppcszDevice, CSTR));
|
|
}
|
|
|
|
return(bResult);
|
|
}
|
|
#endif
|
|
|
|
#if defined(DEBUG) || defined (VSTF)
|
|
|
|
/*
|
|
** IsValidPCCNRLINK()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE BOOL IsValidPCCNRLINK(PCCNRLINK pccnrl)
|
|
{
|
|
return(IS_VALID_STRUCT_PTR((PCICNRLINK)pccnrl, CICNRLINK));
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
/*
|
|
** DumpCNRLink()
|
|
**
|
|
**
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Side Effects: none
|
|
*/
|
|
PUBLIC_CODE void DumpCNRLink(PCCNRLINK pccnrl)
|
|
{
|
|
ASSERT(IS_VALID_STRUCT_PTR(pccnrl, CCNRLINK));
|
|
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] ucbSize %#x"),
|
|
INDENT_STRING,
|
|
INDENT_STRING,
|
|
((PCICNRLINK)pccnrl)->ucbSize));
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] dwFLags = %#08lx"),
|
|
INDENT_STRING,
|
|
INDENT_STRING,
|
|
((PCICNRLINK)pccnrl)->dwFlags));
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] CNR name \"%s\""),
|
|
INDENT_STRING,
|
|
INDENT_STRING,
|
|
ICNRL_Remote_Name_Ptr((PCICNRLINK)pccnrl)));
|
|
if (IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags, ICNRL_FL_VALID_NET_TYPE))
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] net type %#08lx"),
|
|
INDENT_STRING,
|
|
INDENT_STRING,
|
|
((PCICNRLINK)pccnrl)->dwNetType));
|
|
else
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] net type unknown"),
|
|
INDENT_STRING,
|
|
INDENT_STRING));
|
|
if (IS_FLAG_SET(((PCICNRLINK)pccnrl)->dwFlags, ICNRL_FL_VALID_DEVICE))
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] last redirected local device \"%s\""),
|
|
INDENT_STRING,
|
|
INDENT_STRING,
|
|
ICNRL_Device_Ptr((PCICNRLINK)pccnrl)));
|
|
else
|
|
PLAIN_TRACE_OUT((TEXT("%s%s[CNR link] no last redirected local device"),
|
|
INDENT_STRING,
|
|
INDENT_STRING));
|
|
|
|
return;
|
|
}
|
|
|
|
#endif
|