Source code of Windows XP (NT5)
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.

681 lines
21 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. HRESULT LocalCopyString(LPTSTR* ppResult, LPCTSTR pString)
  23. {
  24. if ( !ppResult || !pString )
  25. return E_INVALIDARG;
  26. *ppResult = (LPTSTR)LocalAlloc(LPTR, (wcslen(pString)+1)*sizeof(WCHAR) );
  27. if ( !*ppResult )
  28. return E_OUTOFMEMORY;
  29. lstrcpy(*ppResult, pString);
  30. return S_OK; // success
  31. }
  32. //+--------------------------------------------------------------------------
  33. //
  34. // Function: DisplayList
  35. //
  36. // Synopsis: Dispalys a name and value in list format.
  37. // Arguments: [szName - IN] : name of the attribute
  38. // [szValue - IN]: value of the attribute
  39. //
  40. //
  41. // History: 05-OCT-2000 hiteshr Created
  42. //
  43. //---------------------------------------------------------------------------
  44. VOID DisplayList(LPCWSTR szName, LPCWSTR szValue)
  45. {
  46. if(!szName)
  47. return;
  48. CComBSTR strTemp;
  49. strTemp = szName;
  50. strTemp += L": ";
  51. if(szValue)
  52. strTemp += szValue;
  53. DisplayOutput(strTemp);
  54. }
  55. //+--------------------------------------------------------------------------
  56. //
  57. // Function: FindAttrInfoForName
  58. //
  59. // Synopsis: This function finds the ADS_ATTR_INFO associated with an
  60. // attribute name
  61. //
  62. // Arguments: [pAttrInfo IN] : Array of ADS_ATTR_INFOs
  63. // [dwAttrCount IN] : Count of attributes in array
  64. // [pszAttrName IN] : name of attribute to search for
  65. //
  66. // Returns: PADS_ATTR_INFO : pointer to the ADS_ATTR_INFO struct associated
  67. // with the attribute name, otherwise NULL
  68. //
  69. // History: 17-Oct-2000 JeffJon Created
  70. //
  71. //---------------------------------------------------------------------------
  72. PADS_ATTR_INFO FindAttrInfoForName(PADS_ATTR_INFO pAttrInfo,
  73. DWORD dwAttrCount,
  74. PCWSTR pszAttrName)
  75. {
  76. ENTER_FUNCTION(FULL_LOGGING, FindAttrInfoForName);
  77. PADS_ATTR_INFO pRetAttrInfo = 0;
  78. do // false loop
  79. {
  80. //
  81. // Validate Parameters
  82. //
  83. if (!pszAttrName)
  84. {
  85. ASSERT(pszAttrName);
  86. break;
  87. }
  88. //
  89. // If pAttrInfo is NULL then there is nothing to retrieve
  90. // that is acceptable if the value was not set
  91. //
  92. if (!pAttrInfo ||
  93. dwAttrCount == 0)
  94. {
  95. break;
  96. }
  97. for (DWORD dwIdx = 0; dwIdx < dwAttrCount; dwIdx++)
  98. {
  99. if (_wcsicmp(pAttrInfo[dwIdx].pszAttrName, pszAttrName) == 0)
  100. {
  101. pRetAttrInfo = &(pAttrInfo[dwIdx]);
  102. break;
  103. }
  104. }
  105. } while (false);
  106. return pRetAttrInfo;
  107. }
  108. //+--------------------------------------------------------------------------
  109. //
  110. // Function: DsGetOutputValuesList
  111. //
  112. // Synopsis: This function gets the values for the columns and then adds
  113. // the row to the format helper
  114. //
  115. // Arguments: [pszDN IN] : the DN of the object
  116. // [refBasePathsInfo IN] : reference to path info
  117. // [refCredentialObject IN] : reference to the credential manager
  118. // [pCommandArgs IN] : Command line arguments
  119. // [pObjectEntry IN] : Entry in the object table being processed
  120. // [dwAttrCount IN] : Number of arributes in above array
  121. // [pAttrInfo IN] : the values to display
  122. // [spDirObject IN] : Interface pointer to the object
  123. // [refFormatInfo IN]: Reference to the format helper
  124. //
  125. // Returns: HRESULT : S_OK if everything succeeded
  126. // E_INVALIDARG
  127. //
  128. // History: 16-Oct-2000 JeffJon Created
  129. //
  130. //---------------------------------------------------------------------------
  131. HRESULT DsGetOutputValuesList(PCWSTR pszDN,
  132. CDSCmdBasePathsInfo& refBasePathsInfo,
  133. const CDSCmdCredentialObject& refCredentialObject,
  134. PARG_RECORD pCommandArgs,
  135. PDSGetObjectTableEntry pObjectEntry,
  136. DWORD dwAttrCount,
  137. PADS_ATTR_INFO pAttrInfo,
  138. CComPtr<IDirectoryObject>& spDirObject,
  139. CFormatInfo& refFormatInfo)
  140. {
  141. ENTER_FUNCTION_HR(LEVEL5_LOGGING, DsGetOutputValuesList, hr);
  142. do // false loop
  143. {
  144. if(!pszDN ||
  145. !pCommandArgs ||
  146. !pObjectEntry)
  147. {
  148. ASSERT(pszDN);
  149. ASSERT(pCommandArgs);
  150. ASSERT(pObjectEntry);
  151. hr = E_INVALIDARG;
  152. break;
  153. }
  154. DWORD dwDisplayInfoArraySize = pObjectEntry->dwAttributeCount;
  155. if (pCommandArgs[eCommDN].bDefined)
  156. {
  157. dwDisplayInfoArraySize++;
  158. }
  159. PDSGET_DISPLAY_INFO pDisplayInfoArray = new CDSGetDisplayInfo[dwDisplayInfoArraySize];
  160. if (!pDisplayInfoArray)
  161. {
  162. hr = E_OUTOFMEMORY;
  163. break;
  164. }
  165. DWORD dwDisplayCount = 0;
  166. if (pCommandArgs[eCommDN].bDefined)
  167. {
  168. // JonN 5/10/01 256583 output DSCMD-escaped DN
  169. CComBSTR sbstrOutputDN;
  170. hr = GetOutputDN( &sbstrOutputDN, pszDN );
  171. if (FAILED(hr))
  172. {
  173. ASSERT(FALSE);
  174. break;
  175. }
  176. pDisplayInfoArray[dwDisplayCount].SetDisplayName(g_pszArg1UserDN);
  177. pDisplayInfoArray[dwDisplayCount].AddValue(sbstrOutputDN);
  178. dwDisplayCount++;
  179. }
  180. //
  181. // Loop through the attributes getting their display values
  182. //
  183. for(DWORD i = 0; i < pObjectEntry->dwAttributeCount; i++)
  184. {
  185. if (pObjectEntry->pAttributeTable[i])
  186. {
  187. UINT nCommandEntry = pObjectEntry->pAttributeTable[i]->nAttributeID;
  188. if (pCommandArgs[nCommandEntry].bDefined &&
  189. pObjectEntry->pAttributeTable[i]->pDisplayStringFunc)
  190. {
  191. //
  192. // Find the ADS_ATTR_INFO structure associated with this attribute
  193. //
  194. PADS_ATTR_INFO pAttrInfoDisplay = NULL;
  195. if (pObjectEntry->pAttributeTable[i]->pszName)
  196. {
  197. pAttrInfoDisplay = FindAttrInfoForName(pAttrInfo,
  198. dwAttrCount,
  199. pObjectEntry->pAttributeTable[i]->pszName);
  200. }
  201. //
  202. // Fill in the column header even if there isn't a value
  203. //
  204. pDisplayInfoArray[dwDisplayCount].SetDisplayName(pCommandArgs[nCommandEntry].strArg1);
  205. //
  206. // Format the output strings
  207. // Note: this could actually involve some operation if the value isn't
  208. // retrieved by GetObjectAttributes (ie Can change password)
  209. //
  210. hr = pObjectEntry->pAttributeTable[i]->pDisplayStringFunc(pszDN,
  211. refBasePathsInfo,
  212. refCredentialObject,
  213. pObjectEntry,
  214. pCommandArgs,
  215. pAttrInfoDisplay,
  216. spDirObject,
  217. &(pDisplayInfoArray[dwDisplayCount]));
  218. if (FAILED(hr))
  219. {
  220. DEBUG_OUTPUT(LEVEL5_LOGGING,
  221. L"Failed display string func for %s: hr = 0x%x",
  222. pObjectEntry->pAttributeTable[i]->pszName,
  223. hr);
  224. }
  225. dwDisplayCount++;
  226. }
  227. }
  228. }
  229. DEBUG_OUTPUT(FULL_LOGGING, L"Attributes returned with values:");
  230. #ifdef DBG
  231. for (DWORD dwIdx = 0; dwIdx < dwDisplayCount; dwIdx++)
  232. {
  233. for (DWORD dwValue = 0; dwValue < pDisplayInfoArray[dwIdx].GetValueCount(); dwValue++)
  234. {
  235. if (pDisplayInfoArray[dwIdx].GetDisplayName() &&
  236. pDisplayInfoArray[dwIdx].GetValue(dwValue))
  237. {
  238. DEBUG_OUTPUT(FULL_LOGGING, L"\t%s = %s",
  239. pDisplayInfoArray[dwIdx].GetDisplayName(),
  240. pDisplayInfoArray[dwIdx].GetValue(dwValue));
  241. }
  242. else if (pDisplayInfoArray[dwIdx].GetDisplayName() &&
  243. !pDisplayInfoArray[dwIdx].GetValue(dwValue))
  244. {
  245. DEBUG_OUTPUT(FULL_LOGGING, L"\t%s = ",
  246. pDisplayInfoArray[dwIdx].GetDisplayName());
  247. }
  248. else if (!pDisplayInfoArray[dwIdx].GetDisplayName() &&
  249. pDisplayInfoArray[dwIdx].GetValue(dwValue))
  250. {
  251. DEBUG_OUTPUT(FULL_LOGGING, L"\t??? = %s",
  252. pDisplayInfoArray[dwIdx].GetValue(dwValue));
  253. }
  254. else
  255. {
  256. DEBUG_OUTPUT(FULL_LOGGING, L"\t??? = ???");
  257. }
  258. }
  259. }
  260. #endif
  261. hr = refFormatInfo.AddRow(pDisplayInfoArray, dwDisplayCount);
  262. } while (false);
  263. return hr;
  264. }
  265. //+--------------------------------------------------------------------------
  266. //
  267. // Function: GetStringFromADs
  268. //
  269. // Synopsis: Converts Value into string depending upon type
  270. // Arguments: [pValues - IN]: Value to be converted to string
  271. // [dwADsType-IN]: ADSTYPE of pValue
  272. // [pBuffer - OUT]:Output buffer which gets the string
  273. // [dwBufferLen-IN]:Size of output buffer
  274. // Returns HRESULT S_OK if Successful
  275. // E_INVALIDARG
  276. // Anything else is a failure code from an ADSI
  277. // call
  278. //
  279. //
  280. // History: 05-OCT-2000 hiteshr Created
  281. //
  282. //---------------------------------------------------------------------------
  283. HRESULT GetStringFromADs(IN const ADSVALUE *pValues,
  284. IN ADSTYPE dwADsType,
  285. OUT LPWSTR pBuffer,
  286. IN DWORD dwBufferLen)
  287. {
  288. if(!pValues || !pBuffer || !dwBufferLen)
  289. {
  290. ASSERT(FALSE);
  291. return E_INVALIDARG;
  292. }
  293. pBuffer[0] = 0;
  294. if( dwADsType == ADSTYPE_INVALID )
  295. {
  296. return E_INVALIDARG;
  297. }
  298. switch( dwADsType )
  299. {
  300. case ADSTYPE_DN_STRING :
  301. {
  302. CComBSTR sbstrOutputDN;
  303. HRESULT hr = GetOutputDN( &sbstrOutputDN, pValues->DNString );
  304. if (FAILED(hr))
  305. return hr;
  306. wcsncpy(pBuffer, (BSTR)sbstrOutputDN, dwBufferLen-1);
  307. }
  308. break;
  309. case ADSTYPE_CASE_EXACT_STRING :
  310. wcsncpy(pBuffer ,pValues->CaseExactString, dwBufferLen-1);
  311. break;
  312. case ADSTYPE_CASE_IGNORE_STRING:
  313. wcsncpy(pBuffer ,pValues->CaseIgnoreString, dwBufferLen-1);
  314. break;
  315. case ADSTYPE_PRINTABLE_STRING :
  316. wcsncpy(pBuffer ,pValues->PrintableString, dwBufferLen-1);
  317. break;
  318. case ADSTYPE_NUMERIC_STRING :
  319. wcsncpy(pBuffer ,pValues->NumericString, dwBufferLen-1);
  320. break;
  321. case ADSTYPE_OBJECT_CLASS :
  322. wcsncpy(pBuffer ,pValues->ClassName, dwBufferLen-1);
  323. break;
  324. case ADSTYPE_BOOLEAN :
  325. wsprintf(pBuffer ,L"%s", ((DWORD)pValues->Boolean) ? L"TRUE" : L"FALSE");
  326. break;
  327. case ADSTYPE_INTEGER :
  328. wsprintf(pBuffer ,L"%d", (DWORD) pValues->Integer);
  329. break;
  330. case ADSTYPE_OCTET_STRING :
  331. {
  332. BYTE b;
  333. WCHAR sOctet[128];
  334. DWORD dwLen = 0;
  335. for ( DWORD idx=0; idx<pValues->OctetString.dwLength; idx++)
  336. {
  337. b = ((BYTE *)pValues->OctetString.lpValue)[idx];
  338. wsprintf(sOctet,L"0x%02x ", b);
  339. dwLen += static_cast<DWORD>(wcslen(sOctet));
  340. if(dwLen > (dwBufferLen - 1) )
  341. break;
  342. else
  343. wcscat(pBuffer,sOctet);
  344. }
  345. }
  346. break;
  347. case ADSTYPE_LARGE_INTEGER :
  348. {
  349. CComBSTR strLarge;
  350. LARGE_INTEGER li = pValues->LargeInteger;
  351. litow(li, strLarge);
  352. wcsncpy(pBuffer,strLarge,dwBufferLen-1);
  353. }
  354. break;
  355. case ADSTYPE_UTC_TIME :
  356. wsprintf(pBuffer,
  357. L"%02d/%02d/%04d %02d:%02d:%02d", pValues->UTCTime.wMonth, pValues->UTCTime.wDay, pValues->UTCTime.wYear,
  358. pValues->UTCTime.wHour, pValues->UTCTime.wMinute, pValues->UTCTime.wSecond
  359. );
  360. break;
  361. case ADSTYPE_NT_SECURITY_DESCRIPTOR: // I use the ACLEditor instead
  362. {
  363. //ISSUE:2000/01/05-hiteshr
  364. //I am not sure what to do with the NT_SECURITY_DESCRIPTOR and also
  365. //with someother datatypes not coverd by dsquery.
  366. }
  367. break;
  368. default :
  369. break;
  370. }
  371. return S_OK;
  372. }
  373. //+--------------------------------------------------------------------------
  374. //
  375. // Member: CFormatInfo::CFormatInfo
  376. //
  377. // Synopsis: Constructor for the format info class
  378. //
  379. // Arguments:
  380. //
  381. // Returns:
  382. //
  383. // History: 17-Oct-2000 JeffJon Created
  384. //
  385. //---------------------------------------------------------------------------
  386. CFormatInfo::CFormatInfo()
  387. : m_bInitialized(false),
  388. m_bListFormat(false),
  389. m_bQuiet(false),
  390. m_dwSampleSize(0),
  391. m_dwTotalRows(0),
  392. m_dwNumColumns(0),
  393. m_pColWidth(NULL),
  394. m_ppDisplayInfoArray(NULL)
  395. {};
  396. //+--------------------------------------------------------------------------
  397. //
  398. // Member: CFormatInfo::~CFormatInfo
  399. //
  400. // Synopsis: Destructor for the format info class
  401. //
  402. // Arguments:
  403. //
  404. // Returns:
  405. //
  406. // History: 17-Oct-2000 JeffJon Created
  407. //
  408. //---------------------------------------------------------------------------
  409. CFormatInfo::~CFormatInfo()
  410. {
  411. if (m_pColWidth)
  412. {
  413. delete[] m_pColWidth;
  414. m_pColWidth = NULL;
  415. }
  416. if (m_ppDisplayInfoArray)
  417. {
  418. delete[] m_ppDisplayInfoArray;
  419. m_ppDisplayInfoArray = NULL;
  420. }
  421. }
  422. //+--------------------------------------------------------------------------
  423. //
  424. // Member: CFormatInfo::Initialize
  425. //
  426. // Synopsis: Initializes the CFormatInfo object with the data
  427. //
  428. // Arguments: [dwSamplesSize IN] : Number of rows to use for formatting info
  429. // [bShowAsList IN] : Display should be in list or table format
  430. // [bQuiet IN] : Don't display anything to stdout
  431. //
  432. // Returns: HRESULT : S_OK if everything succeeded
  433. //
  434. // History: 17-Oct-2000 JeffJon Created
  435. //
  436. //---------------------------------------------------------------------------
  437. HRESULT CFormatInfo::Initialize(DWORD dwSampleSize,
  438. bool bShowAsList,
  439. bool bQuiet)
  440. {
  441. ENTER_FUNCTION_HR(LEVEL8_LOGGING, CFormatInfo::Initialize, hr);
  442. do // false loop
  443. {
  444. //
  445. // Validate Parameters
  446. //
  447. if(!dwSampleSize)
  448. {
  449. ASSERT(dwSampleSize);
  450. hr = E_INVALIDARG;
  451. break;
  452. }
  453. m_dwSampleSize = dwSampleSize;
  454. m_bListFormat = bShowAsList;
  455. m_bQuiet = bQuiet;
  456. //
  457. // Allocate the array of rows
  458. //
  459. m_ppDisplayInfoArray = new PDSGET_DISPLAY_INFO[m_dwSampleSize];
  460. if (!m_ppDisplayInfoArray)
  461. {
  462. hr = E_OUTOFMEMORY;
  463. break;
  464. }
  465. memset(m_ppDisplayInfoArray, 0, sizeof(m_ppDisplayInfoArray));
  466. //
  467. // We are now initialized
  468. //
  469. m_bInitialized = true;
  470. } while (false);
  471. return hr;
  472. };
  473. //+--------------------------------------------------------------------------
  474. //
  475. // Member: CFormatInfo::AddRow
  476. //
  477. // Synopsis: Cache and update the columns for specified row
  478. //
  479. // Arguments: [pDisplayInfoArray IN] : Column headers and values
  480. // [dwColumnCount IN] : Number of columns
  481. //
  482. // Returns: HRESULT : S_OK if everything succeeded
  483. //
  484. // History: 17-Oct-2000 JeffJon Created
  485. //
  486. //---------------------------------------------------------------------------
  487. HRESULT CFormatInfo::AddRow(PDSGET_DISPLAY_INFO pDisplayInfo,
  488. DWORD dwColumnCount)
  489. {
  490. ENTER_FUNCTION_HR(LEVEL5_LOGGING, CFormatInfo::AddRow, hr);
  491. do // false loop
  492. {
  493. //
  494. // Make sure we have been initialized
  495. //
  496. if (!m_bInitialized)
  497. {
  498. DEBUG_OUTPUT(MINIMAL_LOGGING, L"CFormatInfo::Initialize has not been called yet!");
  499. ASSERT(m_bInitialized);
  500. hr = E_FAIL;
  501. break;
  502. }
  503. //
  504. // Verify parameters
  505. //
  506. if (!pDisplayInfo)
  507. {
  508. ASSERT(pDisplayInfo);
  509. hr = E_INVALIDARG;
  510. break;
  511. }
  512. if (m_bListFormat)
  513. {
  514. //
  515. // No reason to cache for the list format just output all the name/value pairs
  516. //
  517. for (DWORD dwIdx = 0; dwIdx < dwColumnCount; dwIdx++)
  518. {
  519. if (pDisplayInfo[dwIdx].GetValueCount())
  520. {
  521. for (DWORD dwValue = 0; dwValue < pDisplayInfo[dwIdx].GetValueCount(); dwValue++)
  522. {
  523. DisplayList(pDisplayInfo[dwIdx].GetDisplayName(),
  524. pDisplayInfo[dwIdx].GetValue(dwValue));
  525. }
  526. }
  527. else
  528. {
  529. DisplayList(pDisplayInfo[dwIdx].GetDisplayName(),
  530. NULL);
  531. }
  532. }
  533. NewLine();
  534. }
  535. else // table format
  536. {
  537. //
  538. // Set the row in the array
  539. //
  540. m_ppDisplayInfoArray[m_dwTotalRows] = pDisplayInfo;
  541. //
  542. // If this is the first row, update the column count
  543. // and allocate the column widths array
  544. //
  545. if (m_dwTotalRows == 0)
  546. {
  547. DEBUG_OUTPUT(LEVEL8_LOGGING,
  548. L"Initializing column count to %d",
  549. dwColumnCount);
  550. m_dwNumColumns = dwColumnCount;
  551. m_pColWidth = new DWORD[m_dwNumColumns];
  552. if (!m_pColWidth)
  553. {
  554. hr = E_OUTOFMEMORY;
  555. break;
  556. }
  557. memset(m_pColWidth, 0, sizeof(m_pColWidth));
  558. //
  559. // Set the initial column widths from the column headers
  560. //
  561. for (DWORD dwIdx = 0; dwIdx < m_dwNumColumns; dwIdx++)
  562. {
  563. if (pDisplayInfo[dwIdx].GetDisplayName())
  564. {
  565. m_pColWidth[dwIdx] = static_cast<DWORD>(wcslen(pDisplayInfo[dwIdx].GetDisplayName()));
  566. }
  567. else
  568. {
  569. ASSERT(false);
  570. DEBUG_OUTPUT(MINIMAL_LOGGING, L"The display name for column %d wasn't set!", dwIdx);
  571. }
  572. }
  573. }
  574. else
  575. {
  576. if (m_dwNumColumns != dwColumnCount)
  577. {
  578. DEBUG_OUTPUT(MINIMAL_LOGGING,
  579. L"Column count of new row (%d) does not equal the current column count (%d)",
  580. dwColumnCount,
  581. m_dwNumColumns);
  582. ASSERT(m_dwNumColumns == dwColumnCount);
  583. }
  584. }
  585. //
  586. // Go through the columns and update the widths if necessary
  587. //
  588. for (DWORD dwIdx = 0; dwIdx < m_dwNumColumns; dwIdx++)
  589. {
  590. for (DWORD dwValue = 0; dwValue < pDisplayInfo[dwIdx].GetValueCount(); dwValue++)
  591. {
  592. if (pDisplayInfo[dwIdx].GetValue(dwValue))
  593. {
  594. size_t sColWidth = wcslen(pDisplayInfo[dwIdx].GetValue(dwValue));
  595. m_pColWidth[dwIdx] = (DWORD)__max(sColWidth, m_pColWidth[dwIdx]);
  596. }
  597. }
  598. }
  599. //
  600. // Increment the row count
  601. //
  602. m_dwTotalRows++;
  603. }
  604. } while (false);
  605. return hr;
  606. }