Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

348 lines
8.3 KiB

// 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;
}