Leaked source code of windows server 2003
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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: output.cpp
  7. //
  8. // Contents: Defines the functions which displays the query output
  9. // History: 05-OCT-2000 hiteshr Created
  10. //
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "pch.h"
  14. #include "cstrings.h"
  15. #include "usage.h"
  16. #include "gettable.h"
  17. #include "display.h"
  18. #include "query.h"
  19. #include "resource.h"
  20. #include "stdlib.h"
  21. #include "output.h"
  22. #include <sddl.h>
  23. HRESULT LocalCopyString(LPTSTR* ppResult, LPCTSTR pString)
  24. {
  25. if ( !ppResult || !pString )
  26. return E_INVALIDARG;
  27. //Security Review:pString is null terminated.
  28. *ppResult = (LPTSTR)LocalAlloc(LPTR, (wcslen(pString)+1)*sizeof(WCHAR) );
  29. if ( !*ppResult )
  30. return E_OUTOFMEMORY;
  31. //Correct buffer is allocated.
  32. lstrcpy(*ppResult, pString);
  33. return S_OK; // success
  34. }
  35. //+--------------------------------------------------------------------------
  36. //
  37. // Function: DisplayList
  38. //
  39. // Synopsis: Dispalys a name and value in list format.
  40. // Arguments: [szName - IN] : name of the attribute
  41. // [szValue - IN]: value of the attribute
  42. // [bShowAttribute - IN] : if true the attribute name will be
  43. // prepended to the output
  44. //
  45. //
  46. // History: 05-OCT-2000 hiteshr Created
  47. // 07-AUG-2001 jeffjon Added the bShowAttribute parameter
  48. //
  49. //---------------------------------------------------------------------------
  50. VOID DisplayList(LPCWSTR szName, LPCWSTR szValue, bool bShowAttributes = true)
  51. {
  52. if(!szName)
  53. return;
  54. CComBSTR strTemp;
  55. if (bShowAttributes)
  56. {
  57. strTemp = szName;
  58. strTemp += L": ";
  59. }
  60. if(szValue)
  61. strTemp += szValue;
  62. DisplayOutput(strTemp);
  63. }
  64. //+--------------------------------------------------------------------------
  65. //
  66. // Function: FindAttrInfoForName
  67. //
  68. // Synopsis: This function finds the ADS_ATTR_INFO associated with an
  69. // attribute name
  70. //
  71. // Arguments: [pAttrInfo IN] : Array of ADS_ATTR_INFOs
  72. // [dwAttrCount IN] : Count of attributes in array
  73. // [pszAttrName IN] : name of attribute to search for
  74. //
  75. // Returns: PADS_ATTR_INFO : pointer to the ADS_ATTR_INFO struct associated
  76. // with the attribute name, otherwise NULL
  77. //
  78. // History: 17-Oct-2000 JeffJon Created
  79. //
  80. //---------------------------------------------------------------------------
  81. PADS_ATTR_INFO FindAttrInfoForName(PADS_ATTR_INFO pAttrInfo,
  82. DWORD dwAttrCount,
  83. PCWSTR pszAttrName)
  84. {
  85. ENTER_FUNCTION(FULL_LOGGING, FindAttrInfoForName);
  86. PADS_ATTR_INFO pRetAttrInfo = 0;
  87. LPWSTR pRangeFound = NULL; // 702724 ronmart 2002/09/18 added for range support
  88. do // false loop
  89. {
  90. //
  91. // Validate Parameters
  92. //
  93. if (!pszAttrName)
  94. {
  95. ASSERT(pszAttrName);
  96. break;
  97. }
  98. //
  99. // If pAttrInfo is NULL then there is nothing to retrieve
  100. // that is acceptable if the value was not set
  101. //
  102. if (!pAttrInfo ||
  103. dwAttrCount == 0)
  104. {
  105. break;
  106. }
  107. for (DWORD dwIdx = 0; dwIdx < dwAttrCount; dwIdx++)
  108. {
  109. // 702724 ronmart 2002/09/18 See if a range qualifier has been specified
  110. pRangeFound = wcsstr(pAttrInfo[dwIdx].pszAttrName, g_pszRange);
  111. // If so, then terminate the string at the qualifer so that
  112. // the following comparision will only consider the attribute name
  113. if(pRangeFound)
  114. {
  115. pRangeFound[0] = 0;
  116. }
  117. //Security Review:Both are null terminated.
  118. if (_wcsicmp(pAttrInfo[dwIdx].pszAttrName, pszAttrName) == 0)
  119. {
  120. pRetAttrInfo = &(pAttrInfo[dwIdx]);
  121. break;
  122. }
  123. // If there wasn't a match and the item had a range qualifier
  124. // then restore the string
  125. if(pRangeFound)
  126. {
  127. pRangeFound[0] = g_pszRange[0];
  128. pRangeFound = NULL;
  129. }
  130. }
  131. } while (false);
  132. // All done so restore the string if a range qualifier was found
  133. if(pRangeFound)
  134. pRangeFound[0] = g_pszRange[0];
  135. return pRetAttrInfo;
  136. }
  137. //+--------------------------------------------------------------------------
  138. //
  139. // Function: DsGetOutputValuesList
  140. //
  141. // Synopsis: This function gets the values for the columns and then adds
  142. // the row to the format helper
  143. //
  144. // Arguments: [pszDN IN] : the DN of the object
  145. // [refBasePathsInfo IN] : reference to path info
  146. // [refCredentialObject IN] : reference to the credential manager
  147. // [pCommandArgs IN] : Command line arguments
  148. // [pObjectEntry IN] : Entry in the object table being processed
  149. // [dwAttrCount IN] : Number of arributes in above array
  150. // [pAttrInfo IN] : the values to display
  151. // [spDirObject IN] : Interface pointer to the object
  152. // [refFormatInfo IN]: Reference to the format helper
  153. //
  154. // Returns: HRESULT : S_OK if everything succeeded
  155. // E_INVALIDARG
  156. //
  157. // History: 16-Oct-2000 JeffJon Created
  158. //
  159. //---------------------------------------------------------------------------
  160. HRESULT DsGetOutputValuesList(PCWSTR pszDN,
  161. CDSCmdBasePathsInfo& refBasePathsInfo,
  162. const CDSCmdCredentialObject& refCredentialObject,
  163. PARG_RECORD pCommandArgs,
  164. PDSGetObjectTableEntry pObjectEntry,
  165. DWORD dwAttrCount,
  166. PADS_ATTR_INFO pAttrInfo,
  167. CComPtr<IDirectoryObject>& spDirObject,
  168. CFormatInfo& refFormatInfo)
  169. {
  170. ENTER_FUNCTION_HR(LEVEL5_LOGGING, DsGetOutputValuesList, hr);
  171. do // false loop
  172. {
  173. if(!pszDN ||
  174. !pCommandArgs ||
  175. !pObjectEntry)
  176. {
  177. ASSERT(pszDN);
  178. ASSERT(pCommandArgs);
  179. ASSERT(pObjectEntry);
  180. hr = E_INVALIDARG;
  181. break;
  182. }
  183. DWORD dwDisplayInfoArraySize = pObjectEntry->dwAttributeCount;
  184. if (pCommandArgs[eCommDN].bDefined)
  185. {
  186. dwDisplayInfoArraySize++;
  187. }
  188. PDSGET_DISPLAY_INFO pDisplayInfoArray = new CDSGetDisplayInfo[dwDisplayInfoArraySize];
  189. if (!pDisplayInfoArray)
  190. {
  191. hr = E_OUTOFMEMORY;
  192. break;
  193. }
  194. DWORD dwDisplayCount = 0;
  195. if (pCommandArgs[eCommDN].bDefined)
  196. {
  197. CComBSTR sbstrOutputDN;
  198. // NTRAID#NTBUG9-702418-2002/09/12-ronmart- The partition
  199. // object currently is not bound to the DN of the partition
  200. // but to the dn of the NTDS Quotas container of the
  201. // partition passed on the cmd line. This happens because
  202. // the current attributes to retrieve are quota container
  203. // attributes only. If the user passes the common -dn
  204. // flag on the cmd line then they should get back the
  205. // partition DN, not the quotas container dn
  206. if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszPartition))
  207. {
  208. // The NTDS Quotas container is a child of the parition
  209. // so this will retrieve the partition DN
  210. CComBSTR sbstrParentDN;
  211. hr = CPathCracker::GetParentDN(pszDN, sbstrParentDN);
  212. if (FAILED(hr))
  213. {
  214. ASSERT(FALSE);
  215. break;
  216. }
  217. hr = GetOutputDN( &sbstrOutputDN, sbstrParentDN);
  218. if (FAILED(hr))
  219. {
  220. ASSERT(FALSE);
  221. break;
  222. }
  223. }
  224. else
  225. {
  226. // JonN 5/10/01 256583 output DSCMD-escaped DN
  227. hr = GetOutputDN( &sbstrOutputDN, pszDN );
  228. if (FAILED(hr))
  229. {
  230. ASSERT(FALSE);
  231. break;
  232. }
  233. }
  234. pDisplayInfoArray[dwDisplayCount].SetDisplayName(g_pszArg1UserDN);
  235. pDisplayInfoArray[dwDisplayCount].AddValue(sbstrOutputDN);
  236. dwDisplayCount++;
  237. }
  238. //
  239. // Loop through the attributes getting their display values
  240. //
  241. for(DWORD i = 0; i < pObjectEntry->dwAttributeCount; i++)
  242. {
  243. if (pObjectEntry->pAttributeTable[i])
  244. {
  245. UINT nCommandEntry = pObjectEntry->pAttributeTable[i]->nAttributeID;
  246. if (pCommandArgs[nCommandEntry].bDefined &&
  247. pObjectEntry->pAttributeTable[i]->pDisplayStringFunc)
  248. {
  249. //
  250. // Find the ADS_ATTR_INFO structure associated with this attribute
  251. //
  252. PADS_ATTR_INFO pAttrInfoDisplay = NULL;
  253. if (pObjectEntry->pAttributeTable[i]->pszName)
  254. {
  255. pAttrInfoDisplay = FindAttrInfoForName(pAttrInfo,
  256. dwAttrCount,
  257. pObjectEntry->pAttributeTable[i]->pszName);
  258. }
  259. //
  260. // Fill in the column header even if there isn't a value
  261. //
  262. pDisplayInfoArray[dwDisplayCount].SetDisplayName(pCommandArgs[nCommandEntry].strArg1,
  263. !(pObjectEntry->pAttributeTable[i]->dwOutputFlags & DSGET_OUTPUT_DN_FLAG));
  264. //
  265. // Format the output strings
  266. // Note: this could actually involve some operation if the value isn't
  267. // retrieved by GetObjectAttributes (ie Can change password)
  268. //
  269. hr = pObjectEntry->pAttributeTable[i]->pDisplayStringFunc(pszDN,
  270. refBasePathsInfo,
  271. refCredentialObject,
  272. pObjectEntry,
  273. pCommandArgs,
  274. pAttrInfoDisplay,
  275. spDirObject,
  276. &(pDisplayInfoArray[dwDisplayCount]));
  277. if (FAILED(hr))
  278. {
  279. DEBUG_OUTPUT(LEVEL5_LOGGING,
  280. L"Failed display string func for %s: hr = 0x%x",
  281. pObjectEntry->pAttributeTable[i]->pszName,
  282. hr);
  283. }
  284. dwDisplayCount++;
  285. }
  286. }
  287. }
  288. DEBUG_OUTPUT(FULL_LOGGING, L"Attributes returned with values:");
  289. #ifdef DBG
  290. for (DWORD dwIdx = 0; dwIdx < dwDisplayCount; dwIdx++)
  291. {
  292. for (DWORD dwValue = 0; dwValue < pDisplayInfoArray[dwIdx].GetValueCount(); dwValue++)
  293. {
  294. if (pDisplayInfoArray[dwIdx].GetDisplayName() &&
  295. pDisplayInfoArray[dwIdx].GetValue(dwValue))
  296. {
  297. DEBUG_OUTPUT(FULL_LOGGING, L"\t%s = %s",
  298. pDisplayInfoArray[dwIdx].GetDisplayName(),
  299. pDisplayInfoArray[dwIdx].GetValue(dwValue));
  300. }
  301. else if (pDisplayInfoArray[dwIdx].GetDisplayName() &&
  302. !pDisplayInfoArray[dwIdx].GetValue(dwValue))
  303. {
  304. DEBUG_OUTPUT(FULL_LOGGING, L"\t%s = ",
  305. pDisplayInfoArray[dwIdx].GetDisplayName());
  306. }
  307. else if (!pDisplayInfoArray[dwIdx].GetDisplayName() &&
  308. pDisplayInfoArray[dwIdx].GetValue(dwValue))
  309. {
  310. DEBUG_OUTPUT(FULL_LOGGING, L"\t??? = %s",
  311. pDisplayInfoArray[dwIdx].GetValue(dwValue));
  312. }
  313. else
  314. {
  315. DEBUG_OUTPUT(FULL_LOGGING, L"\t??? = ???");
  316. }
  317. }
  318. }
  319. #endif
  320. hr = refFormatInfo.AddRow(pDisplayInfoArray, dwDisplayCount);
  321. } while (false);
  322. return hr;
  323. }
  324. //+--------------------------------------------------------------------------
  325. //
  326. // Function: GetStringFromADs
  327. //
  328. // Synopsis: Converts Value into string depending upon type
  329. // Arguments: [pValues - IN]: Value to be converted to string
  330. // [dwADsType-IN]: ADSTYPE of pValue
  331. // [pBuffer - OUT]:Output buffer which gets the string
  332. // [dwBufferLen-IN]:Size of output buffer
  333. // [pszAttrName-IN]:Name of the attribute being formatted
  334. // Returns HRESULT S_OK if Successful
  335. // E_INVALIDARG
  336. // Anything else is a failure code from an ADSI
  337. // call
  338. //
  339. //
  340. // History: 05-OCT-2000 hiteshr Created
  341. //
  342. //---------------------------------------------------------------------------
  343. HRESULT GetStringFromADs(IN const ADSVALUE *pValues,
  344. IN ADSTYPE dwADsType,
  345. OUT LPWSTR* ppBuffer,
  346. IN PCWSTR pszAttrName)
  347. {
  348. HRESULT hr = S_OK;
  349. if(!pValues || !ppBuffer)
  350. {
  351. ASSERT(FALSE);
  352. return E_INVALIDARG;
  353. }
  354. if( dwADsType == ADSTYPE_INVALID )
  355. {
  356. return E_INVALIDARG;
  357. }
  358. switch( dwADsType )
  359. {
  360. case ADSTYPE_DN_STRING :
  361. {
  362. CComBSTR sbstrOutputDN;
  363. hr = GetOutputDN( &sbstrOutputDN, pValues->DNString );
  364. if (FAILED(hr))
  365. return hr;
  366. // Quote output DNs so that they can be piped to other
  367. // commands
  368. sbstrOutputDN = GetQuotedDN(sbstrOutputDN);
  369. UINT length = sbstrOutputDN.Length();
  370. *ppBuffer = new WCHAR[length + 1];
  371. if (!(*ppBuffer))
  372. {
  373. hr = E_OUTOFMEMORY;
  374. return hr;
  375. }
  376. //Security Review:Correct Buffer size is passed.
  377. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  378. //Security Review:wcsncpy will copy length char
  379. //length + 1 is already set to zero so we are fine.
  380. wcsncpy(*ppBuffer, (BSTR)sbstrOutputDN, length);
  381. }
  382. break;
  383. case ADSTYPE_CASE_EXACT_STRING :
  384. {
  385. size_t length = wcslen(pValues->CaseExactString);
  386. *ppBuffer = new WCHAR[length + 1];
  387. if (!(*ppBuffer))
  388. {
  389. hr = E_OUTOFMEMORY;
  390. return hr;
  391. }
  392. //Security Review:Correct Buffer size is passed.
  393. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  394. //Security Review:wcsncpy will copy length char
  395. //length + 1 is already set to zero so we are fine.
  396. wcsncpy(*ppBuffer ,pValues->CaseExactString, length);
  397. }
  398. break;
  399. case ADSTYPE_CASE_IGNORE_STRING:
  400. {
  401. size_t length = wcslen(pValues->CaseIgnoreString);
  402. *ppBuffer = new WCHAR[length + 1];
  403. if (!(*ppBuffer))
  404. {
  405. hr = E_OUTOFMEMORY;
  406. return hr;
  407. }
  408. //Security Review:Correct Buffer size is passed.
  409. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  410. //Security Review:wcsncpy will copy length char
  411. //length + 1 is already set to zero so we are fine.
  412. wcsncpy(*ppBuffer ,pValues->CaseIgnoreString, length);
  413. }
  414. break;
  415. case ADSTYPE_PRINTABLE_STRING :
  416. {
  417. size_t length = wcslen(pValues->PrintableString);
  418. *ppBuffer = new WCHAR[length + 1];
  419. if (!(*ppBuffer))
  420. {
  421. hr = E_OUTOFMEMORY;
  422. return hr;
  423. }
  424. //Security Review:Correct Buffer size is passed.
  425. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  426. //Security Review:wcsncpy will copy length char
  427. //length + 1 is already set to zero so we are fine.
  428. wcsncpy(*ppBuffer ,pValues->PrintableString, length);
  429. }
  430. break;
  431. case ADSTYPE_NUMERIC_STRING :
  432. {
  433. size_t length = wcslen(pValues->NumericString);
  434. *ppBuffer = new WCHAR[length + 1];
  435. if (!(*ppBuffer))
  436. {
  437. hr = E_OUTOFMEMORY;
  438. return hr;
  439. }
  440. //Security Review:Correct Buffer size is passed.
  441. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  442. //Security Review:wcsncpy will copy length char
  443. //length + 1 is already set to zero so we are fine.
  444. wcsncpy(*ppBuffer ,pValues->NumericString, length);
  445. }
  446. break;
  447. case ADSTYPE_OBJECT_CLASS :
  448. {
  449. size_t length = wcslen(pValues->ClassName);
  450. *ppBuffer = new WCHAR[length + 1];
  451. if (!(*ppBuffer))
  452. {
  453. hr = E_OUTOFMEMORY;
  454. return hr;
  455. }
  456. //Security Review:Correct Buffer size is passed.
  457. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  458. //Security Review:wcsncpy will copy length char
  459. //length + 1 is already set to zero so we are fine.
  460. wcsncpy(*ppBuffer ,pValues->ClassName, length);
  461. }
  462. break;
  463. case ADSTYPE_BOOLEAN :
  464. {
  465. size_t length = 0;
  466. if (pValues->Boolean)
  467. {
  468. length = wcslen(L"TRUE");
  469. *ppBuffer = new WCHAR[length + 1];
  470. }
  471. else
  472. {
  473. length = wcslen(L"FALSE");
  474. *ppBuffer = new WCHAR[length + 1];
  475. }
  476. if (!(*ppBuffer))
  477. {
  478. hr = E_OUTOFMEMORY;
  479. return hr;
  480. }
  481. //Security Review:Correct Buffer size is passed.
  482. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  483. wcscpy(*ppBuffer ,((DWORD)pValues->Boolean) ? L"TRUE" : L"FALSE");
  484. }
  485. break;
  486. case ADSTYPE_INTEGER :
  487. // Just allocate too much...
  488. *ppBuffer = new WCHAR[MAXSTR];
  489. if (!(*ppBuffer))
  490. {
  491. hr = E_OUTOFMEMORY;
  492. return hr;
  493. }
  494. //Security Review:Correct Buffer size is passed.
  495. ZeroMemory(*ppBuffer, MAXSTR * sizeof(WCHAR));
  496. //Security Review:Usage is safe. Filed a generic bug to replace
  497. //wsprintf with strsafe api.
  498. //NTRAID#NTBUG9-574456-2002/03/12-hiteshr
  499. wsprintf(*ppBuffer ,L"%d", (DWORD) pValues->Integer);
  500. break;
  501. case ADSTYPE_OCTET_STRING :
  502. {
  503. BYTE b;
  504. WCHAR sOctet[128];
  505. DWORD dwLen = 0;
  506. // I am just going to limit the buffer to MAXSTR.
  507. // It will be a rare occasion when someone wants
  508. // to look at a binary string that is not a GUID
  509. // or a SID.
  510. *ppBuffer = new WCHAR[MAXSTR+1];
  511. if (!(*ppBuffer))
  512. {
  513. hr = E_OUTOFMEMORY;
  514. return hr;
  515. }
  516. //Security Review:Correct Buffer size is passed.
  517. ZeroMemory(*ppBuffer, (MAXSTR+1) * sizeof(WCHAR));
  518. //
  519. //Special case objectguid and objectsid attribute
  520. //
  521. //Security Review:pszAttrName is null terminated
  522. if(pszAttrName && !_wcsicmp(pszAttrName, L"objectguid"))
  523. {
  524. GUID *pguid = (GUID*)pValues->OctetString.lpValue;
  525. StringFromGUID2(*pguid,(LPOLESTR)*ppBuffer,MAXSTR);
  526. break;
  527. }
  528. //Security Review:pszAttrName is null terminated
  529. if(pszAttrName && !_wcsicmp(pszAttrName, L"objectsid"))
  530. {
  531. LPWSTR pszSid = NULL;
  532. PSID pSid = (PSID)pValues->OctetString.lpValue;
  533. if(ConvertSidToStringSid(pSid, &pszSid))
  534. {
  535. //Security Review:
  536. //NTRAID#NTBUG9-574385-2002/03/12-hiteshr
  537. wcsncpy(*ppBuffer,pszSid,MAXSTR); //Change ppBuffer size to MAXSTR+1, yanggao
  538. LocalFree(pszSid);
  539. break;
  540. }
  541. }
  542. for ( DWORD idx=0; idx<pValues->OctetString.dwLength; idx++)
  543. {
  544. b = ((BYTE *)pValues->OctetString.lpValue)[idx];
  545. //Security Review:Usage is safe. Filed a generic bug to replace
  546. //wsprintf with strsafe api.
  547. //NTRAID#NTBUG9-574456-2002/03/12-hiteshr
  548. wsprintf(sOctet,L"0x%02x ", b);
  549. //sOctet is null terminated.
  550. dwLen += static_cast<DWORD>(wcslen(sOctet));
  551. if(dwLen > (MAXSTR - 1) )
  552. break;
  553. else
  554. wcscat(*ppBuffer,sOctet);
  555. }
  556. }
  557. break;
  558. case ADSTYPE_LARGE_INTEGER :
  559. {
  560. CComBSTR strLarge;
  561. LARGE_INTEGER li = pValues->LargeInteger;
  562. litow(li, strLarge);
  563. UINT length = strLarge.Length();
  564. *ppBuffer = new WCHAR[length + 1];
  565. if (!(*ppBuffer))
  566. {
  567. hr = E_OUTOFMEMORY;
  568. return hr;
  569. }
  570. //Security Review:Correct Buffer size is passed.
  571. ZeroMemory(*ppBuffer, (length + 1) * sizeof(WCHAR));
  572. //Security Review:wcsncpy will copy length char
  573. //length + 1 is already set to zero so we are fine.
  574. wcsncpy(*ppBuffer,strLarge,length);
  575. }
  576. break;
  577. case ADSTYPE_UTC_TIME :
  578. // The longest date can be 20 characters including the NULL
  579. *ppBuffer = new WCHAR[20];
  580. if (!(*ppBuffer))
  581. {
  582. hr = E_OUTOFMEMORY;
  583. return hr;
  584. }
  585. ZeroMemory(*ppBuffer, sizeof(WCHAR) * 20);
  586. //Security Review:Usage is safe. Filed a generic bug to replace
  587. //wsprintf with strsafe api.
  588. //NTRAID#NTBUG9-574456-2002/03/12-hiteshr
  589. wsprintf(*ppBuffer,
  590. L"%02d/%02d/%04d %02d:%02d:%02d", pValues->UTCTime.wMonth, pValues->UTCTime.wDay, pValues->UTCTime.wYear,
  591. pValues->UTCTime.wHour, pValues->UTCTime.wMinute, pValues->UTCTime.wSecond
  592. );
  593. break;
  594. case ADSTYPE_NT_SECURITY_DESCRIPTOR: // I use the ACLEditor instead
  595. {
  596. //ISSUE:2000/01/05-hiteshr
  597. //I am not sure what to do with the NT_SECURITY_DESCRIPTOR and also
  598. //with someother datatypes not coverd by dsquery.
  599. }
  600. break;
  601. default :
  602. break;
  603. }
  604. return S_OK;
  605. }
  606. //+--------------------------------------------------------------------------
  607. //
  608. // Member: CFormatInfo::CFormatInfo
  609. //
  610. // Synopsis: Constructor for the format info class
  611. //
  612. // Arguments:
  613. //
  614. // Returns:
  615. //
  616. // History: 17-Oct-2000 JeffJon Created
  617. //
  618. //---------------------------------------------------------------------------
  619. CFormatInfo::CFormatInfo()
  620. : m_bInitialized(false),
  621. m_bListFormat(false),
  622. m_bQuiet(false),
  623. m_dwSampleSize(0),
  624. m_dwTotalRows(0),
  625. m_dwNumColumns(0),
  626. m_pColWidth(NULL),
  627. m_ppDisplayInfoArray(NULL)
  628. {};
  629. //+--------------------------------------------------------------------------
  630. //
  631. // Member: CFormatInfo::~CFormatInfo
  632. //
  633. // Synopsis: Destructor for the format info class
  634. //
  635. // Arguments:
  636. //
  637. // Returns:
  638. //
  639. // History: 17-Oct-2000 JeffJon Created
  640. //
  641. //---------------------------------------------------------------------------
  642. CFormatInfo::~CFormatInfo()
  643. {
  644. if (m_pColWidth)
  645. {
  646. delete[] m_pColWidth;
  647. m_pColWidth = NULL;
  648. }
  649. if (m_ppDisplayInfoArray)
  650. {
  651. delete[] m_ppDisplayInfoArray;
  652. m_ppDisplayInfoArray = NULL;
  653. }
  654. }
  655. //+--------------------------------------------------------------------------
  656. //
  657. // Member: CFormatInfo::Initialize
  658. //
  659. // Synopsis: Initializes the CFormatInfo object with the data
  660. //
  661. // Arguments: [dwSamplesSize IN] : Number of rows to use for formatting info
  662. // [bShowAsList IN] : Display should be in list or table format
  663. // [bQuiet IN] : Don't display anything to stdout
  664. //
  665. // Returns: HRESULT : S_OK if everything succeeded
  666. //
  667. // History: 17-Oct-2000 JeffJon Created
  668. //
  669. //---------------------------------------------------------------------------
  670. HRESULT CFormatInfo::Initialize(DWORD dwSampleSize,
  671. bool bShowAsList,
  672. bool bQuiet)
  673. {
  674. ENTER_FUNCTION_HR(LEVEL8_LOGGING, CFormatInfo::Initialize, hr);
  675. do // false loop
  676. {
  677. //
  678. // Validate Parameters
  679. //
  680. if(!dwSampleSize)
  681. {
  682. ASSERT(dwSampleSize);
  683. hr = E_INVALIDARG;
  684. break;
  685. }
  686. m_dwSampleSize = dwSampleSize;
  687. m_bListFormat = bShowAsList;
  688. m_bQuiet = bQuiet;
  689. //
  690. // Allocate the array of rows
  691. //
  692. m_ppDisplayInfoArray = new PDSGET_DISPLAY_INFO[m_dwSampleSize];
  693. if (!m_ppDisplayInfoArray)
  694. {
  695. hr = E_OUTOFMEMORY;
  696. break;
  697. }
  698. //Security Review:memset should take m_dwSampleSize*sizeof(PDSGET_DISPLAY_INFO);
  699. //NTRAID#NTBUG9-574395-2002/03/12-hiteshr, fixed, yanggao
  700. memset(m_ppDisplayInfoArray, 0, m_dwSampleSize*sizeof(PDSGET_DISPLAY_INFO));
  701. //
  702. // We are now initialized
  703. //
  704. m_bInitialized = true;
  705. } while (false);
  706. return hr;
  707. };
  708. //+--------------------------------------------------------------------------
  709. //
  710. // Member: CFormatInfo::AddRow
  711. //
  712. // Synopsis: Cache and update the columns for specified row
  713. //
  714. // Arguments: [pDisplayInfoArray IN] : Column headers and values
  715. // [dwColumnCount IN] : Number of columns
  716. //
  717. // Returns: HRESULT : S_OK if everything succeeded
  718. //
  719. // History: 17-Oct-2000 JeffJon Created
  720. //
  721. //---------------------------------------------------------------------------
  722. HRESULT CFormatInfo::AddRow(PDSGET_DISPLAY_INFO pDisplayInfo,
  723. DWORD dwColumnCount)
  724. {
  725. ENTER_FUNCTION_HR(LEVEL5_LOGGING, CFormatInfo::AddRow, hr);
  726. do // false loop
  727. {
  728. //
  729. // Make sure we have been initialized
  730. //
  731. if (!m_bInitialized)
  732. {
  733. DEBUG_OUTPUT(MINIMAL_LOGGING, L"CFormatInfo::Initialize has not been called yet!");
  734. ASSERT(m_bInitialized);
  735. hr = E_FAIL;
  736. break;
  737. }
  738. //
  739. // Verify parameters
  740. //
  741. if (!pDisplayInfo)
  742. {
  743. ASSERT(pDisplayInfo);
  744. hr = E_INVALIDARG;
  745. break;
  746. }
  747. if (m_bListFormat)
  748. {
  749. //
  750. // No reason to cache for the list format just output all the name/value pairs
  751. //
  752. for (DWORD dwIdx = 0; dwIdx < dwColumnCount; dwIdx++)
  753. {
  754. if (pDisplayInfo[dwIdx].GetValueCount())
  755. {
  756. for (DWORD dwValue = 0; dwValue < pDisplayInfo[dwIdx].GetValueCount(); dwValue++)
  757. {
  758. DisplayList(pDisplayInfo[dwIdx].GetDisplayName(),
  759. pDisplayInfo[dwIdx].GetValue(dwValue),
  760. pDisplayInfo[dwIdx].ShowAttribute());
  761. }
  762. }
  763. else
  764. {
  765. DisplayList(pDisplayInfo[dwIdx].GetDisplayName(),
  766. NULL,
  767. pDisplayInfo[dwIdx].ShowAttribute());
  768. }
  769. }
  770. NewLine();
  771. }
  772. else // table format
  773. {
  774. //
  775. // Set the row in the array
  776. //
  777. m_ppDisplayInfoArray[m_dwTotalRows] = pDisplayInfo;
  778. //
  779. // If this is the first row, update the column count
  780. // and allocate the column widths array
  781. //
  782. if (m_dwTotalRows == 0)
  783. {
  784. DEBUG_OUTPUT(LEVEL8_LOGGING,
  785. L"Initializing column count to %d",
  786. dwColumnCount);
  787. m_dwNumColumns = dwColumnCount;
  788. m_pColWidth = new DWORD[m_dwNumColumns];
  789. if (!m_pColWidth)
  790. {
  791. hr = E_OUTOFMEMORY;
  792. break;
  793. }
  794. //Security Review:memset should take m_dwNumColumns*sizeof(DWORD);
  795. //NTRAID#NTBUG9-574395-2002/03/12-hiteshr, fixed, yanggao
  796. memset(m_pColWidth, 0, sizeof(m_dwNumColumns*sizeof(DWORD)));
  797. //
  798. // Set the initial column widths from the column headers
  799. //
  800. for (DWORD dwIdx = 0; dwIdx < m_dwNumColumns; dwIdx++)
  801. {
  802. if (pDisplayInfo[dwIdx].GetDisplayName())
  803. {
  804. //Security Review:This is fine.
  805. m_pColWidth[dwIdx] = static_cast<DWORD>(wcslen(pDisplayInfo[dwIdx].GetDisplayName()));
  806. }
  807. else
  808. {
  809. ASSERT(false);
  810. DEBUG_OUTPUT(MINIMAL_LOGGING, L"The display name for column %d wasn't set!", dwIdx);
  811. }
  812. }
  813. }
  814. else
  815. {
  816. if (m_dwNumColumns != dwColumnCount)
  817. {
  818. DEBUG_OUTPUT(MINIMAL_LOGGING,
  819. L"Column count of new row (%d) does not equal the current column count (%d)",
  820. dwColumnCount,
  821. m_dwNumColumns);
  822. ASSERT(m_dwNumColumns == dwColumnCount);
  823. }
  824. }
  825. //
  826. // Go through the columns and update the widths if necessary
  827. //
  828. for (DWORD dwIdx = 0; dwIdx < m_dwNumColumns; dwIdx++)
  829. {
  830. for (DWORD dwValue = 0; dwValue < pDisplayInfo[dwIdx].GetValueCount(); dwValue++)
  831. {
  832. if (pDisplayInfo[dwIdx].GetValue(dwValue))
  833. {
  834. //This is fine.
  835. size_t sColWidth = wcslen(pDisplayInfo[dwIdx].GetValue(dwValue));
  836. m_pColWidth[dwIdx] = (DWORD)__max(sColWidth, m_pColWidth[dwIdx]);
  837. }
  838. }
  839. }
  840. //
  841. // Increment the row count
  842. //
  843. m_dwTotalRows++;
  844. }
  845. } while (false);
  846. return hr;
  847. }