|
|
//+-------------------------------------------------------------------------
//
// 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]; //Security Review:Enough buffer is provided.
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));
//Security Review:If the path is MAX_PATH long, API will return MAX_PATH and won't
//NULL terminate, but we are fine since we allocated buffer of size MAX_PATH + 1
//and set it to Zero
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 = sizeof(WCHAR)*MAX_PATH; //NTRAID#NTBUG9-573572-2002/05/24, yanggao, bufSize is the size in bytes according to RegQueryValueEx.
//In order to terminate the returned value, give it value sizeof(WCHAR)*MAX_PATH.
//Security Review: when buffers match the exact length of data
//value data is not null terminated.
//NTRAID#NTBUG9-573572-2002/03/12-hiteshr
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"\r\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);
WCHAR szBuffer[1024];
//Security Review:Check for the return value of function and also
//consider replacing it with strsafe api.
//NTRAID#NTBUG9-573602-2002/03/12-hiteshr
if(FAILED(StringCchVPrintf(szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]), pszOutput, args))) return;
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\r\n", sbstrOutput);
va_end(args); } }
#endif // DBG
//+--------------------------------------------------------------------------
//
// Macro: MyA2WHelper
//
// Synopsis: Converts a string from Ansi to Unicode in the OEM codepage
//
// Arguments: [lpa - IN] : Ansi string to be converted
// [acp - IN] : the codepage to use
//
// Returns: PWSTR : the Unicode string in the OEM codepage. Caller
// must free the returned pointer using delete[]
//
// History: 04-Oct-2000 JeffJon Created
//
//---------------------------------------------------------------------------
inline PWSTR WINAPI MyA2WHelper(LPCSTR lpa, UINT acp) { ASSERT(lpa != NULL);
// Use MultiByteToWideChar without a buffer to find out the required
// size
PWSTR wideString = 0;
int result = MultiByteToWideChar(acp, 0, lpa, -1, 0, 0); if (result) { wideString = new WCHAR[result]; if (wideString) { result = MultiByteToWideChar(acp, 0, lpa, -1, wideString, result); } } return wideString; }
//+--------------------------------------------------------------------------
//
// 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) { if (!pszUnicode) { ASSERT(pszUnicode); return; }
// Use WideCharToMultiByte without a buffer to find out
// the required size
int result = WideCharToMultiByte( CP_OEMCP, 0, pszUnicode, -1, 0, 0, 0, 0);
if (result) { // Now allocate and convert the string
PSTR pszOemAnsi = new CHAR[result]; if (pszOemAnsi) { ZeroMemory(pszOemAnsi, result * sizeof(CHAR));
result = WideCharToMultiByte( CP_OEMCP, 0, pszUnicode, -1, pszOemAnsi, result * sizeof(CHAR), 0, 0);
ASSERT(result);
//
// convert it back to WCHAR on OEM CP
//
PWSTR oemUnicode = MyA2WHelper(pszOemAnsi, CP_OEMCP); if (oemUnicode) { sbstrOemUnicode = oemUnicode; delete[] oemUnicode; oemUnicode = 0; } 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
//Security Review:256 is good enough for largest LARGE_INTEGER.
//But since limit of string is known, a good case for using strsafe api.
//NTRAID#NTBUG9-577081-2002/03/12-hiteshr
WCHAR szTemp[256]; if(SUCCEEDED(StringCchCopy(szTemp, 256, sResult))) { LPWSTR pStart,pEnd; pStart = szTemp; //Security Review Done.
pEnd = pStart + wcslen(pStart) -1; while(pStart < pEnd) { WCHAR ch = *pStart; *pStart++ = *pEnd; *pEnd-- = ch; } sResult = szTemp; } }
//+--------------------------------------------------------------------------
//
// Function: EncryptPasswordString
//
// Synopsis:Encrypts a password.
//
// Arguments:[pszPassword - IN] : Input Password. Input password must be
// smaller than MAX_PASSWORD_LENGTH chars in length. Function
// doesnot modify this string.
//
// [pEncryptedDataBlob - OUT] : Gets the output encrypted
// datablob.
// Returns: HRESULT
//
// History: 27-March-2002 hiteshr Created
//---------------------------------------------------------------------------
HRESULT EncryptPasswordString(IN LPCWSTR pszPassword, OUT DATA_BLOB *pEncryptedDataBlob) {
if(!pszPassword || !pEncryptedDataBlob) { ASSERT(pszPassword); ASSERT(pEncryptedDataBlob); return E_POINTER; }
HRESULT hr = S_OK; do { //Vaidate the length of input password. MAX_PASSWORD_LENGTH includes terminating
//NULL character.
size_t len = 0; hr = StringCchLength(pszPassword, MAX_PASSWORD_LENGTH, &len); if(FAILED(hr)) { hr = E_INVALIDARG; break; }
DATA_BLOB inDataBlob; inDataBlob.pbData = (BYTE*)pszPassword; inDataBlob.cbData = (DWORD)(len + 1)*sizeof(WCHAR);
//Encrypt data
if(!CryptProtectData(&inDataBlob, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, pEncryptedDataBlob)) { pEncryptedDataBlob->pbData = NULL; DWORD dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); break; }
}while(0);
return hr; }
//+--------------------------------------------------------------------------
//
// Function: DecryptPasswordString
//
// Synopsis: Decrypt encrypted password data.
//
// Arguments: [pEncryptedDataBlob- IN] : Input encrypted password data.
// [ppszPassword - OUT] :Gets the output decrypted password.
// This must be freed using LocalFree
// Returns: HRESULT
//
// History: 27-March-2002 hiteshr Created
//---------------------------------------------------------------------------
HRESULT DecryptPasswordString(IN const DATA_BLOB* pEncryptedDataBlob, OUT LPWSTR *ppszPassword) { if(!pEncryptedDataBlob || !ppszPassword) { ASSERT(pEncryptedDataBlob); ASSERT(ppszPassword); return E_POINTER; }
HRESULT hr = S_OK; do {
DATA_BLOB decryptedDataBlob; if(!CryptUnprotectData((DATA_BLOB*)pEncryptedDataBlob, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &decryptedDataBlob)) { DWORD dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); break; }
*ppszPassword = (LPWSTR)decryptedDataBlob.pbData; }while(0);
return hr; }
|