You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
421 lines
10 KiB
421 lines
10 KiB
#include "stdafx.h"
|
|
#include "common.h"
|
|
#include "iisobj.h"
|
|
#include "util.h"
|
|
#include <activeds.h>
|
|
#include <lmerr.h>
|
|
#include <Winsock2.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
void DumpFriendlyName(CIISObject * pObj)
|
|
{
|
|
if (pObj)
|
|
{
|
|
CString strGUIDName;
|
|
GUID * MyGUID = (GUID*) pObj->GetNodeType();
|
|
GetFriendlyGuidName(*MyGUID,strGUIDName);
|
|
TRACEEOL("CIISObject=" << strGUIDName);
|
|
}
|
|
}
|
|
|
|
HRESULT DumpAllScopeItems(CComPtr<IConsoleNameSpace> pConsoleNameSpace, IN HSCOPEITEM hParent, IN int iTreeLevel)
|
|
{
|
|
HSCOPEITEM hChildItem = NULL;
|
|
CIISObject * pItem = NULL;
|
|
LONG_PTR cookie = NULL;
|
|
|
|
if (0 == iTreeLevel)
|
|
{
|
|
TRACEEOL("==============");
|
|
TRACEEOL("[\\]" << hParent);
|
|
}
|
|
iTreeLevel++;
|
|
|
|
HRESULT hr = pConsoleNameSpace->GetChildItem(hParent, &hChildItem, &cookie);
|
|
while(SUCCEEDED(hr) && hChildItem)
|
|
{
|
|
//
|
|
// The cookie is really the IISObject, which is what we stuff
|
|
// in the lparam.
|
|
//
|
|
pItem = (CIISObject *)cookie;
|
|
if (pItem)
|
|
{
|
|
//
|
|
// Recursively dump every object
|
|
//
|
|
CString strGUIDName;GUID * MyGUID = (GUID*) pItem->GetNodeType();GetFriendlyGuidName(*MyGUID,strGUIDName);
|
|
for (int i = 0; i < iTreeLevel; ++i)
|
|
{
|
|
TRACEOUT("-");
|
|
}
|
|
TRACEEOL("[" << strGUIDName << "] (parent=" << hParent << " )(" << hChildItem << ")");
|
|
|
|
// dump all it's children
|
|
DumpAllScopeItems(pConsoleNameSpace,hChildItem,iTreeLevel + 1);
|
|
}
|
|
|
|
//
|
|
// Advance to next child of same parent
|
|
//
|
|
hr = pConsoleNameSpace->GetNextItem(hChildItem, &hChildItem, &cookie);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT DumpAllResultItems(IResultData * pResultData)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RESULTDATAITEM rdi;
|
|
CIISObject * pItem = NULL;
|
|
ZeroMemory(&rdi, sizeof(rdi));
|
|
|
|
rdi.mask = RDI_PARAM | RDI_STATE;
|
|
rdi.nIndex = -1; // -1 to start at first item
|
|
do
|
|
{
|
|
rdi.lParam = 0;
|
|
|
|
// this could AV right here if pResultData is invalid
|
|
hr = pResultData->GetNextItem(&rdi);
|
|
if (hr != S_OK)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The cookie is really the IISObject, which is what we stuff
|
|
// in the lparam.
|
|
//
|
|
pItem = (CIISObject *)rdi.lParam;
|
|
ASSERT_PTR(pItem);
|
|
|
|
DumpFriendlyName(pItem);
|
|
|
|
//
|
|
// Advance to next child of same parent
|
|
//
|
|
} while (SUCCEEDED(hr) && -1 != rdi.nIndex);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// IsValidDomainUser
|
|
// Check if a domain user like redmond\jonsmith specified in szDomainUser
|
|
// is valid or not. returns S_FALSE if it is invalid, S_OK for valid user.
|
|
//
|
|
// szFullName ---- To return the user's full name
|
|
// cch ---- count of characters pointed to by szFullName
|
|
//
|
|
// if szFullName is NULL or cch is zero, no full name is returned
|
|
//
|
|
const TCHAR gszUserDNFmt[] = _T("WinNT://%s/%s,user");
|
|
|
|
HRESULT
|
|
IsValidDomainUser(
|
|
LPCTSTR szDomainUser,
|
|
LPTSTR szFullName,
|
|
DWORD cch)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szDN[256];
|
|
TCHAR szDomain[256];
|
|
LPTSTR szSep;
|
|
LPCTSTR szUser;
|
|
DWORD dw;
|
|
|
|
IADsUser * pUser = NULL;
|
|
BSTR bstrFullName = NULL;
|
|
|
|
// Sanity check
|
|
if (szDomainUser == NULL || szDomainUser[0] == 0)
|
|
{
|
|
hr = S_FALSE;
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// Construct the user DN as <WINNT://domain/user,user>
|
|
//
|
|
szSep = _tcschr (szDomainUser, TEXT('\\'));
|
|
if (szSep == NULL)
|
|
{
|
|
// No '\' is given, assume a local user ,domain is local computer
|
|
szUser = szDomainUser;
|
|
dw = sizeof(szDomain)/sizeof(TCHAR);
|
|
if (GetComputerName (szDomain, &dw) == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32 (GetLastError ());
|
|
goto ExitHere;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// assume invalid domain name if longer than 255
|
|
if (szSep - szDomainUser >= sizeof(szDomain)/sizeof(TCHAR))
|
|
{
|
|
hr = S_FALSE;
|
|
goto ExitHere;
|
|
}
|
|
_tcsncpy (szDomain, szDomainUser, szSep - szDomainUser);
|
|
szDomain[szSep - szDomainUser] = 0;
|
|
szUser = szSep + 1;
|
|
}
|
|
if (_tcslen (gszUserDNFmt) + _tcslen (szDomain) + _tcslen (szUser) >
|
|
sizeof(szDN) / sizeof(TCHAR))
|
|
{
|
|
hr = S_FALSE;
|
|
goto ExitHere;
|
|
}
|
|
wsprintf (szDN, gszUserDNFmt, szDomain, szUser);
|
|
|
|
//
|
|
// Try to bind to the user object
|
|
//
|
|
hr = ADsGetObject (szDN, IID_IADsUser, (void **)&pUser);
|
|
if (FAILED(hr))
|
|
{
|
|
if (hr == E_ADS_INVALID_USER_OBJECT ||
|
|
hr == E_ADS_UNKNOWN_OBJECT ||
|
|
hr == E_ADS_BAD_PATHNAME ||
|
|
HRESULT_CODE(hr) == NERR_UserNotFound)
|
|
{
|
|
hr = S_FALSE; // The user does not exist
|
|
}
|
|
goto ExitHere;
|
|
}
|
|
|
|
//
|
|
// If the user exists, get its full name
|
|
//
|
|
if (cch > 0)
|
|
{
|
|
hr = pUser->get_FullName (&bstrFullName);
|
|
szFullName[0] = 0;
|
|
if (hr == S_OK)
|
|
{
|
|
_tcsncpy (szFullName, bstrFullName, cch);
|
|
szFullName[cch - 1] = 0;
|
|
}
|
|
}
|
|
|
|
ExitHere:
|
|
if (pUser)
|
|
{
|
|
pUser->Release();
|
|
}
|
|
if (bstrFullName)
|
|
{
|
|
SysFreeString (bstrFullName);
|
|
}
|
|
return hr;
|
|
}
|
|
#if 0
|
|
DWORD VerifyPassword(WCHAR * sUserName, WCHAR * sPassword, WCHAR * sDomain)
|
|
{
|
|
CWaitCursor wait;
|
|
DWORD retVal = 0;
|
|
CString strDomainUserName;
|
|
CString localIPC;
|
|
WCHAR localMachine[MAX_PATH];
|
|
WCHAR * computer = NULL;
|
|
DWORD len = DIM(localMachine);
|
|
NETRESOURCE nr;
|
|
CString error=L"no error";
|
|
USER_INFO_3 * pInfo = NULL;
|
|
NET_API_STATUS rc;
|
|
|
|
memset(&nr,0,(sizeof nr));
|
|
|
|
if ( ! gbNeedToVerify )
|
|
return 0;
|
|
|
|
/* see if this domain exists and get a DC name */
|
|
//get the domain controller name
|
|
if (!GetDomainDCName(sDomain,&computer))
|
|
return ERROR_LOGON_FAILURE;
|
|
|
|
/* see if this user is a member of the given domain */
|
|
rc = NetUserGetInfo(computer, sUserName, 3, (LPBYTE *)&pInfo);
|
|
NetApiBufferFree(computer);
|
|
if (rc != NERR_Success)
|
|
return ERROR_LOGON_FAILURE;
|
|
|
|
NetApiBufferFree(pInfo);
|
|
|
|
/* see if the password allows us to connect to a local resource */
|
|
strDomainUserName.Format(L"%s\\%s",sDomain,sUserName);
|
|
// get the name of the local machine
|
|
if ( GetComputerName(localMachine,&len) )
|
|
{
|
|
|
|
localIPC.Format(L"\\\\%s",localMachine);
|
|
nr.dwType = RESOURCETYPE_ANY;
|
|
nr.lpRemoteName = localIPC.GetBuffer(0);
|
|
retVal = WNetAddConnection2(&nr,sPassword,strDomainUserName,0);
|
|
error.Format(L"WNetAddConnection returned%u",retVal);
|
|
if ( ! retVal )
|
|
{
|
|
error.Format(L"WNetAddConnection2 succeeded");
|
|
|
|
retVal = WNetCancelConnection2(localIPC.GetBuffer(0),0,TRUE);
|
|
if ( retVal )
|
|
retVal = 0;
|
|
}
|
|
else if ( retVal == ERROR_SESSION_CREDENTIAL_CONFLICT )
|
|
{
|
|
|
|
// skip the password check in this case
|
|
retVal = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retVal = GetLastError();
|
|
|
|
}
|
|
return retVal;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// IsConnectingToOwnAddress
|
|
// return true if this is an attempt to reconnect to our
|
|
// own address.
|
|
//
|
|
BOOL IsConnectingToOwnAddress(u_long connectAddr)
|
|
{
|
|
//32-bit form of 127.0.0.1 addr
|
|
#define LOOPBACK_ADDR ((u_long)0x0100007f)
|
|
|
|
//
|
|
// First the quick check for localhost/127.0.0.1
|
|
//
|
|
if( LOOPBACK_ADDR == connectAddr)
|
|
{
|
|
TRACEEOLID("Connecting to loopback address...");
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// More extensive check, i.e resolve the local hostname
|
|
//
|
|
char hostname[(512+1)*sizeof(TCHAR)];
|
|
int err;
|
|
int j;
|
|
struct hostent* phostent;
|
|
|
|
err=gethostname(hostname, sizeof(hostname));
|
|
if (err == 0)
|
|
{
|
|
if ((phostent = gethostbyname(hostname)) !=NULL)
|
|
{
|
|
switch (phostent->h_addrtype)
|
|
{
|
|
case AF_INET:
|
|
j=0;
|
|
while (phostent->h_addr_list[j] != NULL)
|
|
{
|
|
if(!memcmp(&connectAddr,
|
|
phostent->h_addr_list[j],
|
|
sizeof(u_long)))
|
|
{
|
|
TRACEEOLID("Connecting to same IP as the local machine...");
|
|
return TRUE;
|
|
}
|
|
j++;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// IsLocalHost
|
|
//
|
|
// Arguments : szHostName (name of computer to check)
|
|
// pbIsHost (set to TRUE if host name matches local computer name)
|
|
//
|
|
// Returns : FALSE on windows socket error
|
|
//
|
|
// Purpose : check if host name matches this (local) computer name
|
|
//-----------------------------------------------------------------------------
|
|
#define WS_VERSION_REQD 0x0101
|
|
BOOL IsLocalHost(LPCTSTR szHostName,BOOL* pbIsHost)
|
|
{
|
|
const char * lpszAnsiHostName = NULL;
|
|
|
|
*pbIsHost = FALSE;
|
|
BOOL bSuccess = TRUE;
|
|
hostent* phostent = NULL;
|
|
|
|
// init winsock (reference counted - can init any number of times)
|
|
//
|
|
WSADATA wsaData;
|
|
int err = WSAStartup(WS_VERSION_REQD, &wsaData);
|
|
if (err)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// convert to ansi
|
|
//
|
|
#ifdef UNICODE
|
|
CHAR szAnsi[MAX_PATH];
|
|
if (::WideCharToMultiByte(CP_ACP, 0L, szHostName, -1, szAnsi, sizeof(szAnsi), NULL, NULL) > 0)
|
|
{
|
|
lpszAnsiHostName = szAnsi;
|
|
}
|
|
#else
|
|
lpszAnsiHostName = szHostName;
|
|
#endif // UNICODE
|
|
|
|
if (NULL == lpszAnsiHostName)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// get dns name for the given hostname
|
|
//
|
|
unsigned long addr = inet_addr(lpszAnsiHostName);
|
|
|
|
if (addr == INADDR_NONE)
|
|
phostent = gethostbyname(lpszAnsiHostName);
|
|
else
|
|
phostent = gethostbyaddr((char*)&addr,4, AF_INET);
|
|
|
|
if (phostent == NULL)
|
|
{
|
|
bSuccess = FALSE;
|
|
goto cleanup;
|
|
}
|
|
else
|
|
{
|
|
IN_ADDR hostaddr;
|
|
memcpy(&hostaddr,phostent->h_addr,sizeof(hostaddr));
|
|
*pbIsHost = IsConnectingToOwnAddress(hostaddr.s_addr);
|
|
bSuccess = TRUE;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
err = WSACleanup();
|
|
if (err != 0)
|
|
{
|
|
bSuccess = FALSE;
|
|
}
|
|
return bSuccess;
|
|
}
|