348 lines
8.3 KiB
C++
348 lines
8.3 KiB
C++
|
// utils.cpp : Implementation of helper functions
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include <dns.h>
|
||
|
#include <macfile.h>
|
||
|
|
||
|
HRESULT
|
||
|
GetErrorMessageFromModule(
|
||
|
IN DWORD dwError,
|
||
|
IN LPCTSTR lpszDll,
|
||
|
OUT LPTSTR *ppBuffer
|
||
|
)
|
||
|
{
|
||
|
if (0 == dwError || !lpszDll || !*lpszDll || !ppBuffer)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
HINSTANCE hMsgLib = LoadLibrary(lpszDll);
|
||
|
if (!hMsgLib)
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
else
|
||
|
{
|
||
|
DWORD dwRet = ::FormatMessage(
|
||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
|
||
|
hMsgLib, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||
|
(LPTSTR)ppBuffer, 0, NULL);
|
||
|
|
||
|
if (0 == dwRet)
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
|
||
|
FreeLibrary(hMsgLib);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
GetErrorMessage(
|
||
|
IN DWORD i_dwError,
|
||
|
OUT CString& cstrErrorMsg
|
||
|
)
|
||
|
{
|
||
|
if (0 == i_dwError)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
LPTSTR lpBuffer = NULL;
|
||
|
|
||
|
DWORD dwRet = ::FormatMessage(
|
||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||
|
NULL, i_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||
|
(LPTSTR)&lpBuffer, 0, NULL);
|
||
|
if (0 == dwRet)
|
||
|
{
|
||
|
// if no message is found, GetLastError will return ERROR_MR_MID_NOT_FOUND
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
|
||
|
if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr ||
|
||
|
0x80070000 == (i_dwError & 0xffff0000) ||
|
||
|
0 == (i_dwError & 0xffff0000) )
|
||
|
{
|
||
|
hr = GetErrorMessageFromModule((i_dwError & 0x0000ffff), _T("netmsg.dll"), &lpBuffer);
|
||
|
if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr)
|
||
|
{
|
||
|
int iError = i_dwError; // convert to a signed integer
|
||
|
if (iError >= AFPERR_MIN && iError < AFPERR_BASE)
|
||
|
{
|
||
|
// use a positive number to search sfmmsg.dll
|
||
|
hr = GetErrorMessageFromModule(-iError, _T("sfmmsg.dll"), &lpBuffer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
cstrErrorMsg = lpBuffer;
|
||
|
LocalFree(lpBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// we failed to retrieve the error message from system/netmsg.dll/sfmmsg.dll,
|
||
|
// report the error code directly to user
|
||
|
hr = S_OK;
|
||
|
cstrErrorMsg.Format(_T("0x%x"), i_dwError);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
GetDisplayMessageHelper(
|
||
|
OUT CString& cstrMsg,
|
||
|
IN DWORD dwErr, // error code
|
||
|
IN UINT iStringId, // string resource Id
|
||
|
IN va_list *parglist) // Optional arguments
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
CString cstrErrorMsg;
|
||
|
|
||
|
if (dwErr)
|
||
|
hr = GetErrorMessage(dwErr, cstrErrorMsg);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (iStringId == 0)
|
||
|
{
|
||
|
if (dwErr)
|
||
|
{
|
||
|
cstrMsg = cstrErrorMsg;
|
||
|
} else
|
||
|
{
|
||
|
cstrMsg = va_arg(*parglist, LPCTSTR);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CString cstrString;
|
||
|
cstrString.LoadString(iStringId);
|
||
|
|
||
|
LPTSTR lpBuffer = NULL;
|
||
|
DWORD dwRet = ::FormatMessage(
|
||
|
FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||
|
cstrString,
|
||
|
0, // dwMessageId
|
||
|
0, // dwLanguageId, ignored
|
||
|
(LPTSTR)&lpBuffer,
|
||
|
0, // nSize
|
||
|
parglist);
|
||
|
if (dwRet == 0)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cstrMsg = lpBuffer;
|
||
|
if (dwErr)
|
||
|
cstrMsg += cstrErrorMsg;
|
||
|
|
||
|
LocalFree(lpBuffer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
// Failed to retrieve the proper message, report the failure directly to user
|
||
|
cstrMsg.Format(_T("0x%x"), hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
GetDisplayMessage(
|
||
|
OUT CString& cstrMsg,
|
||
|
IN DWORD dwErr, // error code
|
||
|
IN UINT iStringId, // string resource Id
|
||
|
...) // Optional arguments
|
||
|
{
|
||
|
va_list arglist;
|
||
|
va_start(arglist, iStringId);
|
||
|
GetDisplayMessageHelper(cstrMsg, dwErr, iStringId, &arglist);
|
||
|
va_end(arglist);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
DisplayMessageBox(
|
||
|
IN HWND hwndParent,
|
||
|
IN UINT uType, // style of message box
|
||
|
IN DWORD dwErr, // error code
|
||
|
IN UINT iStringId, // string resource Id
|
||
|
...) // Optional arguments
|
||
|
{
|
||
|
CString cstrCaption;
|
||
|
CString cstrMsg;
|
||
|
|
||
|
cstrCaption.LoadString(IDS_WIZARD_TITLE);
|
||
|
|
||
|
va_list arglist;
|
||
|
va_start(arglist, iStringId);
|
||
|
GetDisplayMessageHelper(cstrMsg, dwErr, iStringId, &arglist);
|
||
|
va_end(arglist);
|
||
|
|
||
|
return ::MessageBox(hwndParent, cstrMsg, cstrCaption, uType);
|
||
|
}
|
||
|
|
||
|
// NOTE: this function only handles limited cases, e.g., no ip address
|
||
|
BOOL IsLocalComputer(IN LPCTSTR lpszComputer)
|
||
|
{
|
||
|
if (!lpszComputer || !*lpszComputer)
|
||
|
return TRUE;
|
||
|
|
||
|
if ( _tcslen(lpszComputer) > 2 && *lpszComputer == _T('\\') && *(lpszComputer + 1) == _T('\\') )
|
||
|
lpszComputer += 2;
|
||
|
|
||
|
BOOL bReturn = FALSE;
|
||
|
DWORD dwErr = 0;
|
||
|
TCHAR szBuffer[DNS_MAX_NAME_BUFFER_LENGTH];
|
||
|
DWORD dwSize = DNS_MAX_NAME_BUFFER_LENGTH;
|
||
|
|
||
|
// 1st: compare against local Netbios computer name
|
||
|
if ( !GetComputerNameEx(ComputerNameNetBIOS, szBuffer, &dwSize) )
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
} else
|
||
|
{
|
||
|
bReturn = (0 == lstrcmpi(szBuffer, lpszComputer));
|
||
|
if (!bReturn)
|
||
|
{ // 2nd: compare against local Dns computer name
|
||
|
dwSize = DNS_MAX_NAME_BUFFER_LENGTH;
|
||
|
if (GetComputerNameEx(ComputerNameDnsFullyQualified, szBuffer, &dwSize))
|
||
|
bReturn = (0 == lstrcmpi(szBuffer, lpszComputer));
|
||
|
else
|
||
|
dwErr = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwErr)
|
||
|
TRACE(_T("IsLocalComputer dwErr = %x\n"), dwErr);
|
||
|
|
||
|
return bReturn;
|
||
|
}
|
||
|
|
||
|
void GetFullPath(
|
||
|
IN LPCTSTR lpszServer,
|
||
|
IN LPCTSTR lpszDir,
|
||
|
OUT CString& cstrPath
|
||
|
)
|
||
|
{
|
||
|
ASSERT(lpszDir && *lpszDir);
|
||
|
|
||
|
if (IsLocalComputer(lpszServer))
|
||
|
{
|
||
|
cstrPath = lpszDir;
|
||
|
} else
|
||
|
{
|
||
|
if (*lpszServer != _T('\\') || *(lpszServer + 1) != _T('\\'))
|
||
|
{
|
||
|
cstrPath = _T("\\\\");
|
||
|
cstrPath += lpszServer;
|
||
|
} else
|
||
|
{
|
||
|
cstrPath = lpszServer;
|
||
|
}
|
||
|
cstrPath += _T("\\");
|
||
|
cstrPath += lpszDir;
|
||
|
int i = cstrPath.Find(_T(':'));
|
||
|
ASSERT(-1 != i);
|
||
|
cstrPath.SetAt(i, _T('$'));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Purpose: verify if the specified drive belongs to a list of disk drives on the server
|
||
|
// Return:
|
||
|
// S_OK: yes
|
||
|
// S_FALSE: no
|
||
|
// hr: some error happened
|
||
|
HRESULT
|
||
|
VerifyDriveLetter(
|
||
|
IN LPCTSTR lpszServer,
|
||
|
IN LPCTSTR lpszDrive
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_FALSE;
|
||
|
LPBYTE pBuffer = NULL;
|
||
|
DWORD dwEntriesRead = 0;
|
||
|
DWORD dwTotalEntries = 0;
|
||
|
DWORD dwRet = NetServerDiskEnum(
|
||
|
const_cast<LPTSTR>(lpszServer),
|
||
|
0,
|
||
|
&pBuffer,
|
||
|
-1,
|
||
|
&dwEntriesRead,
|
||
|
&dwTotalEntries,
|
||
|
NULL);
|
||
|
|
||
|
if (NERR_Success == dwRet)
|
||
|
{
|
||
|
LPTSTR pDrive = (LPTSTR)pBuffer;
|
||
|
for (UINT i=0; i<dwEntriesRead; i++)
|
||
|
{
|
||
|
if (_totupper(*pDrive) == _totupper(*lpszDrive))
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
pDrive += 3;
|
||
|
}
|
||
|
|
||
|
NetApiBufferFree(pBuffer);
|
||
|
} else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(dwRet);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Purpose: is there a related admin $ share
|
||
|
// Return:
|
||
|
// S_OK: yes
|
||
|
// S_FALSE: no
|
||
|
// hr: some error happened
|
||
|
HRESULT
|
||
|
IsAdminShare(
|
||
|
IN LPCTSTR lpszServer,
|
||
|
IN LPCTSTR lpszDrive
|
||
|
)
|
||
|
{
|
||
|
ASSERT(!IsLocalComputer(lpszServer));
|
||
|
|
||
|
HRESULT hr = S_FALSE;
|
||
|
LPBYTE pBuffer = NULL;
|
||
|
DWORD dwEntriesRead = 0;
|
||
|
DWORD dwTotalEntries = 0;
|
||
|
DWORD dwRet = NetShareEnum(
|
||
|
const_cast<LPTSTR>(lpszServer),
|
||
|
1,
|
||
|
&pBuffer,
|
||
|
-1,
|
||
|
&dwEntriesRead,
|
||
|
&dwTotalEntries,
|
||
|
NULL);
|
||
|
|
||
|
if (NERR_Success == dwRet)
|
||
|
{
|
||
|
PSHARE_INFO_1 pShareInfo = (PSHARE_INFO_1)pBuffer;
|
||
|
for (UINT i=0; i<dwEntriesRead; i++)
|
||
|
{
|
||
|
if ( (pShareInfo->shi1_type & STYPE_SPECIAL) &&
|
||
|
_tcslen(pShareInfo->shi1_netname) == 2 &&
|
||
|
*(pShareInfo->shi1_netname + 1) == _T('$') &&
|
||
|
_totupper(*(pShareInfo->shi1_netname)) == _totupper(*lpszDrive) )
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
pShareInfo++;
|
||
|
}
|
||
|
|
||
|
NetApiBufferFree(pBuffer);
|
||
|
} else
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(dwRet);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|