windows-nt/Source/XPSP1/NT/admin/dscmd/util.cpp
2020-09-26 16:20:57 +08:00

617 lines
16 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: Util.cpp
//
// Contents: Generic utility functions and classes for dscmd
//
// History: 01-Oct-2000 JeffJon Created
//
//--------------------------------------------------------------------------
#include "pch.h"
#include "util.h"
#ifdef DBG
//
// Globals
//
CDebugSpew DebugSpew;
//+--------------------------------------------------------------------------
//
// Member: CDebugSpew::EnterFunction
//
// Synopsis: Outputs "Enter " followed by the function name (or any passed
// in string) and then calls Indent so that any output is indented
//
// Arguments: [nDebugLevel - IN] : the level at which this output should
// be spewed
// [pszFunction - IN] : a string to output to the console which
// is proceeded by "Entering "
//
// Returns:
//
// History: 01-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CDebugSpew::EnterFunction(UINT nDebugLevel, PCWSTR pszFunction)
{
//
// Verify input parameter
//
if (!pszFunction)
{
ASSERT(pszFunction);
return;
}
CComBSTR sbstrOutput(L"Entering ");
sbstrOutput += pszFunction;
//
// Output the debug spew
//
Output(nDebugLevel, sbstrOutput);
//
// Indent
//
Indent();
}
//+--------------------------------------------------------------------------
//
// Member: CDebugSpew::LeaveFunction
//
// Synopsis: Outputs "Exit " followed by the function name (or any passed
// in string) and then calls Outdent
//
// Arguments: [nDebugLevel - IN] : the level at which this output should
// be spewed
// [pszFunction - IN] : a string to output to the console which
// is proceeded by "Leaving "
//
// Returns:
//
// History: 01-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CDebugSpew::LeaveFunction(UINT nDebugLevel, PCWSTR pszFunction)
{
//
// Verify input parameter
//
if (!pszFunction)
{
ASSERT(pszFunction);
return;
}
//
// Outdent
//
Outdent();
CComBSTR sbstrOutput(L"Leaving ");
sbstrOutput += pszFunction;
//
// Output the debug spew
//
Output(nDebugLevel, sbstrOutput);
}
//+--------------------------------------------------------------------------
//
// Member: CDebugSpew::LeaveFunctionHr
//
// Synopsis: Outputs "Exit " followed by the function name (or any passed
// in string), the HRESULT return value, and then calls Outdent
//
// Arguments: [nDebugLevel - IN] : the level at which this output should
// be spewed
// [pszFunction - IN] : a string to output to the console which
// is proceeded by "Leaving "
// [hr - IN] : the HRESULT result value that is being
// returned by the function
//
// Returns:
//
// History: 01-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CDebugSpew::LeaveFunctionHr(UINT nDebugLevel, PCWSTR pszFunction, HRESULT hr)
{
//
// Verify input parameter
//
if (!pszFunction)
{
ASSERT(pszFunction);
return;
}
//
// Outdent
//
Outdent();
CComBSTR sbstrOutput(L"Leaving ");
sbstrOutput += pszFunction;
//
// Append the return value
//
WCHAR pszReturn[30];
wsprintf(pszReturn, L" returning 0x%x", hr);
sbstrOutput += pszReturn;
//
// Output the debug spew
//
Output(nDebugLevel, sbstrOutput);
}
//+--------------------------------------------------------------------------
//
// Member: OsName
//
// Synopsis: Returns a readable string of the platform
//
// Arguments: [refInfo IN] : reference the OS version info structure
// retrieved from GetVersionEx()
//
// Returns: PWSTR : returns a pointer to static text describing the
// platform. The returned string does not have to
// be freed.
//
// History: 20-Dec-2000 JeffJon Created
//
//---------------------------------------------------------------------------
PWSTR OsName(const OSVERSIONINFO& refInfo)
{
switch (refInfo.dwPlatformId)
{
case VER_PLATFORM_WIN32s:
{
return L"Win32s on Windows 3.1";
}
case VER_PLATFORM_WIN32_WINDOWS:
{
switch (refInfo.dwMinorVersion)
{
case 0:
{
return L"Windows 95";
}
case 1:
{
return L"Windows 98";
}
default:
{
return L"Windows 9X";
}
}
}
case VER_PLATFORM_WIN32_NT:
{
return L"Windows NT";
}
default:
{
ASSERT(false);
break;
}
}
return L"Some Unknown Windows Version";
}
//+--------------------------------------------------------------------------
//
// Member: CDebugSpew::SpewHeader
//
// Synopsis: Outputs debug information like command line and build info
//
// Arguments:
//
// Returns:
//
// History: 20-Dec-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CDebugSpew::SpewHeader()
{
//
// First output the command line
//
PWSTR pszCommandLine = GetCommandLine();
if (pszCommandLine)
{
Output(MINIMAL_LOGGING,
L"Command line: %s",
GetCommandLine());
}
//
// Output the module being used
//
do // false loop
{
//
// Get the file path
//
WCHAR pszFileName[MAX_PATH + 1];
::ZeroMemory(pszFileName, sizeof(pszFileName));
if (::GetModuleFileNameW(::GetModuleHandle(NULL), pszFileName, MAX_PATH) == 0)
{
break;
}
Output(MINIMAL_LOGGING,
L"Module: %s",
pszFileName);
//
// get the file attributes
//
WIN32_FILE_ATTRIBUTE_DATA attr;
::ZeroMemory(&attr, sizeof(attr));
if (::GetFileAttributesEx(pszFileName, GetFileExInfoStandard, &attr) == 0)
{
break;
}
//
// convert the filetime to a system time
//
FILETIME localtime;
::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &localtime);
SYSTEMTIME systime;
::FileTimeToSystemTime(&localtime, &systime);
//
// output the timestamp
//
Output(MINIMAL_LOGGING,
L"Timestamp: %2d/%2d/%4d %2d:%2d:%d.%d",
systime.wMonth,
systime.wDay,
systime.wYear,
systime.wHour,
systime.wMinute,
systime.wSecond,
systime.wMilliseconds);
} while (false);
//
// Get the system info
//
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
BOOL success = ::GetVersionEx(&info);
ASSERT(success);
//
// Get the Whistler build lab version
//
CComBSTR sbstrLabInfo;
do // false loop
{
HKEY key = 0;
LONG err = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion",
0,
KEY_READ,
&key);
if (err != ERROR_SUCCESS)
{
break;
}
WCHAR buf[MAX_PATH + 1];
::ZeroMemory(buf, sizeof(buf));
DWORD type = 0;
DWORD bufSize = MAX_PATH + 1;
err = ::RegQueryValueEx(key,
L"BuildLab",
0,
&type,
reinterpret_cast<BYTE*>(buf),
&bufSize);
if (err != ERROR_SUCCESS)
{
break;
}
sbstrLabInfo = buf;
} while (false);
Output(MINIMAL_LOGGING,
L"Build: %s %d.%d build %d %s (BuildLab:%s)",
OsName(info),
info.dwMajorVersion,
info.dwMinorVersion,
info.dwBuildNumber,
info.szCSDVersion,
sbstrLabInfo);
//
// Output a blank line to separate the header from the rest of the output
//
Output(MINIMAL_LOGGING,
L"\n");
}
//+--------------------------------------------------------------------------
//
// Member: CDebugSpew::Output
//
// Synopsis: Outputs the passed in string to stdout proceeded by the number
// of spaces specified by GetIndent()
//
// Arguments: [nDebugLevel - IN] : the level at which this output should
// be spewed
// [pszOutput - IN] : a format string to output to the console
// [... - IN] : a variable argument list to be formatted
// into pszOutput similar to wprintf
//
// Returns:
//
// History: 01-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CDebugSpew::Output(UINT nDebugLevel, PCWSTR pszOutput, ...)
{
if (nDebugLevel <= GetDebugLevel())
{
//
// Verify parameters
//
if (!pszOutput)
{
ASSERT(pszOutput);
return;
}
va_list args;
va_start(args, pszOutput);
int nBuf;
WCHAR szBuffer[1024];
nBuf = _vsnwprintf(szBuffer, sizeof(szBuffer)/sizeof(WCHAR), pszOutput, args);
CComBSTR sbstrOutput;
//
// Insert the spaces for the indent
//
for (UINT nCount = 0; nCount < GetIndent(); nCount++)
{
sbstrOutput += L" ";
}
//
// Append the output string
//
sbstrOutput += szBuffer;
//
// Output the results
//
WriteStandardOut(L"%s\n", sbstrOutput);
va_end(args);
}
}
#endif // DBG
//+--------------------------------------------------------------------------
//
// Macro: MyA2WHelper
//
// Synopsis: Converts a string from Ansi to Unicode in the OEM codepage
//
// Arguments: [lpw - IN/OUT] : buffer to receive the Unicode string
// [lpa - IN] : Ansi string to be converted
// [nChars - IN] : maximum number of characters that can fit in the buffer
// [acp - IN] : the codepage to use
//
// Returns: PWSTR : the Unicode string in the OEM codepage
//
// History: 04-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
inline PWSTR WINAPI MyA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
{
ATLASSERT(lpa != NULL);
ATLASSERT(lpw != NULL);
// verify that no illegal character present
// since lpw was allocated based on the size of lpa
// don't worry about the number of chars
lpw[0] = '\0';
MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
return lpw;
}
//+--------------------------------------------------------------------------
//
// Macro: A2W_OEM
//
// Synopsis: Converts a string from Ansi to Unicode in the OEM codepage
//
// Arguments: [lpa - IN] : the string to be converted
//
// Returns: PWSTR : the Unicode string in the OEM codepage
//
// History: 04-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
#define A2W_OEM(lpa) (\
((_lpaMine = lpa) == NULL) ? NULL : (\
_convert = (lstrlenA(_lpaMine)+1),\
MyA2WHelper((LPWSTR) alloca(_convert*2), _lpaMine, _convert, CP_OEMCP)))
//+--------------------------------------------------------------------------
//
// Function: _UnicodeToOemConvert
//
// Synopsis: takes the passed in string (pszUnicode) and converts it to
// the OEM code page
//
// Arguments: [pszUnicode - IN] : the string to be converted
// [sbstrOemUnicode - OUT] : the converted string
//
// Returns:
//
// History: 04-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void _UnicodeToOemConvert(PCWSTR pszUnicode, CComBSTR& sbstrOemUnicode)
{
USES_CONVERSION;
//
// add this for the macro to work
//
LPCSTR _lpaMine = NULL;
//
// convert to CHAR OEM
//
int nLen = lstrlen(pszUnicode);
LPSTR pszOemAnsi = new CHAR[3*(nLen+1)]; // more, to be sure...
if (pszOemAnsi)
{
CharToOem(pszUnicode, pszOemAnsi);
//
// convert it back to WCHAR on OEM CP
//
sbstrOemUnicode = A2W_OEM(pszOemAnsi);
delete[] pszOemAnsi;
pszOemAnsi = 0;
}
}
//+--------------------------------------------------------------------------
//
// Function: SpewAttrs(ADS_ATTR_INFO* pCreateAttrs, DWORD dwNumAttrs);
//
// Synopsis: Uses the DEBUG_OUTPUT macro to output the attributes and the
// values specified
//
// Arguments: [pAttrs - IN] : The ADS_ATTR_INFO
// [dwNumAttrs - IN] : The number of attributes in pAttrs
//
// Returns:
//
// History: 04-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
#ifdef DBG
void SpewAttrs(ADS_ATTR_INFO* pAttrs, DWORD dwNumAttrs)
{
for (DWORD dwAttrIdx = 0; dwAttrIdx < dwNumAttrs; dwAttrIdx++)
{
if (pAttrs[dwAttrIdx].dwADsType == ADSTYPE_DN_STRING ||
pAttrs[dwAttrIdx].dwADsType == ADSTYPE_CASE_EXACT_STRING ||
pAttrs[dwAttrIdx].dwADsType == ADSTYPE_CASE_IGNORE_STRING ||
pAttrs[dwAttrIdx].dwADsType == ADSTYPE_PRINTABLE_STRING)
{
for (DWORD dwValueIdx = 0; dwValueIdx < pAttrs[dwAttrIdx].dwNumValues; dwValueIdx++)
{
if (pAttrs[dwAttrIdx].pADsValues[dwValueIdx].CaseIgnoreString)
{
DEBUG_OUTPUT(FULL_LOGGING, L" %s = %s",
pAttrs[dwAttrIdx].pszAttrName,
pAttrs[dwAttrIdx].pADsValues[dwValueIdx].CaseIgnoreString);
}
else
{
DEBUG_OUTPUT(FULL_LOGGING, L" %s = value being cleared",
pAttrs[dwAttrIdx].pszAttrName);
}
}
}
}
}
#endif // DBG
//+--------------------------------------------------------------------------
//
// Function: litow
//
// Synopsis:
//
// Arguments: [li - IN] : reference to large integer to be converted to string
// [sResult - OUT] : Gets the output string
// Returns: void
//
// History: 25-Sep-2000 hiteshr Created
// Copied from dsadmin code base, changed work with CComBSTR
//---------------------------------------------------------------------------
void litow(LARGE_INTEGER& li, CComBSTR& sResult)
{
LARGE_INTEGER n;
n.QuadPart = li.QuadPart;
if (n.QuadPart == 0)
{
sResult = L"0";
}
else
{
CComBSTR sNeg;
sResult = L"";
if (n.QuadPart < 0)
{
sNeg = CComBSTR(L'-');
n.QuadPart *= -1;
}
while (n.QuadPart > 0)
{
WCHAR ch[2];
ch[0] = static_cast<WCHAR>(L'0' + static_cast<WCHAR>(n.QuadPart % 10));
ch[1] = L'\0';
sResult += ch;
n.QuadPart = n.QuadPart / 10;
}
sResult += sNeg;
}
//Reverse the string
WCHAR szTemp[256];
wcscpy(szTemp,sResult);
LPWSTR pStart,pEnd;
pStart = szTemp;
pEnd = pStart + wcslen(pStart) -1;
while(pStart < pEnd)
{
WCHAR ch = *pStart;
*pStart++ = *pEnd;
*pEnd-- = ch;
}
sResult = szTemp;
}