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.
942 lines
31 KiB
942 lines
31 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 2000
|
|
//
|
|
// File: output.cpp
|
|
//
|
|
// Contents: Defines the functions which displays the query output
|
|
// History: 05-OCT-2000 hiteshr Created
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#include "cstrings.h"
|
|
#include "usage.h"
|
|
#include "gettable.h"
|
|
#include "display.h"
|
|
#include "query.h"
|
|
#include "resource.h"
|
|
#include "stdlib.h"
|
|
#include "output.h"
|
|
|
|
#include <sddl.h>
|
|
|
|
|
|
HRESULT LocalCopyString(LPTSTR* ppResult, LPCTSTR pString)
|
|
{
|
|
if ( !ppResult || !pString )
|
|
return E_INVALIDARG;
|
|
|
|
//Security Review:pString is null terminated.
|
|
*ppResult = (LPTSTR)LocalAlloc(LPTR, (wcslen(pString)+1)*sizeof(WCHAR) );
|
|
|
|
if ( !*ppResult )
|
|
return E_OUTOFMEMORY;
|
|
|
|
//Correct buffer is allocated.
|
|
lstrcpy(*ppResult, pString);
|
|
return S_OK; // success
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DisplayList
|
|
//
|
|
// Synopsis: Dispalys a name and value in list format.
|
|
// Arguments: [szName - IN] : name of the attribute
|
|
// [szValue - IN]: value of the attribute
|
|
// [bShowAttribute - IN] : if true the attribute name will be
|
|
// prepended to the output
|
|
//
|
|
//
|
|
// History: 05-OCT-2000 hiteshr Created
|
|
// 07-AUG-2001 jeffjon Added the bShowAttribute parameter
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
VOID DisplayList(LPCWSTR szName, LPCWSTR szValue, bool bShowAttributes = true)
|
|
{
|
|
if(!szName)
|
|
return;
|
|
CComBSTR strTemp;
|
|
|
|
if (bShowAttributes)
|
|
{
|
|
strTemp = szName;
|
|
strTemp += L": ";
|
|
}
|
|
if(szValue)
|
|
strTemp += szValue;
|
|
DisplayOutput(strTemp);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: FindAttrInfoForName
|
|
//
|
|
// Synopsis: This function finds the ADS_ATTR_INFO associated with an
|
|
// attribute name
|
|
//
|
|
// Arguments: [pAttrInfo IN] : Array of ADS_ATTR_INFOs
|
|
// [dwAttrCount IN] : Count of attributes in array
|
|
// [pszAttrName IN] : name of attribute to search for
|
|
//
|
|
// Returns: PADS_ATTR_INFO : pointer to the ADS_ATTR_INFO struct associated
|
|
// with the attribute name, otherwise NULL
|
|
//
|
|
// History: 17-Oct-2000 JeffJon Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
PADS_ATTR_INFO FindAttrInfoForName(PADS_ATTR_INFO pAttrInfo,
|
|
DWORD dwAttrCount,
|
|
PCWSTR pszAttrName)
|
|
{
|
|
ENTER_FUNCTION(FULL_LOGGING, FindAttrInfoForName);
|
|
|
|
PADS_ATTR_INFO pRetAttrInfo = 0;
|
|
LPWSTR pRangeFound = NULL; // 702724 ronmart 2002/09/18 added for range support
|
|
|
|
do // false loop
|
|
{
|
|
//
|
|
// Validate Parameters
|
|
//
|
|
if (!pszAttrName)
|
|
{
|
|
ASSERT(pszAttrName);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If pAttrInfo is NULL then there is nothing to retrieve
|
|
// that is acceptable if the value was not set
|
|
//
|
|
if (!pAttrInfo ||
|
|
dwAttrCount == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (DWORD dwIdx = 0; dwIdx < dwAttrCount; dwIdx++)
|
|
{
|
|
// 702724 ronmart 2002/09/18 See if a range qualifier has been specified
|
|
pRangeFound = wcsstr(pAttrInfo[dwIdx].pszAttrName, g_pszRange);
|
|
// If so, then terminate the string at the qualifer so that
|
|
// the following comparision will only consider the attribute name
|
|
if(pRangeFound)
|
|
{
|
|
pRangeFound[0] = 0;
|
|
}
|
|
|
|
//Security Review:Both are null terminated.
|
|
if (_wcsicmp(pAttrInfo[dwIdx].pszAttrName, pszAttrName) == 0)
|
|
{
|
|
pRetAttrInfo = &(pAttrInfo[dwIdx]);
|
|
break;
|
|
}
|
|
// If there wasn't a match and the item had a range qualifier
|
|
// then restore the string
|
|
if(pRangeFound)
|
|
{
|
|
pRangeFound[0] = g_pszRange[0];
|
|
pRangeFound = NULL;
|
|
}
|
|
|
|
}
|
|
} while (false);
|
|
|
|
// All done so restore the string if a range qualifier was found
|
|
if(pRangeFound)
|
|
pRangeFound[0] = g_pszRange[0];
|
|
|
|
return pRetAttrInfo;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DsGetOutputValuesList
|
|
//
|
|
// Synopsis: This function gets the values for the columns and then adds
|
|
// the row to the format helper
|
|
//
|
|
// Arguments: [pszDN IN] : the DN of the object
|
|
// [refBasePathsInfo IN] : reference to path info
|
|
// [refCredentialObject IN] : reference to the credential manager
|
|
// [pCommandArgs IN] : Command line arguments
|
|
// [pObjectEntry IN] : Entry in the object table being processed
|
|
// [dwAttrCount IN] : Number of arributes in above array
|
|
// [pAttrInfo IN] : the values to display
|
|
// [spDirObject IN] : Interface pointer to the object
|
|
// [refFormatInfo IN]: Reference to the format helper
|
|
//
|
|
// Returns: HRESULT : S_OK if everything succeeded
|
|
// E_INVALIDARG
|
|
//
|
|
// History: 16-Oct-2000 JeffJon Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT DsGetOutputValuesList(PCWSTR pszDN,
|
|
CDSCmdBasePathsInfo& refBasePathsInfo,
|
|
const CDSCmdCredentialObject& refCredentialObject,
|
|
PARG_RECORD pCommandArgs,
|
|
PDSGetObjectTableEntry pObjectEntry,
|
|
DWORD dwAttrCount,
|
|
PADS_ATTR_INFO pAttrInfo,
|
|
CComPtr<IDirectoryObject>& spDirObject,
|
|
CFormatInfo& refFormatInfo)
|
|
{
|
|
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DsGetOutputValuesList, hr);
|
|
|
|
do // false loop
|
|
{
|
|
if(!pszDN ||
|
|
!pCommandArgs ||
|
|
!pObjectEntry)
|
|
{
|
|
ASSERT(pszDN);
|
|
ASSERT(pCommandArgs);
|
|
ASSERT(pObjectEntry);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
|
|
DWORD dwDisplayInfoArraySize = pObjectEntry->dwAttributeCount;
|
|
if (pCommandArgs[eCommDN].bDefined)
|
|
{
|
|
dwDisplayInfoArraySize++;
|
|
}
|
|
|
|
PDSGET_DISPLAY_INFO pDisplayInfoArray = new CDSGetDisplayInfo[dwDisplayInfoArraySize];
|
|
if (!pDisplayInfoArray)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
DWORD dwDisplayCount = 0;
|
|
if (pCommandArgs[eCommDN].bDefined)
|
|
{
|
|
|
|
CComBSTR sbstrOutputDN;
|
|
|
|
// NTRAID#NTBUG9-702418-2002/09/12-ronmart- The partition
|
|
// object currently is not bound to the DN of the partition
|
|
// but to the dn of the NTDS Quotas container of the
|
|
// partition passed on the cmd line. This happens because
|
|
// the current attributes to retrieve are quota container
|
|
// attributes only. If the user passes the common -dn
|
|
// flag on the cmd line then they should get back the
|
|
// partition DN, not the quotas container dn
|
|
if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszPartition))
|
|
{
|
|
// The NTDS Quotas container is a child of the parition
|
|
// so this will retrieve the partition DN
|
|
CComBSTR sbstrParentDN;
|
|
hr = CPathCracker::GetParentDN(pszDN, sbstrParentDN);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
hr = GetOutputDN( &sbstrOutputDN, sbstrParentDN);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// JonN 5/10/01 256583 output DSCMD-escaped DN
|
|
hr = GetOutputDN( &sbstrOutputDN, pszDN );
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
pDisplayInfoArray[dwDisplayCount].SetDisplayName(g_pszArg1UserDN);
|
|
pDisplayInfoArray[dwDisplayCount].AddValue(sbstrOutputDN);
|
|
dwDisplayCount++;
|
|
}
|
|
|
|
//
|
|
// Loop through the attributes getting their display values
|
|
//
|
|
for(DWORD i = 0; i < pObjectEntry->dwAttributeCount; i++)
|
|
{
|
|
if (pObjectEntry->pAttributeTable[i])
|
|
{
|
|
UINT nCommandEntry = pObjectEntry->pAttributeTable[i]->nAttributeID;
|
|
if (pCommandArgs[nCommandEntry].bDefined &&
|
|
pObjectEntry->pAttributeTable[i]->pDisplayStringFunc)
|
|
{
|
|
//
|
|
// Find the ADS_ATTR_INFO structure associated with this attribute
|
|
//
|
|
PADS_ATTR_INFO pAttrInfoDisplay = NULL;
|
|
if (pObjectEntry->pAttributeTable[i]->pszName)
|
|
{
|
|
pAttrInfoDisplay = FindAttrInfoForName(pAttrInfo,
|
|
dwAttrCount,
|
|
pObjectEntry->pAttributeTable[i]->pszName);
|
|
}
|
|
|
|
//
|
|
// Fill in the column header even if there isn't a value
|
|
//
|
|
pDisplayInfoArray[dwDisplayCount].SetDisplayName(pCommandArgs[nCommandEntry].strArg1,
|
|
!(pObjectEntry->pAttributeTable[i]->dwOutputFlags & DSGET_OUTPUT_DN_FLAG));
|
|
|
|
//
|
|
// Format the output strings
|
|
// Note: this could actually involve some operation if the value isn't
|
|
// retrieved by GetObjectAttributes (ie Can change password)
|
|
//
|
|
hr = pObjectEntry->pAttributeTable[i]->pDisplayStringFunc(pszDN,
|
|
refBasePathsInfo,
|
|
refCredentialObject,
|
|
pObjectEntry,
|
|
pCommandArgs,
|
|
pAttrInfoDisplay,
|
|
spDirObject,
|
|
&(pDisplayInfoArray[dwDisplayCount]));
|
|
if (FAILED(hr))
|
|
{
|
|
DEBUG_OUTPUT(LEVEL5_LOGGING,
|
|
L"Failed display string func for %s: hr = 0x%x",
|
|
pObjectEntry->pAttributeTable[i]->pszName,
|
|
hr);
|
|
}
|
|
dwDisplayCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DEBUG_OUTPUT(FULL_LOGGING, L"Attributes returned with values:");
|
|
|
|
#ifdef DBG
|
|
for (DWORD dwIdx = 0; dwIdx < dwDisplayCount; dwIdx++)
|
|
{
|
|
for (DWORD dwValue = 0; dwValue < pDisplayInfoArray[dwIdx].GetValueCount(); dwValue++)
|
|
{
|
|
if (pDisplayInfoArray[dwIdx].GetDisplayName() &&
|
|
pDisplayInfoArray[dwIdx].GetValue(dwValue))
|
|
{
|
|
DEBUG_OUTPUT(FULL_LOGGING, L"\t%s = %s",
|
|
pDisplayInfoArray[dwIdx].GetDisplayName(),
|
|
pDisplayInfoArray[dwIdx].GetValue(dwValue));
|
|
}
|
|
else if (pDisplayInfoArray[dwIdx].GetDisplayName() &&
|
|
!pDisplayInfoArray[dwIdx].GetValue(dwValue))
|
|
{
|
|
DEBUG_OUTPUT(FULL_LOGGING, L"\t%s = ",
|
|
pDisplayInfoArray[dwIdx].GetDisplayName());
|
|
}
|
|
else if (!pDisplayInfoArray[dwIdx].GetDisplayName() &&
|
|
pDisplayInfoArray[dwIdx].GetValue(dwValue))
|
|
{
|
|
DEBUG_OUTPUT(FULL_LOGGING, L"\t??? = %s",
|
|
pDisplayInfoArray[dwIdx].GetValue(dwValue));
|
|
}
|
|
else
|
|
{
|
|
DEBUG_OUTPUT(FULL_LOGGING, L"\t??? = ???");
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
hr = refFormatInfo.AddRow(pDisplayInfoArray, dwDisplayCount);
|
|
|
|
} while (false);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetStringFromADs
|
|
//
|
|
// Synopsis: Converts Value into string depending upon type
|
|
// Arguments: [pValues - IN]: Value to be converted to string
|
|
// [dwADsType-IN]: ADSTYPE of pValue
|
|
// [pBuffer - OUT]:Output buffer which gets the string
|
|
// [dwBufferLen-IN]:Size of output buffer
|
|
// [pszAttrName-IN]:Name of the attribute being formatted
|
|
// Returns HRESULT S_OK if Successful
|
|
// E_INVALIDARG
|
|
// Anything else is a failure code from an ADSI
|
|
// call
|
|
//
|
|
//
|
|
// History: 05-OCT-2000 hiteshr Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT GetStringFromADs(IN const ADSVALUE *pValues,
|
|
IN ADSTYPE dwADsType,
|
|
OUT LPWSTR* ppBuffer,
|
|
IN PCWSTR pszAttrName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(!pValues || !ppBuffer)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if( dwADsType == ADSTYPE_INVALID )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
switch( dwADsType )
|
|
{
|
|
case ADSTYPE_DN_STRING :
|
|
{
|
|
CComBSTR sbstrOutputDN;
|
|
hr = GetOutputDN( &sbstrOutputDN, pValues->DNString );
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// Quote output DNs so that they can be piped to other
|
|
// commands
|
|
|
|
sbstrOutputDN = GetQuotedDN(sbstrOutputDN);
|
|
|
|
UINT length = sbstrOutputDN.Length();
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer, (BSTR)sbstrOutputDN, length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_CASE_EXACT_STRING :
|
|
{
|
|
size_t length = wcslen(pValues->CaseExactString);
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer ,pValues->CaseExactString, length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_CASE_IGNORE_STRING:
|
|
{
|
|
size_t length = wcslen(pValues->CaseIgnoreString);
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer ,pValues->CaseIgnoreString, length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_PRINTABLE_STRING :
|
|
{
|
|
size_t length = wcslen(pValues->PrintableString);
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer ,pValues->PrintableString, length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_NUMERIC_STRING :
|
|
{
|
|
size_t length = wcslen(pValues->NumericString);
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer ,pValues->NumericString, length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_OBJECT_CLASS :
|
|
{
|
|
size_t length = wcslen(pValues->ClassName);
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer ,pValues->ClassName, length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_BOOLEAN :
|
|
{
|
|
size_t length = 0;
|
|
if (pValues->Boolean)
|
|
{
|
|
length = wcslen(L"TRUE");
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
}
|
|
else
|
|
{
|
|
length = wcslen(L"FALSE");
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
}
|
|
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
wcscpy(*ppBuffer ,((DWORD)pValues->Boolean) ? L"TRUE" : L"FALSE");
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_INTEGER :
|
|
// Just allocate too much...
|
|
*ppBuffer = new WCHAR[MAXSTR];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, MAXSTR * sizeof(WCHAR));
|
|
//Security Review:Usage is safe. Filed a generic bug to replace
|
|
//wsprintf with strsafe api.
|
|
//NTRAID#NTBUG9-574456-2002/03/12-hiteshr
|
|
|
|
wsprintf(*ppBuffer ,L"%d", (DWORD) pValues->Integer);
|
|
break;
|
|
|
|
case ADSTYPE_OCTET_STRING :
|
|
{
|
|
BYTE b;
|
|
WCHAR sOctet[128];
|
|
DWORD dwLen = 0;
|
|
|
|
// I am just going to limit the buffer to MAXSTR.
|
|
// It will be a rare occasion when someone wants
|
|
// to look at a binary string that is not a GUID
|
|
// or a SID.
|
|
*ppBuffer = new WCHAR[MAXSTR+1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (MAXSTR+1) * sizeof(WCHAR));
|
|
|
|
//
|
|
//Special case objectguid and objectsid attribute
|
|
//
|
|
//Security Review:pszAttrName is null terminated
|
|
if(pszAttrName && !_wcsicmp(pszAttrName, L"objectguid"))
|
|
{
|
|
GUID *pguid = (GUID*)pValues->OctetString.lpValue;
|
|
StringFromGUID2(*pguid,(LPOLESTR)*ppBuffer,MAXSTR);
|
|
break;
|
|
}
|
|
//Security Review:pszAttrName is null terminated
|
|
if(pszAttrName && !_wcsicmp(pszAttrName, L"objectsid"))
|
|
{
|
|
LPWSTR pszSid = NULL;
|
|
PSID pSid = (PSID)pValues->OctetString.lpValue;
|
|
if(ConvertSidToStringSid(pSid, &pszSid))
|
|
{
|
|
//Security Review:
|
|
//NTRAID#NTBUG9-574385-2002/03/12-hiteshr
|
|
wcsncpy(*ppBuffer,pszSid,MAXSTR); //Change ppBuffer size to MAXSTR+1, yanggao
|
|
LocalFree(pszSid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for ( DWORD idx=0; idx<pValues->OctetString.dwLength; idx++)
|
|
{
|
|
b = ((BYTE *)pValues->OctetString.lpValue)[idx];
|
|
//Security Review:Usage is safe. Filed a generic bug to replace
|
|
//wsprintf with strsafe api.
|
|
//NTRAID#NTBUG9-574456-2002/03/12-hiteshr
|
|
|
|
wsprintf(sOctet,L"0x%02x ", b);
|
|
//sOctet is null terminated.
|
|
dwLen += static_cast<DWORD>(wcslen(sOctet));
|
|
if(dwLen > (MAXSTR - 1) )
|
|
break;
|
|
else
|
|
wcscat(*ppBuffer,sOctet);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_LARGE_INTEGER :
|
|
{
|
|
CComBSTR strLarge;
|
|
LARGE_INTEGER li = pValues->LargeInteger;
|
|
litow(li, strLarge);
|
|
|
|
UINT length = strLarge.Length();
|
|
*ppBuffer = new WCHAR[length + 1];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
//Security Review:Correct Buffer size is passed.
|
|
ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
|
|
//Security Review:wcsncpy will copy length char
|
|
//length + 1 is already set to zero so we are fine.
|
|
wcsncpy(*ppBuffer,strLarge,length);
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_UTC_TIME :
|
|
// The longest date can be 20 characters including the NULL
|
|
*ppBuffer = new WCHAR[20];
|
|
if (!(*ppBuffer))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
ZeroMemory(*ppBuffer, sizeof(WCHAR) * 20);
|
|
//Security Review:Usage is safe. Filed a generic bug to replace
|
|
//wsprintf with strsafe api.
|
|
//NTRAID#NTBUG9-574456-2002/03/12-hiteshr
|
|
wsprintf(*ppBuffer,
|
|
L"%02d/%02d/%04d %02d:%02d:%02d", pValues->UTCTime.wMonth, pValues->UTCTime.wDay, pValues->UTCTime.wYear,
|
|
pValues->UTCTime.wHour, pValues->UTCTime.wMinute, pValues->UTCTime.wSecond
|
|
);
|
|
break;
|
|
|
|
case ADSTYPE_NT_SECURITY_DESCRIPTOR: // I use the ACLEditor instead
|
|
{
|
|
//ISSUE:2000/01/05-hiteshr
|
|
//I am not sure what to do with the NT_SECURITY_DESCRIPTOR and also
|
|
//with someother datatypes not coverd by dsquery.
|
|
}
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormatInfo::CFormatInfo
|
|
//
|
|
// Synopsis: Constructor for the format info class
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 17-Oct-2000 JeffJon Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
CFormatInfo::CFormatInfo()
|
|
: m_bInitialized(false),
|
|
m_bListFormat(false),
|
|
m_bQuiet(false),
|
|
m_dwSampleSize(0),
|
|
m_dwTotalRows(0),
|
|
m_dwNumColumns(0),
|
|
m_pColWidth(NULL),
|
|
m_ppDisplayInfoArray(NULL)
|
|
{};
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormatInfo::~CFormatInfo
|
|
//
|
|
// Synopsis: Destructor for the format info class
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 17-Oct-2000 JeffJon Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
CFormatInfo::~CFormatInfo()
|
|
{
|
|
if (m_pColWidth)
|
|
{
|
|
delete[] m_pColWidth;
|
|
m_pColWidth = NULL;
|
|
}
|
|
|
|
if (m_ppDisplayInfoArray)
|
|
{
|
|
delete[] m_ppDisplayInfoArray;
|
|
m_ppDisplayInfoArray = NULL;
|
|
}
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormatInfo::Initialize
|
|
//
|
|
// Synopsis: Initializes the CFormatInfo object with the data
|
|
//
|
|
// Arguments: [dwSamplesSize IN] : Number of rows to use for formatting info
|
|
// [bShowAsList IN] : Display should be in list or table format
|
|
// [bQuiet IN] : Don't display anything to stdout
|
|
//
|
|
// Returns: HRESULT : S_OK if everything succeeded
|
|
//
|
|
// History: 17-Oct-2000 JeffJon Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CFormatInfo::Initialize(DWORD dwSampleSize,
|
|
bool bShowAsList,
|
|
bool bQuiet)
|
|
{
|
|
ENTER_FUNCTION_HR(LEVEL8_LOGGING, CFormatInfo::Initialize, hr);
|
|
|
|
do // false loop
|
|
{
|
|
//
|
|
// Validate Parameters
|
|
//
|
|
if(!dwSampleSize)
|
|
{
|
|
ASSERT(dwSampleSize);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
m_dwSampleSize = dwSampleSize;
|
|
m_bListFormat = bShowAsList;
|
|
m_bQuiet = bQuiet;
|
|
|
|
//
|
|
// Allocate the array of rows
|
|
//
|
|
m_ppDisplayInfoArray = new PDSGET_DISPLAY_INFO[m_dwSampleSize];
|
|
if (!m_ppDisplayInfoArray)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
//Security Review:memset should take m_dwSampleSize*sizeof(PDSGET_DISPLAY_INFO);
|
|
//NTRAID#NTBUG9-574395-2002/03/12-hiteshr, fixed, yanggao
|
|
memset(m_ppDisplayInfoArray, 0, m_dwSampleSize*sizeof(PDSGET_DISPLAY_INFO));
|
|
|
|
//
|
|
// We are now initialized
|
|
//
|
|
m_bInitialized = true;
|
|
} while (false);
|
|
|
|
return hr;
|
|
};
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CFormatInfo::AddRow
|
|
//
|
|
// Synopsis: Cache and update the columns for specified row
|
|
//
|
|
// Arguments: [pDisplayInfoArray IN] : Column headers and values
|
|
// [dwColumnCount IN] : Number of columns
|
|
//
|
|
// Returns: HRESULT : S_OK if everything succeeded
|
|
//
|
|
// History: 17-Oct-2000 JeffJon Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CFormatInfo::AddRow(PDSGET_DISPLAY_INFO pDisplayInfo,
|
|
DWORD dwColumnCount)
|
|
{
|
|
ENTER_FUNCTION_HR(LEVEL5_LOGGING, CFormatInfo::AddRow, hr);
|
|
|
|
do // false loop
|
|
{
|
|
//
|
|
// Make sure we have been initialized
|
|
//
|
|
if (!m_bInitialized)
|
|
{
|
|
DEBUG_OUTPUT(MINIMAL_LOGGING, L"CFormatInfo::Initialize has not been called yet!");
|
|
ASSERT(m_bInitialized);
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Verify parameters
|
|
//
|
|
if (!pDisplayInfo)
|
|
{
|
|
ASSERT(pDisplayInfo);
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
if (m_bListFormat)
|
|
{
|
|
//
|
|
// No reason to cache for the list format just output all the name/value pairs
|
|
//
|
|
for (DWORD dwIdx = 0; dwIdx < dwColumnCount; dwIdx++)
|
|
{
|
|
if (pDisplayInfo[dwIdx].GetValueCount())
|
|
{
|
|
for (DWORD dwValue = 0; dwValue < pDisplayInfo[dwIdx].GetValueCount(); dwValue++)
|
|
{
|
|
DisplayList(pDisplayInfo[dwIdx].GetDisplayName(),
|
|
pDisplayInfo[dwIdx].GetValue(dwValue),
|
|
pDisplayInfo[dwIdx].ShowAttribute());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DisplayList(pDisplayInfo[dwIdx].GetDisplayName(),
|
|
NULL,
|
|
pDisplayInfo[dwIdx].ShowAttribute());
|
|
}
|
|
}
|
|
NewLine();
|
|
}
|
|
else // table format
|
|
{
|
|
//
|
|
// Set the row in the array
|
|
//
|
|
m_ppDisplayInfoArray[m_dwTotalRows] = pDisplayInfo;
|
|
|
|
//
|
|
// If this is the first row, update the column count
|
|
// and allocate the column widths array
|
|
//
|
|
if (m_dwTotalRows == 0)
|
|
{
|
|
DEBUG_OUTPUT(LEVEL8_LOGGING,
|
|
L"Initializing column count to %d",
|
|
dwColumnCount);
|
|
|
|
m_dwNumColumns = dwColumnCount;
|
|
|
|
m_pColWidth = new DWORD[m_dwNumColumns];
|
|
if (!m_pColWidth)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
//Security Review:memset should take m_dwNumColumns*sizeof(DWORD);
|
|
//NTRAID#NTBUG9-574395-2002/03/12-hiteshr, fixed, yanggao
|
|
memset(m_pColWidth, 0, sizeof(m_dwNumColumns*sizeof(DWORD)));
|
|
|
|
//
|
|
// Set the initial column widths from the column headers
|
|
//
|
|
for (DWORD dwIdx = 0; dwIdx < m_dwNumColumns; dwIdx++)
|
|
{
|
|
if (pDisplayInfo[dwIdx].GetDisplayName())
|
|
{
|
|
//Security Review:This is fine.
|
|
m_pColWidth[dwIdx] = static_cast<DWORD>(wcslen(pDisplayInfo[dwIdx].GetDisplayName()));
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
DEBUG_OUTPUT(MINIMAL_LOGGING, L"The display name for column %d wasn't set!", dwIdx);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (m_dwNumColumns != dwColumnCount)
|
|
{
|
|
DEBUG_OUTPUT(MINIMAL_LOGGING,
|
|
L"Column count of new row (%d) does not equal the current column count (%d)",
|
|
dwColumnCount,
|
|
m_dwNumColumns);
|
|
ASSERT(m_dwNumColumns == dwColumnCount);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go through the columns and update the widths if necessary
|
|
//
|
|
for (DWORD dwIdx = 0; dwIdx < m_dwNumColumns; dwIdx++)
|
|
{
|
|
for (DWORD dwValue = 0; dwValue < pDisplayInfo[dwIdx].GetValueCount(); dwValue++)
|
|
{
|
|
if (pDisplayInfo[dwIdx].GetValue(dwValue))
|
|
{
|
|
//This is fine.
|
|
size_t sColWidth = wcslen(pDisplayInfo[dwIdx].GetValue(dwValue));
|
|
m_pColWidth[dwIdx] = (DWORD)__max(sColWidth, m_pColWidth[dwIdx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Increment the row count
|
|
//
|
|
m_dwTotalRows++;
|
|
}
|
|
} while (false);
|
|
|
|
return hr;
|
|
}
|
|
|