|
|
/*
* 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
|