windows-nt/Source/XPSP1/NT/admin/snapin/filemgmt/smb.cpp
2020-09-26 16:20:57 +08:00

2230 lines
58 KiB
C++

// smb.cpp : SMB shares, sessions and open resources
#include "stdafx.h"
#include "cmponent.h"
#include "safetemp.h"
#include "FileSvc.h"
#include "DynamLnk.h" // DynamicDLL
#include "smb.h"
#include "ShrPgSMB.h" // Share Properties Pages
#include "permpage.h" // CSecurityInformation
#include "compdata.h"
#include "shrpub.h"
#include <activeds.h>
#include <dsrole.h>
#include <dsgetdc.h>
#include <lmwksta.h>
#include <winsock2.h>
#define DONT_WANT_SHELLDEBUG
#include "shlobjp.h" // LPITEMIDLIST
#include "wraps.h" // Wrap_ILCreateFromPath
#include "macros.h"
USE_HANDLE_MACROS("FILEMGMT(smb.cpp)")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// no Publish page for these system shares
//
LPCTSTR g_pszSystemShares[] = { _T("SYSVOL"), _T("NETLOGON"), _T("DEBUG") };
class CSMBSecurityInformation : public CShareSecurityInformation
{
STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation,
PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
BOOL fDefault );
STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor );
public:
SHARE_INFO_502* m_pvolumeinfo;
PSECURITY_DESCRIPTOR m_pDefaultDescriptor;
CSMBSecurityInformation();
~CSMBSecurityInformation();
};
typedef enum _SmbApiIndex
{
SMB_SHARE_ENUM = 0,
SMB_SESSION_ENUM,
SMB_FILE_ENUM,
SMB_API_BUFFER_FREE,
SMB_SHARE_DEL,
SMB_SESSION_DEL,
SMB_FILE_CLOSE,
SMB_SHARE_GET_INFO,
SMB_SHARE_SET_INFO
};
// not subject to localization
static LPCSTR g_apchFunctionNames[] = {
"NetShareEnum",
"NetSessionEnum",
"NetFileEnum",
"NetApiBufferFree",
"NetShareDel",
"NetSessionDel",
"NetFileClose",
"NetShareGetInfo",
"NetShareSetInfo",
NULL
};
// not subject to localization
DynamicDLL g_SmbDLL( _T("NETAPI32.DLL"), g_apchFunctionNames );
typedef DWORD (*APIBUFFERFREEPROC) (LPVOID);
VOID SMBFreeData(PVOID* ppv)
{
if (*ppv != NULL)
{
ASSERT( NULL != g_SmbDLL[SMB_API_BUFFER_FREE] );
(void) ((APIBUFFERFREEPROC)g_SmbDLL[SMB_API_BUFFER_FREE])( *ppv );
*ppv = NULL;
}
}
SmbFileServiceProvider::SmbFileServiceProvider( CFileMgmtComponentData* pFileMgmtData )
// not subject to localization
: FileServiceProvider( pFileMgmtData )
{
VERIFY( m_strTransportSMB.LoadString( IDS_TRANSPORT_SMB ) );
}
/*
NET_API_STATUS NET_API_FUNCTION
NetShareEnum (
IN LPTSTR servername,
IN DWORD level,
OUT LPBYTE *bufptr,
IN DWORD prefmaxlen,
OUT LPDWORD entriesread,
OUT LPDWORD totalentries,
IN OUT LPDWORD resume_handle
);
*/
typedef DWORD (*SHAREENUMPROC) (LPTSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
HRESULT SmbFileServiceProvider::PopulateShares(
IResultData* pResultData,
CFileMgmtCookie* pcookie)
{
TEST_NONNULL_PTR_PARAM(pcookie);
if ( !g_SmbDLL.LoadFunctionPointers() )
{
ASSERT(FALSE); // NETAPI32 isn't installed?
return S_OK;
}
SHARE_INFO_2* psi2 = NULL;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD hEnumHandle = 0;
NET_API_STATUS retval = NERR_Success;
do {
retval = ((SHAREENUMPROC)g_SmbDLL[SMB_SHARE_ENUM])(
const_cast<LPTSTR>(pcookie->QueryTargetServer()),
2,
(PBYTE*)&psi2,
(DWORD)-1L,
&dwEntriesRead,
&dwTotalEntries,
&hEnumHandle );
if (NERR_Success == retval)
{
AddSMBShareItems( pResultData, pcookie, psi2, dwEntriesRead );
psi2 = NULL;
break;
} else if (ERROR_MORE_DATA == retval) {
ASSERT( NULL != hEnumHandle );
AddSMBShareItems( pResultData, pcookie, psi2, dwEntriesRead );
psi2 = NULL;
continue;
/*
} else if (RPC_S_SERVER_UNAVAILABLE == retval && 0 == hEnumHandle) {
// SMB just isn't installed, don't worry about it
break;
*/
} else {
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, retval, IDS_POPUP_SMB_SHARES, pcookie->QueryNonNULLMachineName() );
break;
}
} while (TRUE);
return HRESULT_FROM_WIN32(retval);
}
//
// skip sharenames that contain leading/trailing spaces
//
BOOL IsInvalidSharename(LPCTSTR psz)
{
return (!psz || !*psz || _istspace(psz[0]) || _istspace(psz[lstrlen(psz) - 1]));
}
/*
typedef struct _SHARE_INFO_2 {
LPTSTR shi2_netname;
DWORD shi2_type;
LPTSTR shi2_remark;
DWORD shi2_permissions;
DWORD shi2_max_uses;
DWORD shi2_current_uses;
LPTSTR shi2_path;
LPTSTR shi2_passwd;
} SHARE_INFO_2, *PSHARE_INFO_2, *LPSHARE_INFO_2;
*/
HRESULT SmbFileServiceProvider::AddSMBShareItems(
IResultData* pResultData,
CFileMgmtCookie* pParentCookie,
PVOID pinfo,
DWORD nItems)
{
TEST_NONNULL_PTR_PARAM(pParentCookie);
TEST_NONNULL_PTR_PARAM(pinfo);
if (0 >= nItems)
return S_OK;
RESULTDATAITEM tRDItem;
::ZeroMemory( &tRDItem, sizeof(tRDItem) );
// CODEWORK should use MMC_ICON_CALLBACK
tRDItem.nImage = iIconSMBShare;
tRDItem.nCol = COLNUM_SHARES_SHARED_FOLDER;
tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
tRDItem.str = MMC_CALLBACK;
SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pinfo;
DWORD nItemsToAdd = 0;
for (DWORD i = 0; i < nItems; i++ )
{
switch ((psi2[i]).shi2_type)
{
case STYPE_PRINTQ: // Do not show print shares
case STYPE_DEVICE: // Do not show device shares
break;
default:
if (!IsInvalidSharename(psi2[i].shi2_netname))
nItemsToAdd++;
break;
}
}
CSmbShareCookie* pcookiearray = new CSmbShareCookie[nItemsToAdd];
CSmbCookieBlock* pCookieBlock = new CSmbCookieBlock(
pcookiearray,
nItemsToAdd,
pParentCookie->QueryNonNULLMachineName(),
pinfo );
pParentCookie->m_listResultCookieBlocks.AddHead( pCookieBlock );
CString str;
for ( ; nItems > 0; nItems--, psi2++ )
{
switch (psi2->shi2_type)
{
case STYPE_PRINTQ: // Do not show print shares
case STYPE_DEVICE: // Do not show device shares
continue;
default:
if (!IsInvalidSharename(psi2->shi2_netname))
{
pcookiearray->m_pobject = psi2;
// WARNING cookie cast
tRDItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pcookiearray);
HRESULT hr = pResultData->InsertItem(&tRDItem);
ASSERT(SUCCEEDED(hr));
pcookiearray++;
}
break;
}
}
ASSERT( pcookiearray ==
((CSmbShareCookie*)(pCookieBlock->QueryBaseCookie(0)))+nItemsToAdd );
return S_OK;
}
/*
NET_API_STATUS NET_API_FUNCTION
NetSessionEnum (
IN LPTSTR servername OPTIONAL,
IN LPTSTR UncClientName OPTIONAL,
IN LPTSTR username OPTIONAL,
IN DWORD level,
OUT LPBYTE *bufptr,
IN DWORD prefmaxlen,
OUT LPDWORD entriesread,
OUT LPDWORD totalentries,
IN OUT LPDWORD resume_handle OPTIONAL
);
*/
typedef DWORD (*SESSIONENUMPROC) (LPTSTR,LPTSTR,LPTSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
// if pResultData is not NULL, add sessions/resources to the listbox
// if pResultData is NULL, delete all sessions/resources
// if pResultData is NULL, return SUCCEEDED(hr) to continue or
// FAILED(hr) to abort
HRESULT SmbFileServiceProvider::EnumerateSessions(
IResultData* pResultData,
CFileMgmtCookie* pcookie,
bool bAddToResultPane)
{
TEST_NONNULL_PTR_PARAM(pcookie);
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
SESSION_INFO_1* psi1 = NULL;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD hEnumHandle = 0;
HRESULT hr = S_OK;
NET_API_STATUS retval = NERR_Success;
do {
retval = ((SESSIONENUMPROC)g_SmbDLL[SMB_SESSION_ENUM])(
const_cast<LPTSTR>(pcookie->QueryTargetServer()),
NULL,
NULL,
1,
(PBYTE*)&psi1,
(DWORD)-1L,
&dwEntriesRead,
&dwTotalEntries,
&hEnumHandle );
if (NERR_Success == retval)
{
hr = HandleSMBSessionItems( pResultData, pcookie, psi1, dwEntriesRead,
bAddToResultPane );
psi1 = NULL;
break;
} else if (ERROR_MORE_DATA == retval) {
ASSERT( NULL != hEnumHandle );
hr = HandleSMBSessionItems( pResultData, pcookie, psi1, dwEntriesRead,
bAddToResultPane );
psi1 = NULL;
continue;
} else {
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, retval, IDS_POPUP_SMB_SESSIONS, pcookie->QueryNonNULLMachineName() );
break;
}
} while (S_OK == hr);
return HRESULT_FROM_WIN32(retval);
}
/*
typedef enum _COLNUM_SESSIONS {
COLNUM_SESSIONS_USERNAME = 0,
COLNUM_SESSIONS_COMPUTERNAME,
COLNUM_SESSIONS_NUM_FILES,
COLNUM_SESSIONS_CONNECTED_TIME,
COLNUM_SESSIONS_IDLE_TIME,
COLNUM_SESSIONS_IS_GUEST
} COLNUM_SESSIONS;
typedef struct _SESSION_INFO_1 {
LPTSTR sesi1_cname; // client name (no backslashes)
LPTSTR sesi1_username;
DWORD sesi1_num_opens;
DWORD sesi1_time;
DWORD sesi1_idle_time;
DWORD sesi1_user_flags;
} SESSION_INFO_1, *PSESSION_INFO_1, *LPSESSION_INFO_1;
*/
// if pResultData is not NULL, add sessions/resources to the listbox
// if pResultData is NULL, delete all sessions/resources
// if pResultData is NULL, return SUCCEEDED(hr) to continue or
// FAILED(hr) to abort
HRESULT SmbFileServiceProvider::HandleSMBSessionItems(
IResultData* pResultData,
CFileMgmtCookie* pParentCookie,
PVOID pinfo,
DWORD nItems,
BOOL bAddToResultPane)
{
TEST_NONNULL_PTR_PARAM(pParentCookie);
TEST_NONNULL_PTR_PARAM(pinfo);
if (0 >= nItems)
return S_OK;
BOOL fDeleteAllItems = (NULL == pResultData);
RESULTDATAITEM tRDItem;
::ZeroMemory( &tRDItem, sizeof(tRDItem) );
// CODEWORK should use MMC_ICON_CALLBACK
tRDItem.nImage = iIconSMBSession;
tRDItem.nCol = COLNUM_SESSIONS_USERNAME;
tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
tRDItem.str = MMC_CALLBACK;
SESSION_INFO_1* psi1 = (SESSION_INFO_1*)pinfo;
CSmbSessionCookie* pcookiearray = new CSmbSessionCookie[nItems];
CSmbCookieBlock* pCookieBlock = new CSmbCookieBlock(
pcookiearray,nItems,pParentCookie->QueryNonNULLMachineName(),pinfo );
bool bAdded = false;
if ( !fDeleteAllItems || !bAddToResultPane )
{
pParentCookie->m_listResultCookieBlocks.AddHead( pCookieBlock );
bAdded = true;
}
for ( ; nItems > 0; nItems--, psi1++, pcookiearray++ )
{
pcookiearray->m_pobject = psi1;
if ( bAddToResultPane )
{
if (fDeleteAllItems)
{
DWORD dwApiResult = CloseSession( pcookiearray );
if (0L != dwApiResult)
{
CString strName;
TranslateIPToComputerName(psi1->sesi1_cname, strName);
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, dwApiResult,
IDS_POPUP_SMB_DISCONNECTALLSESSION_ERROR,
strName );
//return S_FALSE;
}
continue;
}
// WARNING cookie cast
if (psi1->sesi1_username && *(psi1->sesi1_username)) // bug#3903: exclude NULL session
{
tRDItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pcookiearray);
HRESULT hr = pResultData->InsertItem(&tRDItem);
ASSERT(SUCCEEDED(hr));
}
}
}
if ( !bAdded ) // they were not added to the parent cookie's list
delete pCookieBlock;
return S_OK;
}
/*
NET_API_STATUS NET_API_FUNCTION
NetFileEnum (
IN LPTSTR servername OPTIONAL,
IN LPTSTR basepath OPTIONAL,
IN LPTSTR username OPTIONAL,
IN DWORD level,
OUT LPBYTE *bufptr,
IN DWORD prefmaxlen,
OUT LPDWORD entriesread,
OUT LPDWORD totalentries,
IN OUT LPDWORD resume_handle OPTIONAL
);
*/
typedef DWORD (*FILEENUMPROC) (LPTSTR,LPTSTR,LPTSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD);
// if pResultData is not NULL, add sessions/resources to the listbox
// if pResultData is NULL, delete all sessions/resources
// if pResultData is NULL, return SUCCEEDED(hr) to continue or
// FAILED(hr) to abort
HRESULT SmbFileServiceProvider::EnumerateResources(
IResultData* pResultData,
CFileMgmtCookie* pcookie)
{
TEST_NONNULL_PTR_PARAM(pcookie);
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
FILE_INFO_3* pfi3 = NULL;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD hEnumHandle = 0;
HRESULT hr = S_OK;
NET_API_STATUS retval = NERR_Success;
do {
retval = ((FILEENUMPROC)g_SmbDLL[SMB_FILE_ENUM])(
const_cast<LPTSTR>(pcookie->QueryTargetServer()),
NULL,
NULL,
3,
(PBYTE*)&pfi3,
(DWORD)-1L,
&dwEntriesRead,
&dwTotalEntries,
&hEnumHandle );
if (NERR_Success == retval)
{
hr = HandleSMBResourceItems( pResultData, pcookie, pfi3, dwEntriesRead );
pfi3 = NULL;
break;
} else if (ERROR_MORE_DATA == retval) {
ASSERT( NULL != hEnumHandle );
hr = HandleSMBResourceItems( pResultData, pcookie, pfi3, dwEntriesRead );
pfi3 = NULL;
continue;
} else {
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, retval, IDS_POPUP_SMB_RESOURCES, pcookie->QueryNonNULLMachineName() );
break;
}
} while (S_OK == hr);
return HRESULT_FROM_WIN32(retval);
}
/*
typedef enum _COLNUM_RESOURCES {
COLNUM_RESOURCES_FILENAME = 0,
COLNUM_RESOURCES_USERNAME,
COLNUM_RESOURCES_NUM_LOCKS, // we don't try to display sharename for now, since
// only SMB has this information
COLNUM_RESOURCES_OPEN_MODE
} COLNUM_RESOURCES;
typedef struct _FILE_INFO_3 {
DWORD fi3_id;
DWORD fi3_permissions;
DWORD fi3_num_locks;
LPTSTR fi3_pathname;
LPTSTR fi3_username;
} FILE_INFO_3, *PFILE_INFO_3, *LPFILE_INFO_3;
*/
// if pResultData is not NULL, add sessions/resources to the listbox
// if pResultData is NULL, delete all sessions/resources
// if pResultData is NULL, return SUCCEEDED(hr) to continue or
// FAILED(hr) to abort
HRESULT SmbFileServiceProvider::HandleSMBResourceItems(
IResultData* pResultData,
CFileMgmtCookie* pParentCookie,
PVOID pinfo,
DWORD nItems)
{
TEST_NONNULL_PTR_PARAM(pParentCookie);
TEST_NONNULL_PTR_PARAM(pinfo);
if (0 >= nItems)
return S_OK;
BOOL fDeleteAllItems = (NULL == pResultData);
RESULTDATAITEM tRDItem;
::ZeroMemory( &tRDItem, sizeof(tRDItem) );
// CODEWORK should use MMC_ICON_CALLBACK
tRDItem.nImage = iIconSMBResource;
tRDItem.nCol = COLNUM_RESOURCES_FILENAME;
tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
tRDItem.str = MMC_CALLBACK;
FILE_INFO_3* pfi3 = (FILE_INFO_3*)pinfo;
CSmbResourceCookie* pcookiearray = new CSmbResourceCookie[nItems];
CSmbCookieBlock* pCookieBlock = new CSmbCookieBlock(
pcookiearray,nItems,pParentCookie->QueryNonNULLMachineName(),pinfo );
if (!fDeleteAllItems)
{
pParentCookie->m_listResultCookieBlocks.AddHead( pCookieBlock );
}
CString str;
for ( ; nItems > 0; nItems--, pfi3++, pcookiearray++ )
{
pcookiearray->m_pobject = pfi3;
if (fDeleteAllItems)
{
DWORD dwApiResult = CloseResource( pcookiearray );
if (0L != dwApiResult)
{
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, dwApiResult,
IDS_POPUP_SMB_DISCONNECTALLRESOURCE_ERROR,
pfi3->fi3_pathname );
return S_FALSE;
}
continue;
}
// WARNING cookie cast
tRDItem.lParam = reinterpret_cast<LPARAM>((CCookie*)pcookiearray);
HRESULT hr = pResultData->InsertItem(&tRDItem);
ASSERT(SUCCEEDED(hr));
}
if (fDeleteAllItems) // they were not added to the parent cookie's list
delete pCookieBlock;
return S_OK;
}
/*
NET_API_STATUS NET_API_FUNCTION
NetShareDel (
IN LPTSTR servername,
IN LPTSTR netname,
IN DWORD reserved
);
*/
typedef DWORD (*SHAREGETINFOPROC) (LPTSTR,LPTSTR,DWORD,LPBYTE*);
typedef DWORD (*SHAREDELPROC) (LPTSTR,LPTSTR,DWORD);
DWORD SmbFileServiceProvider::DeleteShare( LPCTSTR lpcszServerName, LPCTSTR lpcszShareName )
{
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
SHARE_INFO_2 *pshi2 = NULL;
NET_API_STATUS dwRet = NERR_Success;
BOOL bLocal = TRUE;
bLocal = IsLocalComputername(lpcszServerName);
if (bLocal)
{
dwRet = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
const_cast<LPTSTR>(lpcszServerName),
const_cast<LPTSTR>(lpcszShareName),
2,
(LPBYTE*)&pshi2);
if (NERR_NetNameNotFound == dwRet)
return NERR_Success;
if (NERR_Success != dwRet)
return dwRet;
}
dwRet = ((SHAREDELPROC)g_SmbDLL[SMB_SHARE_DEL])(
const_cast<LPTSTR>(lpcszServerName),
const_cast<LPTSTR>(lpcszShareName),
0L );
if (NERR_NetNameNotFound == dwRet)
dwRet = NERR_Success;
if (NERR_Success == dwRet)
{
IADsContainer *piADsContainer = m_pFileMgmtData->GetIADsContainer(); // no need to AddRef
if (piADsContainer)
{
CString strCNName = _T("CN=");
strCNName += lpcszShareName;
(void)piADsContainer->Delete(_T("volume"), (LPTSTR)(LPCTSTR)strCNName);
}
}
if (bLocal)
{
if (dwRet == NERR_Success)
{
SHChangeNotify(
SHCNE_NETUNSHARE,
SHCNF_PATH | SHCNF_FLUSHNOWAIT ,
pshi2->shi2_path,
0);
}
FreeData( pshi2 );
}
return dwRet;
}
/*
NET_API_STATUS NET_API_FUNCTION
NetSessionDel (
IN LPTSTR servername OPTIONAL,
IN LPTSTR UncClientName,
IN LPTSTR username
);
*/
typedef DWORD (*SESSIONDELPROC) (LPTSTR,LPTSTR,LPTSTR);
BOOL BlockRemoteAdminSession(
IN PCTSTR i_pszTargetServer,
IN PCTSTR i_pszClientName,
IN PCTSTR i_pszUserName,
IN DWORD i_dwNumOpenSessions
);
BOOL BlockRemoteAdminFile(
IN PCTSTR i_pszTargetServer,
IN PCTSTR i_pszPathName,
IN PCTSTR i_pszUserName
);
DWORD SmbFileServiceProvider::CloseSession(CFileMgmtResultCookie* pcookie)
{
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
ASSERT( FILEMGMT_SESSION == pcookie->QueryObjectType() );
SESSION_INFO_1* psi1 = (SESSION_INFO_1*)pcookie->m_pobject;
ASSERT( NULL != psi1 &&
NULL != psi1->sesi1_cname &&
TEXT('\0') != *(psi1->sesi1_cname) );
PCTSTR pszTargetServer = pcookie->QueryTargetServer();
if (BlockRemoteAdminSession(pszTargetServer, psi1->sesi1_cname, psi1->sesi1_username, psi1->sesi1_num_opens))
return NERR_Success;
CString strCName = _T("\\\\");
strCName += psi1->sesi1_cname;
DWORD dwRetval = ((SESSIONDELPROC)g_SmbDLL[SMB_SESSION_DEL])(
const_cast<LPTSTR>(pszTargetServer),
const_cast<LPTSTR>((LPCTSTR)strCName),
psi1->sesi1_username );
return (NERR_NoSuchSession == dwRetval) ? NERR_Success : dwRetval;
}
/*
NET_API_STATUS NET_API_FUNCTION
NetFileClose (
IN LPTSTR servername OPTIONAL,
IN DWORD fileid
);
*/
typedef DWORD (*FILECLOSEPROC) (LPTSTR,DWORD);
DWORD SmbFileServiceProvider::CloseResource(CFileMgmtResultCookie* pcookie)
{
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
ASSERT( FILEMGMT_RESOURCE == pcookie->QueryObjectType() );
FILE_INFO_3* pfileinfo = (FILE_INFO_3*)pcookie->m_pobject;
ASSERT( NULL != pfileinfo );
PCTSTR pszTargetServer = pcookie->QueryTargetServer();
if (BlockRemoteAdminFile(pszTargetServer, pfileinfo->fi3_pathname, pfileinfo->fi3_username))
return NERR_Success;
DWORD dwRetval = ((FILECLOSEPROC)g_SmbDLL[SMB_FILE_CLOSE])(
const_cast<LPTSTR>(pszTargetServer),
pfileinfo->fi3_id );
return (NERR_FileIdNotFound == dwRetval) ? NERR_Success : dwRetval;
}
/*
NET_API_STATUS NET_API_FUNCTION
NetShareGetInfo (
IN LPTSTR servername,
IN LPTSTR netname,
IN DWORD level,
OUT LPBYTE *bufptr
);
NET_API_STATUS NET_API_FUNCTION
NetShareSetInfo (
IN LPTSTR servername,
IN LPTSTR netname,
IN DWORD level,
IN LPBYTE buf,
OUT LPDWORD parm_err
);
typedef struct _SHARE_INFO_2 {
LPTSTR shi2_netname;
DWORD shi2_type;
LPTSTR shi2_remark;
DWORD shi2_permissions;
DWORD shi2_max_uses;
DWORD shi2_current_uses;
LPTSTR shi2_path;
LPTSTR shi2_passwd;
} SHARE_INFO_2, *PSHARE_INFO_2, *LPSHARE_INFO_2;
*/
typedef DWORD (*SHARESETINFOPROC) (LPTSTR,LPTSTR,DWORD,LPBYTE,LPDWORD);
VOID SmbFileServiceProvider::DisplayShareProperties(
LPPROPERTYSHEETCALLBACK pCallBack,
LPDATAOBJECT pDataObject,
LONG_PTR handle)
{
HRESULT hr = S_OK;
CSharePageGeneralSMB * pPage = new CSharePageGeneralSMB();
if ( !pPage->Load( m_pFileMgmtData, pDataObject ) )
return;
// This mechanism deletes the CFileMgmtGeneral when the property sheet is finished
pPage->m_pfnOriginalPropSheetPageProc = pPage->m_psp.pfnCallback;
pPage->m_psp.lParam = reinterpret_cast<LPARAM>(pPage);
pPage->m_psp.pfnCallback = &CSharePageGeneralSMB::PropSheetPageProc;
pPage->m_handle = handle;
MMCPropPageCallback(INOUT &pPage->m_psp);
HPROPSHEETPAGE hPage=MyCreatePropertySheetPage(&pPage->m_psp);
pCallBack->AddPage(hPage);
if (pPage->m_dwShareType & (STYPE_IPC | STYPE_SPECIAL))
{
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONINFORMATION, 0, IDS_s_POPUP_ADMIN_SHARE);
return;
}
//
// display the "Publish" page
//
if (m_pFileMgmtData->GetSchemaSupportSharePublishing() && CheckPolicyOnSharePublish(pPage->m_strShareName))
{
CSharePagePublish * pPagePublish = new CSharePagePublish();
if ( !pPagePublish->Load( m_pFileMgmtData, pDataObject ) )
return;
// This mechanism deletes the pPagePublish when the property sheet is finished
pPagePublish->m_pfnOriginalPropSheetPageProc = pPagePublish->m_psp.pfnCallback;
pPagePublish->m_psp.lParam = reinterpret_cast<LPARAM>(pPagePublish);
pPagePublish->m_psp.pfnCallback = &CSharePagePublish::PropSheetPageProc;
pPagePublish->m_handle = handle;
MMCPropPageCallback(INOUT &pPagePublish->m_psp);
HPROPSHEETPAGE hPagePublish=MyCreatePropertySheetPage(&pPagePublish->m_psp);
pCallBack->AddPage(hPagePublish);
}
//
// display the "Share Security" page
//
CComObject<CSMBSecurityInformation>* psecinfo = NULL;
hr = CComObject<CSMBSecurityInformation>::CreateInstance(&psecinfo);
if ( SUCCEEDED(hr) )
MyCreateShareSecurityPage(
pCallBack,
psecinfo,
pPage->m_strMachineName,
pPage->m_strShareName );
CreateFolderSecurityPropPage(pCallBack, pDataObject);
}
DWORD SmbFileServiceProvider::ReadShareType(
LPCTSTR ptchServerName,
LPCTSTR ptchShareName,
OUT DWORD* pdwShareType)
{
if ( !g_SmbDLL.LoadFunctionPointers() )
{
ASSERT(FALSE);
return S_OK;
}
*pdwShareType = 0;
SHARE_INFO_2* psi2 = NULL;
NET_API_STATUS retval = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
const_cast<LPTSTR>(ptchServerName),
const_cast<LPTSTR>(ptchShareName),
2,
(LPBYTE*)&psi2);
if (NERR_Success != retval)
return retval;
ASSERT( NULL != psi2 );
*pdwShareType = psi2->shi2_type;
FreeData(psi2);
return NERR_Success;
}
DWORD SmbFileServiceProvider::ReadShareProperties(
LPCTSTR ptchServerName,
LPCTSTR ptchShareName,
OUT PVOID* ppvPropertyBlock,
OUT CString& strDescription,
OUT CString& strPath,
OUT BOOL* pfEditDescription,
OUT BOOL* pfEditPath,
OUT DWORD* pdwShareType)
{
if ( !g_SmbDLL.LoadFunctionPointers() )
{
ASSERT(FALSE);
return S_OK;
}
if (ppvPropertyBlock) *ppvPropertyBlock = NULL;
if (pdwShareType) *pdwShareType = 0;
if (pfEditDescription) *pfEditDescription = TRUE;
if (pfEditPath) *pfEditPath = FALSE;
SHARE_INFO_2* psi2 = NULL;
NET_API_STATUS retval = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
const_cast<LPTSTR>(ptchServerName),
const_cast<LPTSTR>(ptchShareName),
2,
(LPBYTE*)&psi2);
if (NERR_Success != retval)
return retval;
strDescription = psi2->shi2_remark;
strPath = psi2->shi2_path;
if (pdwShareType)
*pdwShareType = psi2->shi2_type;
if (ppvPropertyBlock)
{
*ppvPropertyBlock = psi2; // will be freed by the caller
} else
{
FreeData((LPVOID)psi2);
}
return NERR_Success;
}
DWORD SmbFileServiceProvider::WriteShareProperties(
OUT LPCTSTR ptchServerName,
OUT LPCTSTR ptchShareName,
OUT PVOID pvPropertyBlock,
OUT LPCTSTR ptchDescription,
OUT LPCTSTR ptchPath)
{
ASSERT( NULL != pvPropertyBlock );
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pvPropertyBlock;
//
// CODEWORK Note that this leaves psi2 invalid after the call, but that any subsequent
// use will replace these pointers.
//
psi2->shi2_remark = const_cast<LPTSTR>(ptchDescription);
psi2->shi2_path = const_cast<LPTSTR>(ptchPath);
DWORD dwDummy;
DWORD retval = ((SHARESETINFOPROC)g_SmbDLL[SMB_SHARE_SET_INFO])(
const_cast<LPTSTR>(ptchServerName),
const_cast<LPTSTR>(ptchShareName),
2,
(LPBYTE)psi2,
&dwDummy);
psi2->shi2_remark = NULL;
psi2->shi2_path = NULL;
return retval;
}
HRESULT TranslateManagedBy(
IN PCTSTR i_pszDCName,
IN PCTSTR i_pszIn,
OUT CString& o_strOut,
IN ADS_NAME_TYPE_ENUM i_formatIn,
IN ADS_NAME_TYPE_ENUM i_formatOut
)
{
o_strOut.Empty();
HRESULT hr = S_OK;
if (!i_pszIn || !*i_pszIn)
return hr;
CComPtr<IADsNameTranslate> spiADsNameTranslate;
hr = CoCreateInstance(CLSID_NameTranslate, NULL, CLSCTX_INPROC_SERVER, IID_IADsNameTranslate, (void **)&spiADsNameTranslate);
if (FAILED(hr)) return hr;
hr = spiADsNameTranslate->Init(ADS_NAME_INITTYPE_SERVER, (LPTSTR)i_pszDCName);
if (FAILED(hr)) return hr;
hr = spiADsNameTranslate->Set(i_formatIn, (LPTSTR)i_pszIn);
if (FAILED(hr)) return hr;
CComBSTR sbstr;
hr = spiADsNameTranslate->Get(i_formatOut, &sbstr);
if (SUCCEEDED(hr))
o_strOut = (BSTR)sbstr;
return hr;
}
HRESULT SmbFileServiceProvider::ReadSharePublishInfo(
LPCTSTR ptchServerName,
LPCTSTR ptchShareName,
OUT BOOL* pbPublish,
OUT CString& strUNCPath,
OUT CString& strDescription,
OUT CString& strKeywords,
OUT CString& strManagedBy)
{
HRESULT hr = S_OK;
do {
CString strADsPath, strDCName;
hr = GetADsPathOfComputerObject(ptchServerName, strADsPath, strDCName);
if (S_OK != hr) break;
CComPtr<IADsContainer> spiADsContainer;
hr = ADsGetObject(strADsPath, IID_IADsContainer, (void**)&spiADsContainer);
if (FAILED(hr)) break;
CString strCNName = _T("CN=");
strCNName += ptchShareName;
CComPtr<IDispatch> spiDispatch;
hr = spiADsContainer->GetObject(_T("volume"), (LPTSTR)(LPCTSTR)strCNName, &spiDispatch);
if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hr)
{
hr = S_OK;
*pbPublish = FALSE;
break;
}
if (FAILED(hr)) break;
*pbPublish = TRUE;
CComPtr<IADs> spiADs;
hr = spiDispatch->QueryInterface(IID_IADs, (void**)&spiADs);
if (FAILED(hr)) break;
VARIANT var;
VariantInit(&var);
hr = spiADs->Get(_T("uNCName"), &var);
if (FAILED(hr)) break;
strUNCPath = V_BSTR(&var);
VariantClear(&var);
hr = spiADs->Get(_T("description"), &var);
if (SUCCEEDED(hr))
{
hr = GetSingleOrMultiValuesFromVarArray(&var, strDescription);
VariantClear(&var);
} else if (E_ADS_PROPERTY_NOT_FOUND == hr)
hr = S_OK;
else
break;
hr = spiADs->Get(_T("keywords"), &var);
if (SUCCEEDED(hr))
{
hr = GetSingleOrMultiValuesFromVarArray(&var, strKeywords);
VariantClear(&var);
} else if (E_ADS_PROPERTY_NOT_FOUND == hr)
hr = S_OK;
else
break;
hr = spiADs->Get(_T("managedBy"), &var);
if (SUCCEEDED(hr))
{
// 1st, try map to a UPN user@xyz.com
hr = TranslateManagedBy(strDCName,
V_BSTR(&var),
strManagedBy,
ADS_NAME_TYPE_1779,
ADS_NAME_TYPE_USER_PRINCIPAL_NAME);
// in case no UPN, map to NT4 style domain\user
if (FAILED(hr))
hr = TranslateManagedBy(strDCName,
V_BSTR(&var),
strManagedBy,
ADS_NAME_TYPE_1779,
ADS_NAME_TYPE_NT4);
VariantClear(&var);
} else if (E_ADS_PROPERTY_NOT_FOUND == hr)
hr = S_OK;
else
break;
} while (0);
return hr;
}
HRESULT SmbFileServiceProvider::WriteSharePublishInfo(
LPCTSTR ptchServerName,
LPCTSTR ptchShareName,
IN BOOL bPublish,
LPCTSTR ptchDescription,
LPCTSTR ptchKeywords,
LPCTSTR ptchManagedBy)
{
HRESULT hr = S_OK;
do {
CString strADsPath, strDCName;
hr = GetADsPathOfComputerObject(ptchServerName, strADsPath, strDCName);
if (S_OK != hr) break;
CComPtr<IADsContainer> spiADsContainer;
hr = ADsGetObject(strADsPath, IID_IADsContainer, (void**)&spiADsContainer);
if (FAILED(hr)) break;
CString strCNName = _T("CN=");
strCNName += ptchShareName;
if (!bPublish)
{
hr = spiADsContainer->Delete(_T("volume"), (LPTSTR)(LPCTSTR)strCNName);
if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hr)
hr = S_OK;
break;
}
BOOL bNewObject = FALSE;
CComPtr<IDispatch> spiDispatch;
hr = spiADsContainer->GetObject(_T("volume"), (LPTSTR)(LPCTSTR)strCNName, &spiDispatch);
if (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) == hr)
{
hr = spiADsContainer->Create(_T("volume"), (LPTSTR)(LPCTSTR)strCNName, &spiDispatch);
bNewObject = TRUE;
}
if (FAILED(hr)) break;
CComPtr<IADs> spiADs;
hr = spiDispatch->QueryInterface(IID_IADs, (void**)&spiADs);
if (FAILED(hr)) break;
VARIANT var;
VariantInit(&var);
if (bNewObject)
{
CString strUNCName = _T("\\\\");
strUNCName += ptchServerName;
strUNCName += _T("\\");
strUNCName += ptchShareName;
V_BSTR(&var) = SysAllocString(strUNCName);
V_VT(&var) = VT_BSTR;
hr = spiADs->Put(_T("uNCName"), var);
VariantClear(&var);
if (FAILED(hr)) break;
}
// according to schema, description is multi valued.
// but we're treating it as single value
if (ptchDescription && *ptchDescription)
{
V_BSTR(&var) = SysAllocString(ptchDescription);
V_VT(&var) = VT_BSTR;
hr = spiADs->Put(_T("description"), var);
VariantClear(&var);
} else if (!bNewObject)
{
V_VT(&var)=VT_NULL;
hr = spiADs->PutEx(ADS_PROPERTY_CLEAR, _T("description"), var);
VariantClear(&var);
}
if (FAILED(hr)) break;
if (ptchKeywords && *ptchKeywords)
{
hr = PutMultiValuesIntoVarArray(ptchKeywords, &var);
if (SUCCEEDED(hr))
{
hr = spiADs->Put(_T("keywords"), var);
VariantClear(&var);
}
} else if (!bNewObject)
{
V_VT(&var)=VT_NULL;
hr = spiADs->PutEx(ADS_PROPERTY_CLEAR, _T("keywords"), var);
VariantClear(&var);
}
if (FAILED(hr)) break;
if (ptchManagedBy && *ptchManagedBy)
{
CString strManagedByFQDN;
hr = TranslateManagedBy(strDCName,
ptchManagedBy,
strManagedByFQDN,
(_tcschr(ptchManagedBy, _T('@')) ? ADS_NAME_TYPE_USER_PRINCIPAL_NAME : ADS_NAME_TYPE_NT4),
ADS_NAME_TYPE_1779);
if (SUCCEEDED(hr))
{
V_BSTR(&var) = SysAllocString(strManagedByFQDN);
V_VT(&var) = VT_BSTR;
hr = spiADs->Put(_T("managedBy"), var);
VariantClear(&var);
}
} else if (!bNewObject)
{
V_VT(&var)=VT_NULL;
hr = spiADs->PutEx(ADS_PROPERTY_CLEAR, _T("managedBy"), var);
VariantClear(&var);
}
if (FAILED(hr)) break;
hr = spiADs->SetInfo(); // commit
} while (0);
return hr;
}
//
// These methods cover the seperate API to determine whether IntelliMirror
// caching is enabled. By default (FPNW and SFM) they are disabled.
//
// We read this data at level 501 in order to determine whether the target
// server is NT4. NetShareGetInfo[1005] actually succeeds on an NT4 server,
// whereas NetShareGetInfo[501] fails with ERROR_INVALID_LEVEL. We want this
// to fail so that we can disable the checkbox where the underlying
// functionality is not supported.
//
DWORD SmbFileServiceProvider::ReadShareFlags(
LPCTSTR ptchServerName,
LPCTSTR ptchShareName,
DWORD* pdwFlags )
{
ASSERT( NULL != pdwFlags );
if ( !g_SmbDLL.LoadFunctionPointers() )
{
ASSERT(FALSE);
return S_OK;
}
*pdwFlags = 0;
SHARE_INFO_501* pshi501 = NULL;
NET_API_STATUS retval = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
const_cast<LPTSTR>(ptchServerName),
const_cast<LPTSTR>(ptchShareName),
501,
(LPBYTE*)&pshi501);
if (NERR_Success != retval)
return retval;
ASSERT( NULL != pshi501 );
*pdwFlags = pshi501->shi501_flags;
FreeData( pshi501 );
return NERR_Success;
}
DWORD SmbFileServiceProvider::WriteShareFlags(
LPCTSTR ptchServerName,
LPCTSTR ptchShareName,
DWORD dwFlags )
{
if ( !g_SmbDLL.LoadFunctionPointers() )
return S_OK;
SHARE_INFO_1005 shi1005;
ZeroMemory( &shi1005, sizeof(shi1005) );
shi1005.shi1005_flags = dwFlags;
DWORD dwDummy;
DWORD retval = ((SHARESETINFOPROC)g_SmbDLL[SMB_SHARE_SET_INFO])(
const_cast<LPTSTR>(ptchServerName),
const_cast<LPTSTR>(ptchShareName),
1005,
(LPBYTE)&shi1005,
&dwDummy);
return retval;
}
BOOL SmbFileServiceProvider::GetCachedFlag( DWORD dwFlags, DWORD dwFlagToCheck )
{
return (dwFlags & CSC_MASK) == dwFlagToCheck;
}
VOID SmbFileServiceProvider::SetCachedFlag( DWORD* pdwFlags, DWORD dwNewFlag )
{
*pdwFlags &= ~CSC_MASK;
*pdwFlags |= dwNewFlag;
}
VOID SmbFileServiceProvider::FreeShareProperties(PVOID pvPropertyBlock)
{
FreeData( pvPropertyBlock );
}
DWORD SmbFileServiceProvider::QueryMaxUsers(PVOID pvPropertyBlock)
{
SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pvPropertyBlock;
ASSERT( NULL != psi2 );
return psi2->shi2_max_uses;
}
VOID SmbFileServiceProvider::SetMaxUsers(PVOID pvPropertyBlock, DWORD dwMaxUsers)
{
SHARE_INFO_2* psi2 = (SHARE_INFO_2*)pvPropertyBlock;
ASSERT( NULL != psi2 );
psi2->shi2_max_uses = dwMaxUsers;
}
VOID SmbFileServiceProvider::FreeData(PVOID pv)
{
SMBFreeData( &pv );
}
LPCTSTR SmbFileServiceProvider::QueryTransportString()
{
return m_strTransportSMB;
}
CSmbCookieBlock::~CSmbCookieBlock()
{
SMBFreeData( &m_pvCookieData );
}
DEFINE_COOKIE_BLOCK(CSmbCookie)
DEFINE_FORWARDS_MACHINE_NAME( CSmbCookie, m_pCookieBlock )
void CSmbCookie::AddRefCookie() { m_pCookieBlock->AddRef(); }
void CSmbCookie::ReleaseCookie() { m_pCookieBlock->Release(); }
HRESULT CSmbCookie::GetTransport( FILEMGMT_TRANSPORT* pTransport )
{
*pTransport = FILEMGMT_SMB;
return S_OK;
}
HRESULT CSmbShareCookie::GetShareName( CString& strShareName )
{
SHARE_INFO_2* psi2 = (SHARE_INFO_2*)m_pobject;
ASSERT( NULL != psi2 );
strShareName = psi2->shi2_netname;
return S_OK;
}
HRESULT CSmbShareCookie::GetExplorerViewDescription(
OUT CString& strExplorerViewDescription )
{
strExplorerViewDescription = GetShareInfo()->shi2_remark;
return S_OK;
}
HRESULT
CSmbShareCookie::GetSharePIDList( OUT LPITEMIDLIST *ppidl )
{
ASSERT(ppidl);
ASSERT(NULL == *ppidl); // prevent memory leak
*ppidl = NULL;
SHARE_INFO_2* psi2 = (SHARE_INFO_2*)m_pobject;
ASSERT( NULL != psi2 );
PCTSTR pszTargetServer = m_pCookieBlock->QueryTargetServer();
CString csPath;
if (pszTargetServer)
{
if ( _tcslen(pszTargetServer) >= 2 &&
_T('\\') == *pszTargetServer &&
_T('\\') == *(pszTargetServer + 1) )
{
csPath = pszTargetServer;
} else
{
csPath = _T("\\\\");
csPath += pszTargetServer;
}
csPath += _T("\\");
csPath += psi2->shi2_netname;
} else
{
csPath = psi2->shi2_path;
}
if (FALSE == csPath.IsEmpty())
*ppidl = ILCreateFromPath(csPath);
return ((*ppidl) ? S_OK : E_FAIL);
}
HRESULT CSmbSessionCookie::GetSessionClientName( CString& strName )
{
SESSION_INFO_1* psi1 = (SESSION_INFO_1*)m_pobject;
ASSERT( NULL != psi1 );
TranslateIPToComputerName(psi1->sesi1_cname, strName);
return S_OK;
}
HRESULT CSmbSessionCookie::GetSessionUserName( CString& strShareName )
{
SESSION_INFO_1* psi1 = (SESSION_INFO_1*)m_pobject;
ASSERT( NULL != psi1 );
strShareName = psi1->sesi1_username;
return S_OK;
}
HRESULT CSmbResourceCookie::GetFileID( DWORD* pdwFileID )
{
FILE_INFO_3* pfileinfo = (FILE_INFO_3*)m_pobject;
ASSERT( NULL != pdwFileID && NULL != pfileinfo );
*pdwFileID = pfileinfo->fi3_id;
return S_OK;
}
BSTR CSmbShareCookie::GetColumnText( int nCol )
{
switch (nCol)
{
case COLNUM_SHARES_SHARED_FOLDER:
return GetShareInfo()->shi2_netname;
case COLNUM_SHARES_SHARED_PATH:
return GetShareInfo()->shi2_path;
case COLNUM_SHARES_TRANSPORT:
return const_cast<BSTR>((LPCTSTR)g_strTransportSMB);
case COLNUM_SHARES_COMMENT:
return GetShareInfo()->shi2_remark;
default:
ASSERT(FALSE);
break;
}
return L"";
}
BSTR CSmbShareCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ )
{
if (COLNUM_SHARES_NUM_SESSIONS == nCol)
return MakeDwordResult( GetNumOfCurrentUses() );
return GetColumnText(nCol);
}
extern CString g_cstrClientName;
extern CString g_cstrGuest;
extern CString g_cstrYes;
extern CString g_cstrNo;
BSTR CSmbSessionCookie::GetColumnText( int nCol )
{
switch (nCol)
{
case COLNUM_SESSIONS_USERNAME:
if ( (GetSessionInfo()->sesi1_user_flags & SESS_GUEST) &&
( !(GetSessionInfo()->sesi1_username) ||
_T('\0') == *(GetSessionInfo()->sesi1_username) ) )
{
return const_cast<BSTR>(((LPCTSTR)g_cstrGuest));
} else
{
return GetSessionInfo()->sesi1_username;
}
case COLNUM_SESSIONS_COMPUTERNAME:
{
TranslateIPToComputerName(GetSessionInfo()->sesi1_cname, g_cstrClientName);
return const_cast<BSTR>(((LPCTSTR)g_cstrClientName));
}
case COLNUM_SESSIONS_TRANSPORT:
return const_cast<BSTR>((LPCTSTR)g_strTransportSMB);
case COLNUM_SESSIONS_IS_GUEST:
if (GetSessionInfo()->sesi1_user_flags & SESS_GUEST)
return const_cast<BSTR>(((LPCTSTR)g_cstrYes));
else
return const_cast<BSTR>(((LPCTSTR)g_cstrNo));
default:
ASSERT(FALSE);
break;
}
return L"";
}
BSTR CSmbSessionCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ )
{
switch (nCol)
{
case COLNUM_SESSIONS_NUM_FILES:
return MakeDwordResult( GetNumOfOpenFiles() );
case COLNUM_SESSIONS_CONNECTED_TIME:
return MakeElapsedTimeResult( GetConnectedTime() );
case COLNUM_SESSIONS_IDLE_TIME:
return MakeElapsedTimeResult( GetIdleTime() );
default:
break;
}
return GetColumnText(nCol);
}
BSTR CSmbResourceCookie::GetColumnText( int nCol )
{
switch (nCol)
{
case COLNUM_RESOURCES_FILENAME:
return GetFileInfo()->fi3_pathname;
case COLNUM_RESOURCES_USERNAME:
return GetFileInfo()->fi3_username;
case COLNUM_RESOURCES_TRANSPORT:
return const_cast<BSTR>((LPCTSTR)g_strTransportSMB);
case COLNUM_RESOURCES_OPEN_MODE:
return MakePermissionsResult( GetFileInfo()->fi3_permissions );
default:
ASSERT(FALSE);
break;
}
return L"";
}
BSTR CSmbResourceCookie::QueryResultColumnText( int nCol, CFileMgmtComponentData& /*refcdata*/ )
{
if (COLNUM_RESOURCES_NUM_LOCKS == nCol)
return MakeDwordResult( GetNumOfLocks() );
return GetColumnText(nCol);
}
CSMBSecurityInformation::CSMBSecurityInformation()
: m_pvolumeinfo( NULL ),
m_pDefaultDescriptor( NULL )
{
}
CSMBSecurityInformation::~CSMBSecurityInformation()
{
if (NULL != m_pDefaultDescriptor)
{
LocalFree(m_pDefaultDescriptor);
m_pvolumeinfo->shi502_security_descriptor = NULL;
}
SMBFreeData( (PVOID*)&m_pvolumeinfo );
}
STDMETHODIMP CSMBSecurityInformation::GetSecurity (
SECURITY_INFORMATION RequestedInformation,
PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
BOOL fDefault )
{
MFC_TRY;
// NOTE: we allow NULL == ppSecurityDescriptor, see SetSecurity
if (0 == RequestedInformation )
{
ASSERT(FALSE);
return E_INVALIDARG;
}
if (fDefault)
return E_NOTIMPL;
if ( NULL != ppSecurityDescriptor )
*ppSecurityDescriptor = NULL;
if ( !g_SmbDLL.LoadFunctionPointers() )
{
ASSERT(FALSE); // NETAPI32 isn't installed?
return S_OK;
}
SMBFreeData( (PVOID*)&m_pvolumeinfo );
NET_API_STATUS dwErr = ((SHAREGETINFOPROC)g_SmbDLL[SMB_SHARE_GET_INFO])(
QueryMachineName(),
QueryShareName(),
502,
(LPBYTE*)&m_pvolumeinfo );
if (NERR_Success != dwErr)
{
return HRESULT_FROM_WIN32(dwErr);
}
ASSERT(NULL != m_pvolumeinfo);
if ( NULL == ppSecurityDescriptor )
return S_OK;
if (NULL == m_pvolumeinfo->shi502_security_descriptor)
{
if (NULL == m_pDefaultDescriptor)
{
HRESULT hr = NewDefaultDescriptor(
&m_pDefaultDescriptor,
RequestedInformation );
if ( !SUCCEEDED(hr) )
return hr;
}
m_pvolumeinfo->shi502_security_descriptor = m_pDefaultDescriptor;
}
ASSERT( NULL != m_pvolumeinfo->shi502_security_descriptor );
// We have to pass back a LocalAlloc'ed copy of the SD
return MakeSelfRelativeCopy(
m_pvolumeinfo->shi502_security_descriptor,
ppSecurityDescriptor );
MFC_CATCH;
}
STDMETHODIMP CSMBSecurityInformation::SetSecurity (
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor )
{
MFC_TRY;
if ( !g_SmbDLL.LoadFunctionPointers() )
{
ASSERT(FALSE); // NETAPI32 isn't installed?
return S_OK;
}
// First get the current settings
// We call GetSecurity with NULL == ppSecurityDescriptor, this indicates to
// GetSecurity that it should refresh the shi502 structure but not return
// a copy of an actual security descriptor.
HRESULT hr = GetSecurity( SecurityInformation, NULL, FALSE );
if ( FAILED(hr) )
return hr;
// Now set the new values
m_pvolumeinfo->shi502_security_descriptor = pSecurityDescriptor;
NET_API_STATUS dwErr = ((SHARESETINFOPROC)g_SmbDLL[SMB_SHARE_SET_INFO])(
QueryMachineName(),
QueryShareName(),
502,
(LPBYTE)m_pvolumeinfo,
NULL );
if (NERR_Success != dwErr)
{
return HRESULT_FROM_WIN32(dwErr);
}
return S_OK;
MFC_CATCH;
}
//
// helper functions
//
HRESULT GetDCInfo(
IN LPCTSTR ptchServerName,
OUT CString& strDCName
)
/*
Function: retrieve DC name of the domain the server belongs to.
Return:
S_OK: if succeeded
others: if server does not belong to a domain, or error occurred
*/
{
strDCName.Empty();
//
// get domain name of the server
//
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBuffer = NULL;
DWORD dwErr = DsRoleGetPrimaryDomainInformation(
ptchServerName,
DsRolePrimaryDomainInfoBasic,
(PBYTE *)&pBuffer);
if (ERROR_SUCCESS != dwErr)
return HRESULT_FROM_WIN32(dwErr);
CString strDomainName = (pBuffer->DomainNameDns ? pBuffer->DomainNameDns : pBuffer->DomainNameFlat);
DsRoleFreeMemory(pBuffer);
if (!strDomainName)
return E_OUTOFMEMORY;
if (strDomainName.IsEmpty())
return S_FALSE; // server does not belong to a domain
//
// In case the DNS name is in absolute form, remove the ending dot
//
int nlen = strDomainName.GetLength();
if ( _T('.') == strDomainName[nlen - 1] )
strDomainName.SetAt(nlen - 1, _T('\0'));
//
// get DC name of that domain
//
PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
dwErr = DsGetDcName(
NULL, // Run on Current Server.
strDomainName,
NULL,
NULL,
DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_DNS_NAME,
&pDCInfo
);
if (ERROR_SUCCESS != dwErr)
return HRESULT_FROM_WIN32(dwErr);
if ( _T('\\') == *(pDCInfo->DomainControllerName) )
strDCName = pDCInfo->DomainControllerName + 2;
else
strDCName = pDCInfo->DomainControllerName;
NetApiBufferFree(pDCInfo);
if (!strDCName)
return E_OUTOFMEMORY;
return S_OK;
}
HRESULT GetADsPathOfComputerObject(
IN LPCTSTR ptchServerName,
OUT CString& strADsPath,
OUT CString& strDCName
)
/*
Function: retrieve LDAP://<DC>/<FQDN of computer object>.
Return:
S_OK: if succeeded
others: if server does not belong to a domain, or error occurred
*/
{
//
// Get NT4 account name for this server
//
PWKSTA_INFO_100 wki100 = NULL;
NET_API_STATUS NetStatus = NetWkstaGetInfo((LPTSTR)ptchServerName, 100, (LPBYTE *)&wki100 );
if (ERROR_SUCCESS != NetStatus)
return HRESULT_FROM_WIN32(NetStatus);
HRESULT hr = S_FALSE;
CString strNT4Name;
if (wki100->wki100_langroup)
{
strNT4Name = wki100->wki100_langroup;
strNT4Name += _T("\\");
strNT4Name += wki100->wki100_computername;
strNT4Name += _T("$");
hr = S_OK;
}
NetApiBufferFree((LPBYTE)wki100);
if (S_OK != hr)
return hr;
//
// get DC name of the server's domain
//
hr = GetDCInfo(ptchServerName, strDCName);
if (S_OK != hr)
return hr;
//
// get computerDN
//
CComPtr<IADsNameTranslate> spiADsNameTranslate;
hr = CoCreateInstance(CLSID_NameTranslate, NULL, CLSCTX_INPROC_SERVER, IID_IADsNameTranslate, (void **)&spiADsNameTranslate);
if (FAILED(hr)) return hr;
hr = spiADsNameTranslate->Init(ADS_NAME_INITTYPE_SERVER, (LPTSTR)(LPCTSTR)strDCName);
if (FAILED(hr)) return hr;
hr = spiADsNameTranslate->Set(ADS_NAME_TYPE_NT4, (LPTSTR)(LPCTSTR)strNT4Name);
if (FAILED(hr)) return hr;
CComBSTR sbstrComputerDN;
hr = spiADsNameTranslate->Get(ADS_NAME_TYPE_1779, &sbstrComputerDN);
if (FAILED(hr)) return hr;
strADsPath = _T("LDAP://");
strADsPath += strDCName;
strADsPath += _T("/");
strADsPath += sbstrComputerDN;
return hr;
}
HRESULT CheckSchemaVersion(IN LPCTSTR ptchServerName)
/*
Function: check if the schema allows volume object be created as child of computer object.
Return:
S_OK: yes, it's the new schema, it allows
S_FALSE: it doesn't allow, or the server doesn't belong to a domain at all
others: error occurred
*/
{
HRESULT hr = S_OK;
//
// get DC name of the server's domain
//
CString strDCName;
hr = GetDCInfo(ptchServerName, strDCName);
if (S_OK != hr)
return hr;
//
// Get schema naming context from the rootDSE.
//
CComPtr<IADs> spiRootADs;
hr = ADsGetObject(_T("LDAP://rootDSE"),
IID_IADs,
(void**)&spiRootADs);
if (SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
hr = spiRootADs->Get(_T("schemaNamingContext"), &var);
if (FAILED(hr)) return hr;
//
// get LDAP path to the schema of Connection-Point class
//
CString strADsPath = _T("LDAP://");
strADsPath += strDCName;
strADsPath += _T("/CN=Connection-Point,");
strADsPath += V_BSTR(&var);
VariantClear(&var);
CComPtr<IADs> spiADs;
hr = ADsGetObject(strADsPath, IID_IADs, (void**)&spiADs);
if (FAILED(hr)) return hr;
VariantInit(&var);
hr = spiADs->Get(_T("systemPossSuperiors"), &var);
if (SUCCEEDED(hr))
{
hr = IsValueInVarArray(&var, _T("computer"));
VariantClear(&var);
} else if (E_ADS_PROPERTY_NOT_FOUND == hr)
hr = S_FALSE;
}
return hr;
}
BOOL CheckPolicyOnSharePublish(IN LPCTSTR ptchShareName)
{
if (!ptchShareName && !*ptchShareName)
return FALSE; // invalid share name
//
// no publish page on hidden shares
//
int len = lstrlen(ptchShareName);
if (_T('$') == *(ptchShareName + len - 1))
return FALSE;
//
// no publish page on system shares
//
int n = sizeof(g_pszSystemShares) / sizeof(LPCTSTR);
for (int i = 0; i < n; i++)
{
if (!lstrcmpi(ptchShareName, g_pszSystemShares[i]))
return FALSE;
}
//
// check group policy
//
BOOL bAddPublishPage = TRUE; // by default, we display the share publish page
HKEY hKey = NULL;
DWORD dwType = 0;
DWORD dwData = 0;
DWORD cbData = sizeof(dwData);
LONG lErr = RegOpenKeyEx(
HKEY_CURRENT_USER,
_T("Software\\Policies\\Microsoft\\Windows NT\\SharedFolders"),
0,
KEY_QUERY_VALUE,
&hKey);
if (ERROR_SUCCESS == lErr)
{
lErr = RegQueryValueEx(hKey, _T("PublishSharedFolders"), 0, &dwType, (LPBYTE)&dwData, &cbData);
if (ERROR_SUCCESS == lErr &&
REG_DWORD == dwType &&
0 == dwData) // policy is disabled
bAddPublishPage = FALSE;
RegCloseKey(hKey);
}
return bAddPublishPage;
}
void mystrtok(
IN LPCTSTR pszString,
IN OUT int* pnIndex, // start from 0
IN LPCTSTR pszCharSet,
OUT CString& strToken
)
{
strToken.Empty();
if (!pszString || !*pszString ||
!pszCharSet || !pnIndex ||
*pnIndex >= lstrlen(pszString))
{
return;
}
TCHAR *ptchStart = (PTSTR)pszString + *pnIndex;
if (!*pszCharSet)
{
strToken = ptchStart;
return;
}
//
// move p to the 1st char of the token
//
TCHAR *p = ptchStart;
while (*p)
{
if (_tcschr(pszCharSet, *p))
p++;
else
break;
}
ptchStart = p; // adjust ptchStart to point at the 1st char of the token
//
// move p to the char after the last char of the token
//
while (*p)
{
if (_tcschr(pszCharSet, *p))
break;
else
p++;
}
//
// ptchStart: points at the 1st char of the token
// p: points at the char after the last char of the token
//
if (ptchStart != p)
{
strToken = CString(ptchStart, (int)(p - ptchStart));
*pnIndex = (int)(p - pszString);
}
// return
}
//
// write a semi-colon separated string into a VARIANT
//
HRESULT PutMultiValuesIntoVarArray(
IN LPCTSTR pszValues,
OUT VARIANT* pVar
)
{
if (!pVar || !pszValues || !*pszValues)
return E_INVALIDARG;
//
// get count of items
//
int nCount = 0;
int nIndex = 0;
CString strToken;
mystrtok(pszValues, &nIndex, _T(";"), strToken);
while (!strToken.IsEmpty())
{
nCount++;
mystrtok(pszValues, &nIndex, _T(";"), strToken);
}
if (!nCount)
return E_INVALIDARG;
//
// create an array of variants to hold all the data
//
SAFEARRAYBOUND bounds = {nCount, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
nCount = 0;
nIndex = 0;
mystrtok(pszValues, &nIndex, _T(";"), strToken);
while (!strToken.IsEmpty())
{
strToken.TrimLeft();
strToken.TrimRight();
VariantInit(&(varArray[nCount]));
varArray[nCount].vt = VT_BSTR;
varArray[nCount].bstrVal = SysAllocString(strToken);
nCount++;
mystrtok(pszValues, &nIndex, _T(";"), strToken);
}
SafeArrayUnaccessData(psa);
//
// return the variant array
//
VariantInit(pVar);
pVar->vt = VT_ARRAY | VT_VARIANT;
pVar->parray = psa;
return S_OK;
}
//
// read a multi-valued VARIANT into a semicolon separated string
//
HRESULT GetSingleOrMultiValuesFromVarArray(
IN VARIANT* pVar,
OUT CString& strValues
)
{
strValues.Empty();
if (V_VT(pVar) != VT_BSTR &&
V_VT(pVar) != (VT_ARRAY | VT_VARIANT))
return E_INVALIDARG;
if (V_VT(pVar) == VT_BSTR)
{
strValues = V_BSTR(pVar);
} else
{
LONG lstart, lend;
SAFEARRAY *sa = V_ARRAY(pVar);
VARIANT varItem;
SafeArrayGetLBound(sa, 1, &lstart);
SafeArrayGetUBound(sa, 1, &lend);
VariantInit(&varItem);
for (LONG i = lstart; i <= lend; i++)
{
SafeArrayGetElement(sa, &i, &varItem);
if (!strValues.IsEmpty())
strValues += _T(";");
strValues += V_BSTR(&varItem);
VariantClear(&varItem);
}
}
return S_OK;
}
HRESULT IsValueInVarArray(
IN VARIANT* pVar,
IN LPCTSTR ptchValue
)
{
if (V_VT(pVar) != VT_BSTR &&
V_VT(pVar) != (VT_ARRAY | VT_VARIANT))
return E_INVALIDARG;
HRESULT hr = S_FALSE;
if (V_VT(pVar) == VT_BSTR)
{
if (!lstrcmpi(ptchValue, V_BSTR(pVar)))
hr = S_OK;
} else
{
LONG lstart, lend;
SAFEARRAY *sa = V_ARRAY(pVar);
VARIANT varItem;
SafeArrayGetLBound(sa, 1, &lstart);
SafeArrayGetUBound(sa, 1, &lend);
VariantInit(&varItem);
for (LONG i = lstart; (i <= lend) && (S_FALSE == hr); i++)
{
SafeArrayGetElement(sa, &i, &varItem);
if (!lstrcmpi(ptchValue, V_BSTR(&varItem)))
hr = S_OK;
VariantClear(&varItem);
}
}
return hr;
}
/*
We block the operation if:
A) You are monitoring a remote computer, not the local one
B) The session username matches the currently logged on user
C) The number of files opened on the server is greater than 0
D) The client name is either one of our IP addresses or our ComputerName.
*/
BOOL BlockRemoteAdminSession(
IN PCTSTR i_pszTargetServer,
IN PCTSTR i_pszClientName,
IN PCTSTR i_pszUserName,
IN DWORD i_dwNumOpenSessions
)
{
if (!i_pszClientName || !i_pszUserName)
return FALSE;
// if we're monitoring the local machine
if (!i_pszTargetServer || !*i_pszTargetServer)
return FALSE;
// if number of sessions is not greater than 0
if (0 == i_dwNumOpenSessions)
return FALSE;
// get username, return if user name doesn't match
TCHAR szUser[UNLEN+1] = _T("");
DWORD dwSize = UNLEN+1;
GetUserName(szUser, &dwSize);
if (lstrcmpi(szUser, i_pszUserName))
return FALSE;
// compare with local computer's name
TCHAR tszComputer[MAX_COMPUTERNAME_LENGTH + 1] = _T("");
dwSize = MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(tszComputer, &dwSize);
BOOL bMatch = (0 == lstrcmpi(tszComputer, i_pszClientName));
// compare with each IP address of the local computer
if (!bMatch)
{
// convert WCHAR to char
int iBytes = 0;
char szComputer[MAX_COMPUTERNAME_LENGTH + 1] = "";
char szClientName[MAX_COMPUTERNAME_LENGTH + 1] = "";
#if defined UNICODE
iBytes = MAX_COMPUTERNAME_LENGTH + 1;
WideCharToMultiByte(CP_ACP, 0, tszComputer, -1, szComputer, iBytes, NULL, NULL);
iBytes = MAX_COMPUTERNAME_LENGTH + 1;
WideCharToMultiByte(CP_ACP, 0, i_pszClientName, -1, szClientName, iBytes, NULL, NULL);
#else
lstrcpy(szComputer, tszComputer);
lstrcpy(szClientName, i_pszClientName);
#endif
struct hostent *pHostEnt = gethostbyname(szComputer);
if (pHostEnt)
{
struct in_addr IPAddr = {0};
PSTR pszIP = NULL;
int i = 0;
while (pHostEnt->h_addr_list[i])
{
memcpy(&IPAddr, pHostEnt->h_addr_list[i++], pHostEnt->h_length);
pszIP = inet_ntoa(IPAddr);
if (!_stricmp(pszIP, szClientName))
{
bMatch = TRUE;
break;
}
}
}
}
// keep this session for remote admin purpose
if (bMatch)
DoErrMsgBox(GetActiveWindow(), MB_OK, 0, IDS_POPUP_REMOTEADMINSESSION);
return bMatch;
}
/*
We block the operation if:
A) You are monitoring a remote computer, not the local one
B) The openfile pathname matches \PIPE\srvsvc or \PIPE\MacFile
C) The openfile username matches the currently logged on user
*/
BOOL BlockRemoteAdminFile(
IN PCTSTR i_pszTargetServer,
IN PCTSTR i_pszPathName,
IN PCTSTR i_pszUserName
)
{
if (!i_pszPathName || !i_pszUserName)
return FALSE;
// if we're monitoring the local machine
if (!i_pszTargetServer || !*i_pszTargetServer)
return FALSE;
if (lstrcmpi(_T("\\PIPE\\srvsvc"), i_pszPathName) && lstrcmpi(_T("\\PIPE\\MacFile"), i_pszPathName))
return FALSE;
// get username, return if user name doesn't match
TCHAR szUser[UNLEN+1] = _T("");
DWORD dwSize = UNLEN+1;
GetUserName(szUser, &dwSize);
if (lstrcmpi(szUser, i_pszUserName))
return FALSE;
// this is the admin named pipe, keep it for remote admin purpose
DoErrMsgBox(GetActiveWindow(), MB_OK, 0, IDS_POPUP_REMOTEADMINFILE, i_pszPathName);
return TRUE;
}
void TranslateIPToComputerName(LPCTSTR ptszIP, CString& strName)
{
int iBytes = 0;
char szIP[MAX_PATH] = "";
#if defined UNICODE
iBytes = MAX_PATH;
WideCharToMultiByte(CP_ACP, 0, ptszIP, -1, szIP, iBytes, NULL, NULL);
#else
lstrcpy(szIP, ptszIP);
#endif
strName = ptszIP;
ULONG inaddr = inet_addr(szIP);
if (INADDR_NONE != inaddr)
{
struct hostent *pHostEnt = gethostbyaddr((char *)&inaddr, sizeof(inaddr), AF_INET);
if (pHostEnt)
{
#if defined UNICODE
DWORD cb = MultiByteToWideChar(CP_ACP, 0, pHostEnt->h_name, -1, NULL, 0);
strName = CString(_T('0'), cb);
LPTSTR ptszName = strName.GetBuffer(cb);
MultiByteToWideChar(CP_ACP, 0, pHostEnt->h_name, -1, ptszName, cb);
strName.ReleaseBuffer();
#else
strName = pHostEnt->h_name;
#endif
}
}
}