2230 lines
58 KiB
C++
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
|
|
}
|
|
}
|
|
} |