746 lines
17 KiB
C++
746 lines
17 KiB
C++
|
#include <windows.h>
|
||
|
#include "admcmn.h"
|
||
|
|
||
|
// For Net* calls:
|
||
|
|
||
|
#include <lmaccess.h>
|
||
|
#include <lmwksta.h>
|
||
|
#include <lmapibuf.h>
|
||
|
#include <lmerr.h>
|
||
|
|
||
|
// For CAddr:: calls:
|
||
|
|
||
|
#include "cpool.h"
|
||
|
#include "abook.h"
|
||
|
#include "abtype.h"
|
||
|
#include "address.hxx"
|
||
|
|
||
|
#include "webhlpr.h"
|
||
|
|
||
|
static HRESULT GetDCName (
|
||
|
LPCWSTR wszServer,
|
||
|
LPCWSTR wszDomain,
|
||
|
LPWSTR * pwszDC
|
||
|
);
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
// Taken from smtp/shash.hxx
|
||
|
#define TABLE_SIZE 241
|
||
|
|
||
|
static unsigned long ElfHash (const unsigned char * UserName);
|
||
|
|
||
|
static HRESULT RecursiveDeleteDirectory (
|
||
|
LPCWSTR wszPath
|
||
|
);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Exported functions:
|
||
|
//
|
||
|
|
||
|
HRESULT
|
||
|
EnumerateTrustedDomains (
|
||
|
LPCWSTR wszComputer,
|
||
|
LPWSTR * pmszDomains
|
||
|
)
|
||
|
{
|
||
|
_ASSERT ( wszComputer && *wszComputer );
|
||
|
_ASSERT ( pmszDomains );
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD dwErr = NOERROR;
|
||
|
LPWSTR mszDomains = NULL;
|
||
|
DWORD cchDomains = 0;
|
||
|
DWORD cchLocalDomain = 0;
|
||
|
LPWSTR wszPrimaryDomain = NULL;
|
||
|
DWORD cchPrimaryDomain = 0;
|
||
|
LPWSTR wszCurrent;
|
||
|
LPWSTR mszResult = NULL;
|
||
|
|
||
|
*pmszDomains = NULL;
|
||
|
|
||
|
//
|
||
|
// Get a list of the trusted 1st tier domains:
|
||
|
//
|
||
|
|
||
|
dwErr = NetEnumerateTrustedDomains (
|
||
|
const_cast <LPWSTR> (wszComputer),
|
||
|
&mszDomains
|
||
|
);
|
||
|
if ( dwErr != NOERROR ) {
|
||
|
//
|
||
|
// This didn't work, but we should always add the primary
|
||
|
// domain & computer name. Make an empty multisz to signify
|
||
|
// no trusted domains.
|
||
|
//
|
||
|
|
||
|
dwErr = NetApiBufferAllocate (
|
||
|
2 * sizeof ( WCHAR ),
|
||
|
(LPVOID *) &mszDomains
|
||
|
);
|
||
|
if ( dwErr != NOERROR ) {
|
||
|
BAIL_WITH_FAILURE ( hr, HRESULT_FROM_WIN32 ( dwErr ) );
|
||
|
}
|
||
|
|
||
|
mszDomains[0] = NULL;
|
||
|
mszDomains[1] = NULL;
|
||
|
}
|
||
|
|
||
|
_ASSERT ( mszDomains );
|
||
|
if ( mszDomains == NULL ) {
|
||
|
BAIL_WITH_FAILURE ( hr, E_UNEXPECTED );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check for an empty domain list:
|
||
|
//
|
||
|
|
||
|
if ( mszDomains[0] == NULL && mszDomains[1] == NULL ) {
|
||
|
cchDomains = 2;
|
||
|
}
|
||
|
else {
|
||
|
wszCurrent = mszDomains;
|
||
|
if ( mszDomains[0] == _T('\0') &&
|
||
|
mszDomains[1] == _T('\0') ) {
|
||
|
}
|
||
|
while ( wszCurrent && *wszCurrent ) {
|
||
|
DWORD cchCurrent;
|
||
|
|
||
|
cchCurrent = lstrlen ( wszCurrent ) + 1;
|
||
|
cchDomains += cchCurrent;
|
||
|
wszCurrent += cchCurrent;
|
||
|
}
|
||
|
cchDomains += 1; // Terminating NULL
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add the local machine and primary domain:
|
||
|
//
|
||
|
|
||
|
hr = GetPrimaryDomain ( wszComputer, &wszPrimaryDomain );
|
||
|
BAIL_ON_FAILURE ( hr );
|
||
|
|
||
|
//
|
||
|
// PREFIX flagged this as something we need to fix. Easier to
|
||
|
// add check than to argue.
|
||
|
//
|
||
|
if ( !wszPrimaryDomain ) {
|
||
|
hr = E_FAIL;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
_ASSERT ( wszPrimaryDomain );
|
||
|
cchPrimaryDomain = lstrlen ( wszPrimaryDomain ) + 1;
|
||
|
|
||
|
if ( wszPrimaryDomain[0] != _T('\\') ||
|
||
|
wszPrimaryDomain[1] != _T('\\') ||
|
||
|
lstrcmpi ( wszPrimaryDomain + 2, wszComputer )
|
||
|
) {
|
||
|
|
||
|
//
|
||
|
// The primary domain isn't the local machine, so add the local
|
||
|
// machine to the list.
|
||
|
//
|
||
|
|
||
|
cchLocalDomain = lstrlen ( _T("\\\\") ) + lstrlen ( wszComputer ) + 1;
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// The primary domain is the local machine - no need to add it twice.
|
||
|
//
|
||
|
|
||
|
cchLocalDomain = 0;
|
||
|
}
|
||
|
|
||
|
mszResult = new WCHAR [ cchDomains + cchLocalDomain + cchPrimaryDomain];
|
||
|
if ( !mszResult ) {
|
||
|
BAIL_WITH_FAILURE ( hr, E_OUTOFMEMORY );
|
||
|
}
|
||
|
|
||
|
if ( cchLocalDomain ) {
|
||
|
wsprintf ( mszResult, _T("\\\\%s"), wszComputer );
|
||
|
StringToUpper ( mszResult );
|
||
|
}
|
||
|
|
||
|
wsprintf ( mszResult + cchLocalDomain, _T("%s"), wszPrimaryDomain );
|
||
|
StringToUpper ( mszResult + cchLocalDomain );
|
||
|
|
||
|
//
|
||
|
// Copy the rest of the domains in the domain list:
|
||
|
//
|
||
|
CopyMemory (
|
||
|
mszResult + cchLocalDomain + cchPrimaryDomain,
|
||
|
mszDomains,
|
||
|
cchDomains * sizeof (WCHAR)
|
||
|
);
|
||
|
|
||
|
*pmszDomains = mszResult;
|
||
|
|
||
|
Exit:
|
||
|
if ( wszPrimaryDomain ) {
|
||
|
delete [] wszPrimaryDomain;
|
||
|
}
|
||
|
if ( mszDomains ) {
|
||
|
NetApiBufferFree ( mszDomains );
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
GetPrimaryDomain (
|
||
|
LPCWSTR wszComputer,
|
||
|
LPWSTR * pwszPrimaryDomain
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD dwErr = NOERROR;
|
||
|
WKSTA_INFO_100 * pwkstaInfo = NULL;
|
||
|
LPWSTR wszLangroup = NULL;
|
||
|
|
||
|
*pwszPrimaryDomain = NULL;
|
||
|
|
||
|
//
|
||
|
// Get the workstation info to get the primary domain:
|
||
|
//
|
||
|
|
||
|
dwErr = NetWkstaGetInfo (
|
||
|
const_cast <LPWSTR> (wszComputer),
|
||
|
100,
|
||
|
(LPBYTE *)&pwkstaInfo
|
||
|
);
|
||
|
if ( dwErr != NOERROR ) {
|
||
|
BAIL_WITH_FAILURE ( hr, HRESULT_FROM_WIN32 ( dwErr ) );
|
||
|
}
|
||
|
|
||
|
_ASSERT ( pwkstaInfo );
|
||
|
|
||
|
wszLangroup = pwkstaInfo->wki100_langroup;
|
||
|
|
||
|
if ( wszLangroup && *wszLangroup ) {
|
||
|
*pwszPrimaryDomain = new WCHAR [ lstrlen ( wszLangroup ) + 1 ];
|
||
|
if ( !*pwszPrimaryDomain ) {
|
||
|
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
lstrcpy ( *pwszPrimaryDomain, wszLangroup );
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// If there is no primary domain, use the computer name prefixed
|
||
|
// by backslashes.
|
||
|
//
|
||
|
|
||
|
*pwszPrimaryDomain = new WCHAR [ 2 + lstrlen ( wszComputer ) + 1 ];
|
||
|
if ( !*pwszPrimaryDomain ) {
|
||
|
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
wsprintf ( *pwszPrimaryDomain, _T("\\\\%s"), wszComputer );
|
||
|
}
|
||
|
StringToUpper ( *pwszPrimaryDomain );
|
||
|
|
||
|
Exit:
|
||
|
if ( pwkstaInfo ) {
|
||
|
NetApiBufferFree ( pwkstaInfo );
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CheckNTAccount (
|
||
|
LPCWSTR wszComputer,
|
||
|
LPCWSTR wszUsername,
|
||
|
BOOL * pfExists
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD dwErr = NOERROR;
|
||
|
BOOL fFound;
|
||
|
BYTE sidUser [ MAX_PATH ];
|
||
|
DWORD cbSid = ARRAY_SIZE ( sidUser );
|
||
|
WCHAR wszDomain [ 512 ];
|
||
|
DWORD cchDomain = ARRAY_SIZE ( wszDomain );
|
||
|
SID_NAME_USE nuUser;
|
||
|
|
||
|
*pfExists = FALSE;
|
||
|
|
||
|
fFound = LookupAccountName (
|
||
|
wszComputer,
|
||
|
wszUsername,
|
||
|
&sidUser,
|
||
|
&cbSid,
|
||
|
wszDomain,
|
||
|
&cchDomain,
|
||
|
&nuUser
|
||
|
);
|
||
|
|
||
|
if ( !fFound ) {
|
||
|
dwErr = GetLastError ( );
|
||
|
|
||
|
//
|
||
|
// The not found error is ERROR_NONE_MAPPED:
|
||
|
//
|
||
|
if ( dwErr != ERROR_NONE_MAPPED ) {
|
||
|
BAIL_WITH_FAILURE ( hr, HRESULT_FROM_WIN32 ( dwErr ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*pfExists = fFound;
|
||
|
|
||
|
Exit:
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CreateNTAccount (
|
||
|
LPCWSTR wszComputer,
|
||
|
LPCWSTR wszDomain,
|
||
|
LPCWSTR wszUsername,
|
||
|
LPCWSTR wszPassword // = ""
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD dwErr = NOERROR;
|
||
|
DWORD dwParmErr = 0;
|
||
|
LPWSTR wszDC = NULL;
|
||
|
USER_INFO_3 UserInfo;
|
||
|
WCHAR wszNull[] = { 0 };
|
||
|
|
||
|
hr = GetDCName ( wszComputer, wszDomain, &wszDC );
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
ZeroMemory ( &UserInfo, sizeof ( UserInfo ) );
|
||
|
|
||
|
UserInfo.usri3_name = const_cast <LPWSTR> (wszUsername);
|
||
|
UserInfo.usri3_full_name = const_cast <LPWSTR> (wszUsername);
|
||
|
UserInfo.usri3_password = const_cast <LPWSTR> (wszPassword);
|
||
|
// UserInfo.usri3_password_age
|
||
|
UserInfo.usri3_priv = USER_PRIV_USER;
|
||
|
UserInfo.usri3_home_dir = wszNull;
|
||
|
UserInfo.usri3_comment = wszNull;
|
||
|
UserInfo.usri3_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
|
||
|
UserInfo.usri3_script_path = wszNull;
|
||
|
UserInfo.usri3_auth_flags = 0;
|
||
|
UserInfo.usri3_usr_comment = wszNull;
|
||
|
UserInfo.usri3_parms = wszNull;
|
||
|
UserInfo.usri3_workstations = wszNull;
|
||
|
// UserInfo.usri3_last_logon =;
|
||
|
// UserInfo.usri3_last_logoff =;
|
||
|
UserInfo.usri3_acct_expires = TIMEQ_FOREVER;
|
||
|
UserInfo.usri3_max_storage = USER_MAXSTORAGE_UNLIMITED;
|
||
|
// UserInfo.usri3_units_per_week =;
|
||
|
// UserInfo.usri3_logon_hours = NULL;
|
||
|
// UserInfo.usri3_bad_pw_count =;
|
||
|
// UserInfo.usri3_num_logons =;
|
||
|
UserInfo.usri3_logon_server = wszNull;
|
||
|
UserInfo.usri3_country_code = 0;
|
||
|
UserInfo.usri3_code_page = CP_ACP;
|
||
|
// UserInfo.usri3_user_id =;
|
||
|
UserInfo.usri3_primary_group_id = DOMAIN_GROUP_RID_USERS;
|
||
|
UserInfo.usri3_profile = wszNull;
|
||
|
UserInfo.usri3_home_dir_drive = wszNull;
|
||
|
UserInfo.usri3_password_expired = FALSE;
|
||
|
|
||
|
//
|
||
|
// Add the user:
|
||
|
//
|
||
|
|
||
|
dwErr = NetUserAdd (
|
||
|
wszDC,
|
||
|
3,
|
||
|
(LPBYTE) &UserInfo,
|
||
|
&dwParmErr
|
||
|
);
|
||
|
|
||
|
if ( dwErr != NOERROR ) {
|
||
|
// TRACE ( _T("Failed to add user: %d, parmerr = %d\r\n"), dwErr, dwParmErr );
|
||
|
BAIL_WITH_FAILURE ( hr, HRESULT_FROM_WIN32 ( dwErr ) );
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
//
|
||
|
// Attempt to add the user to the "USERS" group:
|
||
|
//
|
||
|
|
||
|
dwErr = NetGroupAddUser (
|
||
|
wszDC,
|
||
|
// (LPWSTR) (LPCWSTR) CString ( strDC + L"\\Users" ),
|
||
|
(LPWSTR) (LPCWSTR) strUsername
|
||
|
);
|
||
|
if ( dwErr != NOERROR ) {
|
||
|
TRACE ( _T("Couldn't add user to USERS group: %d\r\n"), dwErr );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
Exit:
|
||
|
delete wszDC;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
LPCWSTR StripBackslashesFromComputerName ( LPCWSTR wsz )
|
||
|
{
|
||
|
if ( wsz[0] == _T('\\') &&
|
||
|
wsz[1] == _T('\\') ) {
|
||
|
|
||
|
return wsz + 2;
|
||
|
}
|
||
|
else {
|
||
|
return wsz;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static LPWSTR DuplicateString ( LPCWSTR wsz )
|
||
|
{
|
||
|
LPWSTR wszResult;
|
||
|
|
||
|
_ASSERT ( wsz );
|
||
|
|
||
|
wszResult = new WCHAR [ lstrlen ( wsz ) + 1 ];
|
||
|
if ( wszResult ) {
|
||
|
lstrcpy ( wszResult, wsz );
|
||
|
}
|
||
|
|
||
|
return wszResult;
|
||
|
}
|
||
|
|
||
|
void StringToUpper ( LPWSTR wsz )
|
||
|
{
|
||
|
while ( *wsz ) {
|
||
|
*wsz = towupper ( *wsz );
|
||
|
wsz++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT GetDCName (
|
||
|
LPCWSTR wszServer,
|
||
|
LPCWSTR wszDomain,
|
||
|
LPWSTR * pwszDC
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD dwError = NOERROR;
|
||
|
LPWSTR wszServerCopy = NULL;
|
||
|
LPWSTR wszDomainCopy = NULL;
|
||
|
LPCWSTR wszPlainServer = NULL;
|
||
|
LPCWSTR wszPlainDomain = NULL;
|
||
|
LPWSTR wszDC = NULL;
|
||
|
|
||
|
if ( wszServer == NULL ) {
|
||
|
wszServer = _T("");
|
||
|
}
|
||
|
|
||
|
wszServerCopy = DuplicateString ( wszServer );
|
||
|
wszDomainCopy = DuplicateString ( wszDomain );
|
||
|
|
||
|
if ( !wszServerCopy || !wszDomainCopy ) {
|
||
|
BAIL_WITH_FAILURE ( hr, E_OUTOFMEMORY );
|
||
|
}
|
||
|
|
||
|
StringToUpper ( wszServerCopy );
|
||
|
StringToUpper ( wszDomainCopy );
|
||
|
|
||
|
wszPlainServer = StripBackslashesFromComputerName ( wszServerCopy );
|
||
|
wszPlainDomain = StripBackslashesFromComputerName ( wszDomainCopy );
|
||
|
|
||
|
if ( ! lstrcmp ( wszPlainServer, wszPlainDomain ) ) {
|
||
|
|
||
|
*pwszDC = new WCHAR [ lstrlen (_T("\\\\")) + lstrlen (wszPlainServer) + 1 ];
|
||
|
if ( *pwszDC == NULL ) {
|
||
|
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
|
||
|
}
|
||
|
wsprintf ( *pwszDC, _T("\\\\%s"), wszPlainServer );
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
dwError = NetGetDCName ( wszServer, wszDomain, (LPBYTE *) &wszDC );
|
||
|
if ( dwError != NOERROR ) {
|
||
|
|
||
|
//
|
||
|
// Error, try to get any DC name:
|
||
|
//
|
||
|
|
||
|
_ASSERT ( wszDC == NULL );
|
||
|
|
||
|
hr = HRESULT_FROM_WIN32 ( dwError );
|
||
|
|
||
|
dwError = NetGetAnyDCName ( wszServer, wszDomain, (LPBYTE *) &wszDC );
|
||
|
if ( dwError != NOERROR ) {
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_ASSERT ( dwError == NOERROR );
|
||
|
_ASSERT ( wszDC[0] == _T('\\') );
|
||
|
_ASSERT ( wszDC[1] == _T('\\') );
|
||
|
|
||
|
*pwszDC = new WCHAR [ lstrlen ( wszDC ) + 1 ];
|
||
|
if ( *pwszDC == NULL ) {
|
||
|
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
|
||
|
}
|
||
|
lstrcpy ( *pwszDC, wszDC );
|
||
|
|
||
|
Exit:
|
||
|
delete wszServerCopy;
|
||
|
delete wszDomainCopy;
|
||
|
|
||
|
if ( wszDC ) {
|
||
|
NetApiBufferFree ( wszDC );
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
IsValidEmailAddress (
|
||
|
LPCWSTR wszEmailAddress
|
||
|
)
|
||
|
{
|
||
|
char szBuf[512];
|
||
|
int cchCopied;
|
||
|
|
||
|
cchCopied = WideCharToMultiByte ( CP_ACP, 0, wszEmailAddress, -1, szBuf, sizeof (szBuf), NULL, NULL );
|
||
|
|
||
|
if ( cchCopied == 0 ) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return CAddr::ValidateEmailName( szBuf, FALSE );
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
HRESULT
|
||
|
DeleteMailbox (
|
||
|
LPCWSTR wszServer,
|
||
|
LPCWSTR wszAlias,
|
||
|
LPCWSTR wszVDirPath,
|
||
|
LPCWSTR wszUsername, // OPTIONAL
|
||
|
LPCWSTR wszPassword // OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
TraceFunctEnter ( "DeleteMailbox" );
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
UCHAR szAlias[512];
|
||
|
ULONG lHashValue;
|
||
|
DWORD cchMailboxPath;
|
||
|
LPWSTR wszMailboxPath;
|
||
|
LPCWSTR wszFormat;
|
||
|
|
||
|
if ( !wszServer || !wszAlias || !wszVDirPath ) {
|
||
|
BAIL_WITH_FAILURE ( hr, E_INVALIDARG );
|
||
|
}
|
||
|
|
||
|
if ( !*wszServer || !*wszAlias || !*wszVDirPath ) {
|
||
|
BAIL_WITH_FAILURE ( hr, E_INVALIDARG );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Compute the mailbox hash value:
|
||
|
//
|
||
|
|
||
|
WideCharToMultiByte ( CP_ACP, 0, wszAlias, -1, (char *) szAlias, ARRAY_SIZE ( szAlias ), NULL, NULL );
|
||
|
|
||
|
DebugTrace ( 0, "Deleting mailbox for %s", szAlias );
|
||
|
|
||
|
lHashValue = ElfHash ( szAlias ) % TABLE_SIZE;
|
||
|
|
||
|
DebugTrace ( 0, "Hash value = %u", lHashValue );
|
||
|
|
||
|
//
|
||
|
// Compute the mailbox directory path,
|
||
|
// this is: <vdir path>\<alias hash>\<alias>
|
||
|
//
|
||
|
|
||
|
cchMailboxPath =
|
||
|
lstrlen ( wszVDirPath ) + // <Virtual directory path>
|
||
|
1 + // '\'
|
||
|
20 + // <hash value>
|
||
|
1 + // '\'
|
||
|
lstrlen ( wszAlias ) + // <alias>
|
||
|
1; // null terminator
|
||
|
|
||
|
wszMailboxPath = new WCHAR [ cchMailboxPath ];
|
||
|
if ( !wszMailboxPath ) {
|
||
|
BAIL_WITH_FAILURE ( hr, E_OUTOFMEMORY );
|
||
|
}
|
||
|
|
||
|
// Avoid too many '\'s
|
||
|
if ( wszVDirPath [ lstrlen ( wszVDirPath ) - 1 ] == _T('\\') ) {
|
||
|
wszFormat = _T("%s%u\\%s");
|
||
|
}
|
||
|
else {
|
||
|
wszFormat = _T("%s\\%u\\%s");
|
||
|
}
|
||
|
|
||
|
wsprintf (
|
||
|
wszMailboxPath,
|
||
|
wszFormat,
|
||
|
wszVDirPath,
|
||
|
lHashValue,
|
||
|
wszAlias
|
||
|
);
|
||
|
|
||
|
RecursiveDeleteDirectory ( wszMailboxPath );
|
||
|
|
||
|
Exit:
|
||
|
TraceFunctLeave ();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//---[ ElfHash() ]------------------------------------------------------------
|
||
|
//
|
||
|
// Pulled this function from the stacks project. Calculates the hash value
|
||
|
// given a username. The mailbox of a user is stored in a subdirectory of
|
||
|
// the form <virtual directory root>\<hash value%TABLE_SIZE>\<username>.
|
||
|
// The username is the lowercase of the name part of the proxy address for
|
||
|
// e.g. username@x.com.
|
||
|
//
|
||
|
// Params:
|
||
|
// UserName The username to be hashed.
|
||
|
//
|
||
|
// Return: (HRESULT)
|
||
|
// NOERROR if success, ADSI error code if failed.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
unsigned long ElfHash (const unsigned char * UserName)
|
||
|
{
|
||
|
unsigned long HashValue = 0, g;
|
||
|
|
||
|
while (*UserName)
|
||
|
{
|
||
|
HashValue = (HashValue << 4) + *UserName++;
|
||
|
if( g = HashValue & 0xF0000000)
|
||
|
HashValue ^= g >> 24;
|
||
|
|
||
|
HashValue &= ~g;
|
||
|
}
|
||
|
|
||
|
return HashValue;
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT RecursiveDeleteDirectory (
|
||
|
LPCWSTR wszPath
|
||
|
)
|
||
|
{
|
||
|
TraceFunctEnter ( "DeleteDirectory" );
|
||
|
|
||
|
HRESULT hr = NOERROR;
|
||
|
DWORD cchOldCurrentDirectory;
|
||
|
LPWSTR wszOldCurrentDirectory = NULL;
|
||
|
DWORD cchPath = lstrlen ( wszPath );
|
||
|
HANDLE hSearch = INVALID_HANDLE_VALUE;
|
||
|
WIN32_FIND_DATA find;
|
||
|
BOOL fOk = TRUE;
|
||
|
HANDLE hFile;
|
||
|
|
||
|
//
|
||
|
// Save the current directory:
|
||
|
//
|
||
|
|
||
|
cchOldCurrentDirectory = GetCurrentDirectory ( 0, NULL );
|
||
|
_ASSERT ( cchOldCurrentDirectory > 0 );
|
||
|
wszOldCurrentDirectory = new WCHAR [ cchOldCurrentDirectory ];
|
||
|
if ( !wszOldCurrentDirectory ) {
|
||
|
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
|
||
|
}
|
||
|
GetCurrentDirectory ( cchOldCurrentDirectory, wszOldCurrentDirectory );
|
||
|
|
||
|
//
|
||
|
// Set the current directory to the path:
|
||
|
//
|
||
|
|
||
|
SetCurrentDirectory ( wszPath );
|
||
|
|
||
|
//
|
||
|
// Create the search string:
|
||
|
//
|
||
|
|
||
|
hSearch = FindFirstFile ( _T("*.*"), &find );
|
||
|
while ( hSearch != INVALID_HANDLE_VALUE && fOk ) {
|
||
|
|
||
|
//
|
||
|
// Skip the . and .. directories:
|
||
|
//
|
||
|
|
||
|
if (
|
||
|
lstrcmp ( find.cFileName, _T(".") ) &&
|
||
|
lstrcmp ( find.cFileName, _T("..") )
|
||
|
) {
|
||
|
|
||
|
if ( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
|
||
|
hr = RecursiveDeleteDirectory ( find.cFileName );
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// Delete this file:
|
||
|
//
|
||
|
|
||
|
hFile = CreateFile (
|
||
|
find.cFileName,
|
||
|
GENERIC_WRITE,
|
||
|
FILE_SHARE_DELETE,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_FLAG_DELETE_ON_CLOSE,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if ( hFile != INVALID_HANDLE_VALUE ) {
|
||
|
CloseHandle ( hFile );
|
||
|
}
|
||
|
// Otherwise, press on...
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get the next file:
|
||
|
fOk = FindNextFile ( hSearch, &find );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Delete the directory:
|
||
|
//
|
||
|
if ( hSearch != INVALID_HANDLE_VALUE ) {
|
||
|
FindClose ( hSearch );
|
||
|
hSearch = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
hFile = CreateFile (
|
||
|
wszPath,
|
||
|
GENERIC_WRITE,
|
||
|
FILE_SHARE_DELETE,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_FLAG_DELETE_ON_CLOSE,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if ( hFile != INVALID_HANDLE_VALUE ) {
|
||
|
CloseHandle ( hFile );
|
||
|
}
|
||
|
|
||
|
Exit:
|
||
|
if ( wszOldCurrentDirectory ) {
|
||
|
//
|
||
|
// Restore the current directory:
|
||
|
//
|
||
|
|
||
|
SetCurrentDirectory ( wszOldCurrentDirectory );
|
||
|
delete wszOldCurrentDirectory;
|
||
|
}
|
||
|
|
||
|
if ( hSearch != INVALID_HANDLE_VALUE ) {
|
||
|
FindClose ( hSearch );
|
||
|
hSearch = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
TraceFunctLeave ( );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#endif
|