1014 lines
20 KiB
C++
1014 lines
20 KiB
C++
|
// Copyright (c) 1997-2001 Microsoft Corporation
|
||
|
//
|
||
|
// File: common.cpp
|
||
|
//
|
||
|
// Synopsis: Commonly used functions
|
||
|
//
|
||
|
// History: 02/03/2001 JeffJon Created
|
||
|
|
||
|
#include "pch.h"
|
||
|
|
||
|
#include "resource.h"
|
||
|
|
||
|
#include <ciodm.h>
|
||
|
|
||
|
|
||
|
// Creates the fonts for setLargeFonts().
|
||
|
//
|
||
|
// hDialog - handle to a dialog to be used to retrieve a device
|
||
|
// context.
|
||
|
//
|
||
|
// bigBoldFont - receives the handle of the big bold font created.
|
||
|
|
||
|
void
|
||
|
InitFonts(
|
||
|
HWND hDialog,
|
||
|
HFONT& bigBoldFont)
|
||
|
{
|
||
|
ASSERT(Win::IsWindow(hDialog));
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NONCLIENTMETRICS ncm;
|
||
|
memset(&ncm, 0, sizeof(ncm));
|
||
|
ncm.cbSize = sizeof(ncm);
|
||
|
|
||
|
hr = Win::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
||
|
BREAK_ON_FAILED_HRESULT(hr);
|
||
|
|
||
|
LOGFONT bigBoldLogFont = ncm.lfMessageFont;
|
||
|
bigBoldLogFont.lfWeight = FW_BOLD;
|
||
|
|
||
|
String fontName = String::load(IDS_BIG_BOLD_FONT_NAME);
|
||
|
|
||
|
// ensure null termination 260237
|
||
|
|
||
|
memset(bigBoldLogFont.lfFaceName, 0, LF_FACESIZE * sizeof(TCHAR));
|
||
|
size_t fnLen = fontName.length();
|
||
|
fontName.copy(
|
||
|
bigBoldLogFont.lfFaceName,
|
||
|
|
||
|
// don't copy over the last null
|
||
|
|
||
|
min(LF_FACESIZE - 1, fnLen));
|
||
|
|
||
|
unsigned fontSize = 0;
|
||
|
String::load(IDS_BIG_BOLD_FONT_SIZE).convert(fontSize);
|
||
|
ASSERT(fontSize);
|
||
|
|
||
|
HDC hdc = 0;
|
||
|
hr = Win::GetDC(hDialog, hdc);
|
||
|
BREAK_ON_FAILED_HRESULT(hr);
|
||
|
|
||
|
bigBoldLogFont.lfHeight =
|
||
|
- ::MulDiv(
|
||
|
static_cast<int>(fontSize),
|
||
|
Win::GetDeviceCaps(hdc, LOGPIXELSY),
|
||
|
72);
|
||
|
|
||
|
hr = Win::CreateFontIndirect(bigBoldLogFont, bigBoldFont);
|
||
|
BREAK_ON_FAILED_HRESULT(hr);
|
||
|
|
||
|
Win::ReleaseDC(hDialog, hdc);
|
||
|
}
|
||
|
while (0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
SetControlFont(HWND parentDialog, int controlID, HFONT font)
|
||
|
{
|
||
|
ASSERT(Win::IsWindow(parentDialog));
|
||
|
ASSERT(controlID);
|
||
|
ASSERT(font);
|
||
|
|
||
|
HWND control = Win::GetDlgItem(parentDialog, controlID);
|
||
|
|
||
|
if (control)
|
||
|
{
|
||
|
Win::SetWindowFont(control, font, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
SetLargeFont(HWND dialog, int bigBoldResID)
|
||
|
{
|
||
|
ASSERT(Win::IsWindow(dialog));
|
||
|
ASSERT(bigBoldResID);
|
||
|
|
||
|
static HFONT bigBoldFont = 0;
|
||
|
if (!bigBoldFont)
|
||
|
{
|
||
|
InitFonts(dialog, bigBoldFont);
|
||
|
}
|
||
|
|
||
|
SetControlFont(dialog, bigBoldResID, bigBoldFont);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool
|
||
|
IsServiceInstalledHelper(const wchar_t* serviceName)
|
||
|
{
|
||
|
LOG_FUNCTION2(IsServiceInstalledHelper, serviceName);
|
||
|
ASSERT(serviceName);
|
||
|
|
||
|
// if we can open the service, then it is installed
|
||
|
|
||
|
bool result = false;
|
||
|
|
||
|
SC_HANDLE hsc =
|
||
|
::OpenSCManager(0, SERVICES_ACTIVE_DATABASE, GENERIC_READ);
|
||
|
|
||
|
if (hsc)
|
||
|
{
|
||
|
SC_HANDLE hs = ::OpenServiceW(hsc, serviceName, GENERIC_READ);
|
||
|
|
||
|
if (hs)
|
||
|
{
|
||
|
::CloseServiceHandle(hs);
|
||
|
result = true;
|
||
|
}
|
||
|
|
||
|
::CloseServiceHandle(hsc);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Wait for a handle to become signalled, or a timeout to expire, or WM_QUIT
|
||
|
// to appear in the message queue. Pump the message queue while we wait.
|
||
|
//
|
||
|
// WARNING: UI should diable itself before calling any function that invokes
|
||
|
// this function, or functions calling this one should guard against
|
||
|
// re-entrance. Otherwise there will be a re-entrancy problem.
|
||
|
//
|
||
|
// e.g. command handler gets button clicked message, calls a func that calls
|
||
|
// this wait function, then user clicks the button again, command handler call
|
||
|
// a func that calls this one, and so on.
|
||
|
|
||
|
DWORD
|
||
|
MyWaitForSendMessageThread(HANDLE hThread, DWORD dwTimeout)
|
||
|
{
|
||
|
LOG_FUNCTION(MyWaitForSendMessageThread);
|
||
|
ASSERT(hThread);
|
||
|
|
||
|
MSG msg;
|
||
|
DWORD dwRet;
|
||
|
DWORD dwEnd = GetTickCount() + dwTimeout;
|
||
|
bool quit = false;
|
||
|
|
||
|
// We will attempt to wait up to dwTimeout for the thread to
|
||
|
// terminate
|
||
|
|
||
|
do
|
||
|
{
|
||
|
dwRet = MsgWaitForMultipleObjects(1, &hThread, FALSE,
|
||
|
dwTimeout, QS_ALLEVENTS | QS_SENDMESSAGE );
|
||
|
|
||
|
if (dwRet == (WAIT_OBJECT_0 + 1))
|
||
|
{
|
||
|
// empty out the message queue. We call DispatchMessage to
|
||
|
// ensure that we still process the WM_PAINT messages.
|
||
|
// DANGER: Make sure that the CYS UI is completely disabled
|
||
|
// or there will be re-entrancy problems here
|
||
|
|
||
|
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||
|
{
|
||
|
if (msg.message == WM_QUIT)
|
||
|
{
|
||
|
// Need to re-post this so that we know to close CYS
|
||
|
|
||
|
::PostMessage(msg.hwnd, WM_QUIT, 0, 0);
|
||
|
quit = true;
|
||
|
break;
|
||
|
}
|
||
|
::TranslateMessage(&msg);
|
||
|
::DispatchMessage(&msg);
|
||
|
}
|
||
|
|
||
|
// Calculate if we have any more time left in the timeout to
|
||
|
// wait on.
|
||
|
|
||
|
if (dwTimeout != INFINITE)
|
||
|
{
|
||
|
dwTimeout = dwEnd - GetTickCount();
|
||
|
if ((long)dwTimeout <= 0)
|
||
|
{
|
||
|
// No more time left, fail with WAIT_TIMEOUT
|
||
|
dwRet = WAIT_TIMEOUT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED
|
||
|
// The thread must have exited, so we are happy
|
||
|
//
|
||
|
// dwRet == WAIT_TIMEOUT
|
||
|
// The thread is taking too long to finish, so just
|
||
|
// return and let the caller kill it
|
||
|
|
||
|
} while (dwRet == (WAIT_OBJECT_0 + 1) && !quit);
|
||
|
|
||
|
return(dwRet);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
CreateAndWaitForProcess(const String& commandLine, DWORD& exitCode)
|
||
|
{
|
||
|
LOG_FUNCTION2(CreateAndWaitForProcess, commandLine);
|
||
|
ASSERT(!commandLine.empty());
|
||
|
|
||
|
exitCode = 0;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
do
|
||
|
{
|
||
|
PROCESS_INFORMATION procInfo;
|
||
|
memset(&procInfo, 0, sizeof(procInfo));
|
||
|
|
||
|
STARTUPINFO startup;
|
||
|
memset(&startup, 0, sizeof(startup));
|
||
|
|
||
|
String commandLine2(commandLine);
|
||
|
|
||
|
LOG(L"Calling CreateProcess");
|
||
|
LOG(commandLine2);
|
||
|
|
||
|
hr =
|
||
|
Win::CreateProcess(
|
||
|
commandLine2,
|
||
|
0,
|
||
|
0,
|
||
|
false,
|
||
|
0,
|
||
|
0,
|
||
|
String(),
|
||
|
startup,
|
||
|
procInfo);
|
||
|
BREAK_ON_FAILED_HRESULT(hr);
|
||
|
|
||
|
ASSERT(procInfo.hProcess);
|
||
|
|
||
|
DWORD dwRet = MyWaitForSendMessageThread(procInfo.hProcess, INFINITE);
|
||
|
|
||
|
ASSERT(dwRet == WAIT_OBJECT_0);
|
||
|
|
||
|
hr = Win::GetExitCodeProcess(procInfo.hProcess, exitCode);
|
||
|
BREAK_ON_FAILED_HRESULT(hr);
|
||
|
|
||
|
Win::CloseHandle(procInfo.hThread);
|
||
|
Win::CloseHandle(procInfo.hProcess);
|
||
|
}
|
||
|
while (0);
|
||
|
|
||
|
LOG(String::format(L"exit code = %1!x!", exitCode));
|
||
|
LOG_HRESULT(hr);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
MyCreateProcess(const String& commandLine)
|
||
|
{
|
||
|
LOG_FUNCTION2(MyCreateProcess, commandLine);
|
||
|
ASSERT(!commandLine.empty());
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
do
|
||
|
{
|
||
|
PROCESS_INFORMATION procInfo;
|
||
|
memset(&procInfo, 0, sizeof(procInfo));
|
||
|
|
||
|
STARTUPINFO startup;
|
||
|
memset(&startup, 0, sizeof(startup));
|
||
|
|
||
|
String commandLine2(commandLine);
|
||
|
|
||
|
LOG(L"Calling CreateProcess");
|
||
|
LOG(commandLine2);
|
||
|
|
||
|
hr =
|
||
|
Win::CreateProcess(
|
||
|
commandLine2,
|
||
|
0,
|
||
|
0,
|
||
|
false,
|
||
|
0,
|
||
|
0,
|
||
|
String(),
|
||
|
startup,
|
||
|
procInfo);
|
||
|
BREAK_ON_FAILED_HRESULT(hr);
|
||
|
|
||
|
ASSERT(procInfo.hProcess);
|
||
|
|
||
|
Win::CloseHandle(procInfo.hThread);
|
||
|
Win::CloseHandle(procInfo.hProcess);
|
||
|
}
|
||
|
while (0);
|
||
|
|
||
|
LOG_HRESULT(hr);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
IsKeyValuePresent(RegistryKey& key, const String& valueKey)
|
||
|
{
|
||
|
LOG_FUNCTION(IsKeyValuePresent);
|
||
|
|
||
|
bool result = false;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
|
||
|
String value;
|
||
|
HRESULT hr = key.GetValue(valueKey, value);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to read regkey %1 because: hr = %2!x!",
|
||
|
valueKey,
|
||
|
hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!value.empty())
|
||
|
{
|
||
|
result = true;
|
||
|
break;
|
||
|
}
|
||
|
} while (false);
|
||
|
|
||
|
LOG_BOOL(result);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool
|
||
|
GetRegKeyValue(
|
||
|
const String& keyName,
|
||
|
const String& value,
|
||
|
String& resultString,
|
||
|
HKEY parentKey)
|
||
|
{
|
||
|
LOG_FUNCTION(GetRegKeyValue);
|
||
|
|
||
|
bool result = true;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RegistryKey key;
|
||
|
|
||
|
hr = key.Open(parentKey, keyName);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to open regkey %1 because: hr = %2!x!",
|
||
|
keyName.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = key.GetValue(value, resultString);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to read regkey %1 because: hr = %2!x!",
|
||
|
value.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
LOG(String::format(
|
||
|
L"Value of key: %1",
|
||
|
resultString.c_str()));
|
||
|
|
||
|
} while (false);
|
||
|
|
||
|
LOG_BOOL(result);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
GetRegKeyValue(
|
||
|
const String& keyName,
|
||
|
const String& value,
|
||
|
DWORD& resultValue,
|
||
|
HKEY parentKey)
|
||
|
{
|
||
|
LOG_FUNCTION(GetRegKeyValue);
|
||
|
|
||
|
bool result = true;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RegistryKey key;
|
||
|
|
||
|
hr = key.Open(parentKey, keyName);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to open regkey %1 because: hr = %2!x!",
|
||
|
keyName.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = key.GetValue(value, resultValue);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to read regkey %1 because: hr = %2!x!",
|
||
|
value.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
LOG(String::format(
|
||
|
L"Key value: %1!d!",
|
||
|
resultValue));
|
||
|
|
||
|
} while (false);
|
||
|
|
||
|
LOG_BOOL(result);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
SetRegKeyValue(
|
||
|
const String& keyName,
|
||
|
const String& value,
|
||
|
const String& newString,
|
||
|
HKEY parentKey,
|
||
|
bool create
|
||
|
)
|
||
|
{
|
||
|
LOG_FUNCTION(SetRegKeyValue);
|
||
|
|
||
|
bool result = true;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RegistryKey key;
|
||
|
|
||
|
if (create)
|
||
|
{
|
||
|
hr = key.Create(parentKey, keyName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = key.Open(parentKey, keyName, KEY_ALL_ACCESS);
|
||
|
}
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to open regkey %1 because: hr = %2!x!",
|
||
|
keyName.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = key.SetValue(value, newString);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to write regkey %1 because: hr = %2!x!",
|
||
|
value.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (false);
|
||
|
|
||
|
LOG_BOOL(result);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
SetRegKeyValue(
|
||
|
const String& keyName,
|
||
|
const String& value,
|
||
|
DWORD newValue,
|
||
|
HKEY parentKey,
|
||
|
bool create)
|
||
|
{
|
||
|
LOG_FUNCTION(SetRegKeyValue);
|
||
|
|
||
|
bool result = true;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RegistryKey key;
|
||
|
|
||
|
if (create)
|
||
|
{
|
||
|
hr = key.Create(parentKey, keyName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = key.Open(parentKey, keyName, KEY_WRITE);
|
||
|
}
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to open regkey %1 because: hr = %2!x!",
|
||
|
keyName.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = key.SetValue(value, newValue);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to write regkey %1 because: hr = %2!x!",
|
||
|
value.c_str(),
|
||
|
hr));
|
||
|
|
||
|
result = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (false);
|
||
|
|
||
|
LOG_BOOL(result);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
IsIndexingServiceOn()
|
||
|
{
|
||
|
LOG_FUNCTION(IsIndexingServiceOn);
|
||
|
|
||
|
bool result = false;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
CLSID clsid;
|
||
|
HRESULT hr = CLSIDFromProgID( L"Microsoft.ISAdm", &clsid );
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to get the CLSID from ProgID: hr = 0x%x",
|
||
|
hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SmartInterface<IAdminIndexServer> adminIndexServer;
|
||
|
hr = adminIndexServer.AcquireViaCreateInstance(
|
||
|
clsid,
|
||
|
0,
|
||
|
CLSCTX_INPROC_SERVER);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to CoCreateInstance of IAdminIndexServer: hr = 0x%x",
|
||
|
hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
VARIANT_BOOL var;
|
||
|
hr = adminIndexServer->IsRunning(&var);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to get running state: hr = 0x%x",
|
||
|
hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
result = var ? true : false;
|
||
|
|
||
|
} while (false);
|
||
|
|
||
|
LOG_BOOL(result);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
ModifyIndexingService(bool turnOn)
|
||
|
{
|
||
|
LOG_FUNCTION2(
|
||
|
ModifyIndexingService,
|
||
|
turnOn ? L"true" : L"false");
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
CLSID clsid;
|
||
|
hr = CLSIDFromProgID( L"Microsoft.ISAdm", &clsid );
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to get the CLSID from ProgID: hr = 0x%x",
|
||
|
hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SmartInterface<IAdminIndexServer> adminIndexServer;
|
||
|
hr = adminIndexServer.AcquireViaCreateInstance(
|
||
|
clsid,
|
||
|
0,
|
||
|
CLSCTX_INPROC_SERVER);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to CoCreateInstance of IAdminIndexServer: hr = 0x%x",
|
||
|
hr));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (turnOn)
|
||
|
{
|
||
|
hr = adminIndexServer->Start();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = adminIndexServer->Stop();
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(
|
||
|
L"Failed to start or stop indexing service: hr = 0x%x",
|
||
|
hr));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (false);
|
||
|
|
||
|
LOG(String::format(L"hr = %1!x!", hr));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
StartIndexingService()
|
||
|
{
|
||
|
return ModifyIndexingService(true);
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
StopIndexingService()
|
||
|
{
|
||
|
return ModifyIndexingService(false);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// return true if the name is a reserved name, false otherwise. If true, also
|
||
|
// set message to an error message describing the problem.
|
||
|
|
||
|
bool
|
||
|
IsReservedDnsName(const String& dnsName, String& message)
|
||
|
{
|
||
|
LOG_FUNCTION2(IsReservedDnsName, dnsName);
|
||
|
ASSERT(!dnsName.empty());
|
||
|
|
||
|
message.erase();
|
||
|
bool result = false;
|
||
|
|
||
|
// We're still trying to decide if we should restrict these names
|
||
|
//
|
||
|
// // names with these as the last labels are illegal.
|
||
|
//
|
||
|
// static const String RESERVED[] =
|
||
|
// {
|
||
|
// L"in-addr.arpa",
|
||
|
// L"ipv6.int",
|
||
|
//
|
||
|
// // RFC 2606 documents these:
|
||
|
//
|
||
|
// L"test",
|
||
|
// L"example",
|
||
|
// L"invalid",
|
||
|
// L"localhost",
|
||
|
// L"example.com",
|
||
|
// L"example.org",
|
||
|
// L"example.net"
|
||
|
// };
|
||
|
//
|
||
|
// String name(dnsName);
|
||
|
// name.to_upper();
|
||
|
// if (name[name.length() - 1] == L'.')
|
||
|
// {
|
||
|
// // remove the trailing dot
|
||
|
//
|
||
|
// name.resize(name.length() - 1);
|
||
|
// }
|
||
|
//
|
||
|
// for (int i = 0; i < sizeof(RESERVED) / sizeof(String); ++i)
|
||
|
// {
|
||
|
// String res = RESERVED[i];
|
||
|
// res.to_upper();
|
||
|
//
|
||
|
// size_t pos = name.rfind(res);
|
||
|
//
|
||
|
// if (pos == String::npos)
|
||
|
// {
|
||
|
// continue;
|
||
|
// }
|
||
|
//
|
||
|
// if (pos == 0 && name.length() == res.length())
|
||
|
// {
|
||
|
// ASSERT(name == res);
|
||
|
//
|
||
|
// result = true;
|
||
|
// message =
|
||
|
// String::format(
|
||
|
// IDS_RESERVED_NAME,
|
||
|
// dnsName.c_str());
|
||
|
// break;
|
||
|
// }
|
||
|
//
|
||
|
// if ((pos == name.length() - res.length()) && (name[pos - 1] == L'.'))
|
||
|
// {
|
||
|
// // the name has reserved as a suffix.
|
||
|
//
|
||
|
// result = true;
|
||
|
// message =
|
||
|
// String::format(
|
||
|
// IDS_RESERVED_NAME_SUFFIX,
|
||
|
// dnsName.c_str(),
|
||
|
// RESERVED[i].c_str());
|
||
|
// break;
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool
|
||
|
ValidateDomainDnsNameSyntax(
|
||
|
HWND dialog,
|
||
|
int editResID,
|
||
|
bool warnOnNonRFC,
|
||
|
bool* isNonRFC)
|
||
|
{
|
||
|
return
|
||
|
ValidateDomainDnsNameSyntax(
|
||
|
dialog,
|
||
|
String(),
|
||
|
editResID,
|
||
|
warnOnNonRFC,
|
||
|
isNonRFC);
|
||
|
}
|
||
|
|
||
|
|
||
|
bool
|
||
|
ValidateDomainDnsNameSyntax(
|
||
|
HWND dialog,
|
||
|
const String& domainName,
|
||
|
int editResID,
|
||
|
bool warnOnNonRFC,
|
||
|
bool* isNonRFC)
|
||
|
{
|
||
|
LOG_FUNCTION(ValidateDomainDnsNameSyntax);
|
||
|
ASSERT(Win::IsWindow(dialog));
|
||
|
ASSERT(editResID > 0);
|
||
|
|
||
|
bool valid = false;
|
||
|
String message;
|
||
|
String dnsName =
|
||
|
domainName.empty()
|
||
|
? Win::GetTrimmedDlgItemText(dialog, editResID)
|
||
|
: domainName;
|
||
|
if (isNonRFC)
|
||
|
{
|
||
|
*isNonRFC = false;
|
||
|
}
|
||
|
|
||
|
LOG(L"validating " + dnsName);
|
||
|
|
||
|
switch (
|
||
|
Dns::ValidateDnsNameSyntax(
|
||
|
dnsName,
|
||
|
DNS_DOMAIN_NAME_MAX_LIMIT_DUE_TO_POLICY_UTF8) )
|
||
|
{
|
||
|
case Dns::NON_RFC:
|
||
|
{
|
||
|
if (isNonRFC)
|
||
|
{
|
||
|
*isNonRFC = true;
|
||
|
}
|
||
|
if (warnOnNonRFC)
|
||
|
{
|
||
|
// warn about non-rfc names
|
||
|
|
||
|
String msg = String::format(IDS_NON_RFC_NAME, dnsName.c_str());
|
||
|
popup.Info(
|
||
|
dialog,
|
||
|
msg);
|
||
|
|
||
|
LOG(msg);
|
||
|
}
|
||
|
|
||
|
// fall through
|
||
|
//lint -e616 allow fall thru
|
||
|
}
|
||
|
case Dns::VALID:
|
||
|
{
|
||
|
valid = !IsReservedDnsName(dnsName, message);
|
||
|
break;
|
||
|
}
|
||
|
case Dns::TOO_LONG:
|
||
|
{
|
||
|
message =
|
||
|
String::format(
|
||
|
IDS_DNS_NAME_TOO_LONG,
|
||
|
dnsName.c_str(),
|
||
|
DNS_DOMAIN_NAME_MAX_LIMIT_DUE_TO_POLICY,
|
||
|
DNS_DOMAIN_NAME_MAX_LIMIT_DUE_TO_POLICY_UTF8);
|
||
|
break;
|
||
|
}
|
||
|
case Dns::NUMERIC:
|
||
|
case Dns::BAD_CHARS:
|
||
|
case Dns::INVALID:
|
||
|
default:
|
||
|
{
|
||
|
message =
|
||
|
String::format(
|
||
|
IDS_BAD_DNS_SYNTAX,
|
||
|
dnsName.c_str(),
|
||
|
Dns::MAX_LABEL_LENGTH);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!valid)
|
||
|
{
|
||
|
popup.Gripe(dialog, editResID, message);
|
||
|
}
|
||
|
|
||
|
return valid;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool
|
||
|
ConfirmNetbiosLookingNameIsReallyDnsName(HWND parentDialog, int editResID)
|
||
|
{
|
||
|
ASSERT(Win::IsWindow(parentDialog));
|
||
|
ASSERT(editResID > 0);
|
||
|
|
||
|
// check if the name is a single DNS label (a single label with a trailing
|
||
|
// dot does not count. If the user is DNS-saavy enough to use an absolute
|
||
|
// DNS name, then we will pester him no further.)
|
||
|
|
||
|
String domain = Win::GetTrimmedDlgItemText(parentDialog, editResID);
|
||
|
if (domain.find(L'.') == String::npos)
|
||
|
{
|
||
|
// no dot found: must be a single label
|
||
|
|
||
|
if (
|
||
|
popup.MessageBox(
|
||
|
parentDialog,
|
||
|
String::format(
|
||
|
IDS_CONFIRM_NETBIOS_LOOKING_NAME,
|
||
|
domain.c_str(),
|
||
|
domain.c_str()),
|
||
|
MB_YESNO) == IDNO)
|
||
|
{
|
||
|
// user goofed. or we frightened them.
|
||
|
|
||
|
HWND edit = Win::GetDlgItem(parentDialog, editResID);
|
||
|
Win::SendMessage(edit, EM_SETSEL, 0, -1);
|
||
|
Win::SetFocus(edit);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
VariantArrayToStringList(VARIANT* variant, StringList& stringList)
|
||
|
{
|
||
|
LOG_FUNCTION(VariantArrayToStringList);
|
||
|
|
||
|
ASSERT(variant);
|
||
|
ASSERT(V_VT(variant) == (VT_ARRAY | VT_BSTR));
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
stringList.clear();
|
||
|
|
||
|
SAFEARRAY* psa = V_ARRAY(variant);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
ASSERT(psa);
|
||
|
ASSERT(psa != (SAFEARRAY*)-1);
|
||
|
|
||
|
if (!psa or psa == (SAFEARRAY*)-1)
|
||
|
{
|
||
|
LOG(L"variant not safe array");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (::SafeArrayGetDim(psa) != 1)
|
||
|
{
|
||
|
LOG(L"safe array: wrong number of dimensions");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
VARTYPE vt = VT_EMPTY;
|
||
|
hr = ::SafeArrayGetVartype(psa, &vt);
|
||
|
if (FAILED(hr) || vt != VT_BSTR)
|
||
|
{
|
||
|
LOG(L"safe array: wrong element type");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
long lower = 0;
|
||
|
long upper = 0;
|
||
|
|
||
|
hr = ::SafeArrayGetLBound(psa, 1, &lower);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(L"can't get lower bound");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = ::SafeArrayGetUBound(psa, 1, &upper);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(L"can't get upper bound");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
for (long i = lower; i <= upper; ++i)
|
||
|
{
|
||
|
BSTR item;
|
||
|
hr = ::SafeArrayGetElement(psa, &i, &item);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG(String::format(L"index %1!d! failed", i));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (item)
|
||
|
{
|
||
|
stringList.push_back(String(item));
|
||
|
}
|
||
|
|
||
|
::SysFreeString(item);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
while (0);
|
||
|
|
||
|
LOG_HRESULT(hr);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|