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.

927 lines
31 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: querybld.cpp
  7. //
  8. // Contents: Contains implementatin of functions to build query.
  9. //
  10. // History: 24-Sep-2000 Hiteshr Created
  11. //
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "pch.h"
  15. #include "cstrings.h"
  16. #include "querytable.h"
  17. #include "usage.h"
  18. #include "querybld.h"
  19. #include "resource.h" // For IDS_MSG_INVALID_ACCT_ERROR
  20. #include <lmaccess.h> // UF_ACCOUNTDISABLE and UF_DONT_EXPIRE_PASSWD
  21. #include <ntldap.h> // LDAP_MATCHING_RULE_BIT_AND_W
  22. #include <Sddl.h> // For ConvertSidToStringSid
  23. static const LPWSTR g_szUserAccountCtrlQuery = L"(userAccountControl:" LDAP_MATCHING_RULE_BIT_AND_W L":=%u)";
  24. static const LPWSTR g_szServerIsGCQuery = L"(&(objectCategory=NTDS-DSA)(options:" LDAP_MATCHING_RULE_BIT_AND_W L":=1))";
  25. static const LPWSTR g_szCommonQueryFormat= L"(%s=%s)";
  26. //+--------------------------------------------------------------------------
  27. //
  28. // Function: LdapEscape
  29. //
  30. // Synopsis: Escape the characters in *[pszInput] as required by
  31. // RFC 2254.
  32. //
  33. // Arguments: [pszInput] - string to escape
  34. //
  35. // History: 06-23-2000 DavidMun Created
  36. //
  37. // Notes: RFC 2254
  38. //
  39. // If a value should contain any of the following characters
  40. //
  41. // Character ASCII value
  42. // ---------------------------
  43. // * 0x2a
  44. // ( 0x28
  45. // ) 0x29
  46. // \ 0x5c
  47. // NUL 0x00
  48. //
  49. // the character must be encoded as the backslash '\'
  50. // character (ASCII 0x5c) followed by the two hexadecimal
  51. // digits representing the ASCII value of the encoded
  52. // character. The case of the two hexadecimal digits is not
  53. // significant.
  54. //
  55. //---------------------------------------------------------------------------
  56. bool
  57. LdapEscape(IN LPCWSTR pszInput, OUT CComBSTR& strFilter)
  58. {
  59. if(!pszInput)
  60. return FALSE;
  61. //Security Review:pszInput is null terminated.
  62. int iLen = (int)wcslen(pszInput);
  63. for( int i = 0; i < iLen; ++i)
  64. {
  65. switch (*(pszInput+i))
  66. {
  67. case L'(':
  68. strFilter += L"\\28";
  69. break;
  70. case L')':
  71. strFilter += L"\\29";
  72. break;
  73. case L'\\':
  74. if( i + 1 < iLen )
  75. {
  76. // \\ is treated as '\'
  77. switch (*(pszInput+i + 1))
  78. {
  79. case L'\\':
  80. strFilter += L"\\5c";
  81. i++;
  82. break;
  83. // \* is treated as '*'
  84. case L'*':
  85. strFilter += L"\\2a";
  86. i++;
  87. break;
  88. default:
  89. // \X is treated \X only
  90. strFilter += L"\\5c";
  91. break;
  92. }
  93. }
  94. else
  95. strFilter += L"\\5c";
  96. break;
  97. default:
  98. strFilter.Append(pszInput+i,1);
  99. break;
  100. }
  101. }
  102. return TRUE;
  103. }
  104. HRESULT MakeQuery(IN LPCWSTR pszAttrName,
  105. IN LPCWSTR pszCommandLineFilter,
  106. OUT CComBSTR& strFilter)
  107. {
  108. ENTER_FUNCTION_HR(LEVEL3_LOGGING, MakeQuery, hr);
  109. if(!pszAttrName || !pszCommandLineFilter)
  110. {
  111. ASSERT(FALSE);
  112. hr = E_INVALIDARG;
  113. return hr;
  114. }
  115. CComBSTR strEscapedCLFilter;
  116. LdapEscape(pszCommandLineFilter,strEscapedCLFilter);
  117. strFilter = L"(";
  118. strFilter += pszAttrName;
  119. strFilter += L"=";
  120. strFilter += strEscapedCLFilter;
  121. strFilter += L")";
  122. return hr;
  123. }
  124. //+--------------------------------------------------------------------------
  125. //
  126. // Function: CommonFilterFunc
  127. //
  128. // Synopsis: This function takes the input filter from the commandline
  129. // and converts it into ldapfilter.
  130. // For ex -user (ab* | bc*) is converted to |(cn=ab*)(cn=bc*)
  131. // The pEntry->pszName given the attribute name to use in
  132. // filter( cn in above example).
  133. //
  134. // Arguments: [pRecord - IN] : the command line argument structure used
  135. // to retrieve the filter entered by user
  136. // [pObjectEntry - IN] : pointer to the DSQUERY_ATTR_TABLE_ENTRY
  137. // which has info on attribute corresponding
  138. // switch in pRecord
  139. // [pVoid - IN] :Not used.
  140. // [strFilter - OUT] :Contains the output filter.
  141. // Returns: HRESULT : S_OK if everything succeeded
  142. // E_INVALIDARG if the object entry wasn't found
  143. // Anything else is a failure code from an ADSI call
  144. //
  145. // History: 25-Sep-2000 hiteshr Created
  146. //
  147. //---------------------------------------------------------------------------
  148. HRESULT CommonFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  149. IN ARG_RECORD* pRecord,
  150. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  151. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  152. IN PVOID ,
  153. OUT CComBSTR& strFilter)
  154. {
  155. ENTER_FUNCTION_HR(LEVEL3_LOGGING, CommonFilterFunc, hr);
  156. //validate input
  157. if( !pEntry || !pRecord
  158. //validate DSQUERY_ATTR_TABLE_ENTRY entry
  159. || !pEntry->pszName || !pEntry->nAttributeID
  160. //validate pRecord
  161. || !pRecord->bDefined || !pRecord->strValue)
  162. {
  163. ASSERT(FALSE);
  164. hr = E_INVALIDARG;
  165. return hr;
  166. }
  167. //Make Query
  168. hr = MakeQuery(pEntry->pszName,
  169. pRecord->strValue,
  170. strFilter);
  171. DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
  172. return hr;
  173. }
  174. //+--------------------------------------------------------------------------
  175. //
  176. // Function: StarFilterFunc
  177. //
  178. // Synopsis: Filter Function for dsquery *. It returns the value of
  179. // -filter flag.
  180. //
  181. // Arguments: [pRecord - IN] : the command line argument structure used
  182. // to retrieve the filter entered by user
  183. // [pObjectEntry - IN] : pointer to the DSQUERY_ATTR_TABLE_ENTRY
  184. // which has info on attribute corresponding
  185. // switch in pRecord
  186. // [pVoid - IN] :Not used.
  187. // [strFilter - OUT] :Contains the output filter.
  188. // Returns: HRESULT : S_OK if everything succeeded
  189. // E_INVALIDARG if the object entry wasn't found
  190. // Anything else is a failure code from an ADSI call
  191. //
  192. // History: 25-Sep-2000 hiteshr Created
  193. //
  194. //---------------------------------------------------------------------------
  195. HRESULT StarFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  196. IN ARG_RECORD* pRecord,
  197. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  198. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  199. IN PVOID ,
  200. OUT CComBSTR& strFilter)
  201. {
  202. ENTER_FUNCTION_HR(LEVEL3_LOGGING, StarFilterFunc, hr);
  203. //validate input
  204. if(!pEntry || !pRecord
  205. //validate DSQUERY_ATTR_TABLE_ENTRY entry
  206. || !pEntry->nAttributeID
  207. //validate pRecord
  208. || !pRecord->bDefined || !pRecord->strValue)
  209. {
  210. ASSERT(FALSE);
  211. hr = E_INVALIDARG;
  212. return hr;
  213. }
  214. strFilter = pRecord->strValue;
  215. DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
  216. return hr;
  217. }
  218. //+--------------------------------------------------------------------------
  219. //
  220. // Function: InactiveComputerFilterFunc
  221. //
  222. // Synopsis: Filter Function for computer inactive query.
  223. //
  224. // Arguments: [pRecord - IN] : Not Used
  225. // [pObjectEntry - IN] : Not Used
  226. // [pVoid - IN] :Not used.
  227. // [strFilter - OUT] :Contains the output filter.
  228. // Returns: HRESULT : S_OK if everything succeeded
  229. // E_INVALIDARG if the object entry wasn't found
  230. // Anything else is a failure code from an ADSI call
  231. //
  232. // History: 06-05-2002 hiteshr Created
  233. //
  234. //---------------------------------------------------------------------------
  235. HRESULT InactiveComputerFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  236. IN ARG_RECORD* pRecord,
  237. IN CDSCmdBasePathsInfo& refBasePathsInfo,
  238. IN CDSCmdCredentialObject& refCredentialObject,
  239. IN PVOID pData,
  240. OUT CComBSTR& strFilter)
  241. {
  242. return InactiveFilterFunc(pEntry,
  243. pRecord,
  244. refBasePathsInfo,
  245. refCredentialObject,
  246. pData,
  247. strFilter,
  248. true);
  249. }
  250. //+--------------------------------------------------------------------------
  251. //
  252. // Function: InactiveUserFilterFunc
  253. //
  254. // Synopsis: Filter Function for user inactive query.
  255. //
  256. // Arguments: [pRecord - IN] : Not Used
  257. // [pObjectEntry - IN] : Not Used
  258. // [pVoid - IN] :Not used.
  259. // [strFilter - OUT] :Contains the output filter.
  260. // Returns: HRESULT : S_OK if everything succeeded
  261. // E_INVALIDARG if the object entry wasn't found
  262. // Anything else is a failure code from an ADSI call
  263. //
  264. // History: 25-Sep-2000 hiteshr Created
  265. //
  266. //---------------------------------------------------------------------------
  267. HRESULT InactiveUserFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  268. IN ARG_RECORD* pRecord,
  269. IN CDSCmdBasePathsInfo& refBasePathsInfo,
  270. IN CDSCmdCredentialObject& refCredentialObject,
  271. IN PVOID pData,
  272. OUT CComBSTR& strFilter)
  273. {
  274. return InactiveFilterFunc(pEntry,
  275. pRecord,
  276. refBasePathsInfo,
  277. refCredentialObject,
  278. pData,
  279. strFilter,
  280. false);
  281. }
  282. //+--------------------------------------------------------------------------
  283. //
  284. // Function: InactiveFilterFunc
  285. //
  286. // Synopsis: Filter Function for account inactive query.
  287. //
  288. // Arguments: [pRecord - IN] : Not Used
  289. // [pObjectEntry - IN] : Not Used
  290. // [pVoid - IN] :Not used.
  291. // [strFilter - OUT] :Contains the output filter.
  292. // [bComputer]: if true query is for inactive computer accounts
  293. // Returns: HRESULT : S_OK if everything succeeded
  294. // E_INVALIDARG if the object entry wasn't found
  295. // Anything else is a failure code from an ADSI call
  296. //
  297. // History: 25-Sep-2000 hiteshr Created
  298. //
  299. //---------------------------------------------------------------------------
  300. HRESULT InactiveFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  301. IN ARG_RECORD* pRecord,
  302. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  303. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  304. IN PVOID ,
  305. OUT CComBSTR& strFilter,
  306. IN bool bComputer)
  307. {
  308. ENTER_FUNCTION_HR(LEVEL3_LOGGING, InactiveFilterFunc, hr);
  309. if( !pEntry || !pRecord || !pRecord->bDefined )
  310. {
  311. hr = E_INVALIDARG;
  312. return hr;
  313. }
  314. if(pRecord->nValue < 0 )
  315. {
  316. hr = E_INVALIDARG;
  317. return hr;
  318. }
  319. //
  320. //Unit at commandline is Week
  321. //
  322. int nDays = pRecord->nValue * 7;
  323. FILETIME ftCurrent;
  324. ::GetSystemTimeAsFileTime(&ftCurrent);
  325. LARGE_INTEGER li;
  326. li.LowPart = ftCurrent.dwLowDateTime;
  327. li.HighPart = ftCurrent.dwHighDateTime;
  328. //
  329. //Get the number of days since the reference time
  330. //
  331. int nDaysSince1600 = (int)(li.QuadPart/(((LONGLONG) (24 * 60) * 60) * 10000000));
  332. if(nDaysSince1600 < nDays)
  333. {
  334. hr = E_INVALIDARG;
  335. return hr;
  336. }
  337. li.QuadPart -= ((((LONGLONG)nDays * 24) * 60) * 60) * 10000000;
  338. CComBSTR strTime;
  339. litow(li, strTime);
  340. WCHAR buffer[256];
  341. //Security Review:Replace with strsafe api
  342. //NTRAID#NTBUG9-573989-2002/03/12-hiteshr
  343. if(bComputer)
  344. {
  345. //NTRAID#NTBUG9-616892-2002/06/05-hiteshr
  346. //Cluster creates some virtual computers which never update password or login and
  347. //these accounts should not be displayed by dsquery computer -[inactive|stalepwd]
  348. hr = StringCchPrintf(buffer,256,L"(!(serviceprincipalname=msclustervirtualserver/*))(lastLogonTimestamp<=%s)",(LPCWSTR)strTime);
  349. }
  350. else
  351. {
  352. hr = StringCchPrintf(buffer,256,L"(lastLogonTimestamp<=%s)",(LPCWSTR)strTime);
  353. }
  354. if(SUCCEEDED(hr))
  355. {
  356. strFilter = buffer;
  357. DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
  358. }
  359. return hr;
  360. }
  361. //+--------------------------------------------------------------------------
  362. //
  363. // Function: StalepwdComputerFilterFunc
  364. //
  365. // Synopsis: Filter Function for Stale Computer Password query.
  366. //
  367. // Arguments: [pRecord - IN] : Not Used
  368. // [pObjectEntry - IN] : Not Used
  369. // [pVoid - IN] :Not used.
  370. // [strFilter - OUT] :Contains the output filter.
  371. // Returns: HRESULT : S_OK if everything succeeded
  372. // E_INVALIDARG if the object entry wasn't found
  373. // Anything else is a failure code from an ADSI call
  374. //
  375. // History: 25-Sep-2000 hiteshr Created
  376. //
  377. //---------------------------------------------------------------------------
  378. HRESULT StalepwdComputerFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  379. IN ARG_RECORD* pRecord,
  380. IN CDSCmdBasePathsInfo& refBasePathsInfo,
  381. IN CDSCmdCredentialObject& refCredentialObject,
  382. IN PVOID pData,
  383. OUT CComBSTR& strFilter)
  384. {
  385. return StalepwdFilterFunc(pEntry,
  386. pRecord,
  387. refBasePathsInfo,
  388. refCredentialObject,
  389. pData,
  390. strFilter,
  391. true);
  392. }
  393. //+--------------------------------------------------------------------------
  394. //
  395. // Function: StalepwdUserFilterFunc
  396. //
  397. // Synopsis: Filter Function for Stale User Password query.
  398. //
  399. // Arguments: [pRecord - IN] : Not Used
  400. // [pObjectEntry - IN] : Not Used
  401. // [pVoid - IN] :Not used.
  402. // [strFilter - OUT] :Contains the output filter.
  403. // Returns: HRESULT : S_OK if everything succeeded
  404. // E_INVALIDARG if the object entry wasn't found
  405. // Anything else is a failure code from an ADSI call
  406. //
  407. // History: 25-Sep-2000 hiteshr Created
  408. //
  409. //---------------------------------------------------------------------------
  410. HRESULT StalepwdUserFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  411. IN ARG_RECORD* pRecord,
  412. IN CDSCmdBasePathsInfo& refBasePathsInfo,
  413. IN CDSCmdCredentialObject& refCredentialObject,
  414. IN PVOID pData,
  415. OUT CComBSTR& strFilter)
  416. {
  417. return StalepwdFilterFunc(pEntry,
  418. pRecord,
  419. refBasePathsInfo,
  420. refCredentialObject,
  421. pData,
  422. strFilter,
  423. false);
  424. }
  425. //+--------------------------------------------------------------------------
  426. //
  427. // Function: StalepwdFilterFunc
  428. //
  429. // Synopsis: Filter Function for Stale Password query.
  430. //
  431. // Arguments: [pRecord - IN] : Not Used
  432. // [pObjectEntry - IN] : Not Used
  433. // [pVoid - IN] :Not used.
  434. // [strFilter - OUT] :Contains the output filter.
  435. // [bComputer]: if true query is for inactive computer accounts
  436. // Returns: HRESULT : S_OK if everything succeeded
  437. // E_INVALIDARG if the object entry wasn't found
  438. // Anything else is a failure code from an ADSI call
  439. //
  440. // History: 25-Sep-2000 hiteshr Created
  441. //
  442. //---------------------------------------------------------------------------
  443. HRESULT StalepwdFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *pEntry,
  444. IN ARG_RECORD* pRecord,
  445. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  446. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  447. IN PVOID ,
  448. OUT CComBSTR& strFilter,
  449. bool bComputer)
  450. {
  451. ENTER_FUNCTION_HR(LEVEL3_LOGGING, StalepwdFilterFunc, hr);
  452. if( !pEntry || !pRecord || !pRecord->bDefined )
  453. {
  454. hr = E_INVALIDARG;
  455. return hr;
  456. }
  457. int nDays = pRecord->nValue;
  458. if(nDays < 0)
  459. {
  460. hr = E_INVALIDARG;
  461. return hr;
  462. }
  463. FILETIME ftCurrent;
  464. ::GetSystemTimeAsFileTime(&ftCurrent);
  465. LARGE_INTEGER li;
  466. li.LowPart = ftCurrent.dwLowDateTime;
  467. li.HighPart = ftCurrent.dwHighDateTime;
  468. //
  469. //Get the number of days since the reference time
  470. //
  471. int nDaysSince1600 = (int)(li.QuadPart/(((LONGLONG) (24 * 60) * 60) * 10000000));
  472. if(nDaysSince1600 < nDays)
  473. {
  474. hr = E_INVALIDARG;
  475. return hr;
  476. }
  477. li.QuadPart -= ((((ULONGLONG)nDays * 24) * 60) * 60) * 10000000;
  478. CComBSTR strTime;
  479. litow(li, strTime);
  480. WCHAR buffer[256];
  481. //Security Review:Replace with strsafe api
  482. //NTRAID#NTBUG9-573989-2002/03/12-hiteshr
  483. if(bComputer)
  484. {
  485. //NTRAID#NTBUG9-616892-2002/06/05-hiteshr
  486. //Cluster creates some virtual computers which never update password or login and
  487. //these accounts should not be displayed by dsquery computer -[inactive|stalepwd]
  488. hr = StringCchPrintf(buffer,256,L"(!(serviceprincipalname=msclustervirtualserver/*))(pwdLastSet<=%s)",(LPCWSTR)strTime);
  489. }
  490. else
  491. {
  492. hr = StringCchPrintf(buffer,256,L"(pwdLastSet<=%s)",(LPCWSTR)strTime);
  493. }
  494. if(SUCCEEDED(hr))
  495. {
  496. strFilter = buffer;
  497. DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
  498. }
  499. return hr;
  500. }
  501. //+--------------------------------------------------------------------------
  502. //
  503. // Function: DisabledFilterFunc
  504. //
  505. // Synopsis: Filter Function for account disabled query.
  506. //
  507. // Arguments: [pRecord - IN] : Not Used
  508. // [pObjectEntry - IN] : Not Used
  509. // [pVoid - IN] :Not used.
  510. // [strFilter - OUT] :Contains the output filter.
  511. // Returns: HRESULT : S_OK if everything succeeded
  512. // E_INVALIDARG if the object entry wasn't found
  513. // Anything else is a failure code from an ADSI call
  514. //
  515. // History: 25-Sep-2000 hiteshr Created
  516. //
  517. //---------------------------------------------------------------------------
  518. HRESULT DisabledFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
  519. IN ARG_RECORD* ,
  520. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  521. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  522. IN PVOID ,
  523. OUT CComBSTR& strFilter)
  524. {
  525. ENTER_FUNCTION_HR(LEVEL3_LOGGING, DisabledFilterFunc, hr);
  526. WCHAR buffer[256]; //This is long enough
  527. //Security Review:Replace with strsafe api
  528. //NTRAID#NTBUG9-573989-2002/03/12-hiteshr
  529. hr = StringCchPrintf(buffer,256,g_szUserAccountCtrlQuery,UF_ACCOUNTDISABLE);
  530. if(SUCCEEDED(hr))
  531. {
  532. strFilter = buffer;
  533. DEBUG_OUTPUT(LEVEL3_LOGGING, L"filter = %s", strFilter);
  534. }
  535. return hr;
  536. }
  537. //+--------------------------------------------------------------------------
  538. //
  539. // Function: SubnetSiteFilterFunc
  540. //
  541. // Synopsis: Filter Function for -site switch in dsquery subnet.
  542. //
  543. // Arguments: [pEntry - IN] : Not Used
  544. // [pRecord - IN] : Command Line value supplied by user
  545. // [pVoid - IN] : suffix for the siteobject attribute.
  546. // [strFilter - OUT] :Contains the output filter.
  547. // Returns: HRESULT : S_OK if everything succeeded
  548. //
  549. // History: 24-April-2001 hiteshr Created
  550. //
  551. //---------------------------------------------------------------------------
  552. HRESULT SubnetSiteFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
  553. IN ARG_RECORD* pRecord,
  554. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  555. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  556. IN PVOID pParam,
  557. OUT CComBSTR& strFilter)
  558. {
  559. ENTER_FUNCTION_HR(LEVEL3_LOGGING, InactiveFilterFunc, hr);
  560. if( !pRecord || !pRecord->bDefined || !pParam)
  561. {
  562. hr = E_INVALIDARG;
  563. return hr;
  564. }
  565. CComBSTR strEscapedCLFilter;
  566. LdapEscape(pRecord->strValue,strEscapedCLFilter);
  567. strFilter = L"(siteobject=cn=";
  568. strFilter += strEscapedCLFilter;
  569. strFilter += L",";
  570. strFilter += *(static_cast<BSTR*>(pParam));
  571. strFilter += L")";
  572. return hr;
  573. }
  574. //+--------------------------------------------------------------------------
  575. //
  576. // Function: BuildQueryFilter
  577. //
  578. // Synopsis: This function builds the LDAP query filter for given object type.
  579. //
  580. // Arguments: [pCommandArgs - IN] :the command line argument structure used
  581. // to retrieve the values of switches
  582. // [pObjectEntry - IN] :Contains info about the object type
  583. // [pParam -IN] :This value is passed to filter function.
  584. // [strLDAPFilter - OUT] :Contains the output filter.
  585. // Returns: HRESULT : S_OK if everything succeeded
  586. // E_INVALIDARG if the object entry wasn't found
  587. // Anything else is a failure code from an ADSI call
  588. //
  589. // History: 25-Sep-2000 hiteshr Created
  590. //
  591. //---------------------------------------------------------------------------
  592. HRESULT BuildQueryFilter(PARG_RECORD pCommandArgs,
  593. PDSQueryObjectTableEntry pObjectEntry,
  594. CDSCmdBasePathsInfo& refBasePathsInfo,
  595. CDSCmdCredentialObject& refCredentialObject,
  596. PVOID pParam,
  597. CComBSTR& strLDAPFilter)
  598. {
  599. ENTER_FUNCTION_HR(LEVEL3_LOGGING, BuildQueryFilter, hr);
  600. if( !pCommandArgs || !pObjectEntry )
  601. {
  602. ASSERT(FALSE);
  603. hr = E_INVALIDARG;
  604. return hr;
  605. }
  606. DSQUERY_ATTR_TABLE_ENTRY** pAttributeTable;
  607. DWORD dwAttributeCount;
  608. pAttributeTable = pObjectEntry->pAttributeTable;
  609. dwAttributeCount = pObjectEntry->dwAttributeCount;
  610. if( !pAttributeTable || !dwAttributeCount )
  611. {
  612. hr = E_INVALIDARG;
  613. return hr;
  614. }
  615. BOOL bUseDefaultFilter = TRUE;
  616. CComBSTR strFilter;
  617. for( UINT i = 0; i < dwAttributeCount; ++i )
  618. {
  619. if(pCommandArgs[pAttributeTable[i]->nAttributeID].bDefined)
  620. {
  621. bUseDefaultFilter = FALSE;
  622. CComBSTR strLocalFilter;
  623. hr = pAttributeTable[i]->pMakeFilterFunc(pAttributeTable[i],
  624. pCommandArgs + pAttributeTable[i]->nAttributeID,
  625. refBasePathsInfo,
  626. refCredentialObject,
  627. pParam,
  628. strLocalFilter);
  629. if(FAILED(hr))
  630. return hr;
  631. strFilter += strLocalFilter;
  632. DEBUG_OUTPUT(FULL_LOGGING, L"Current filter = %s", strFilter);
  633. }
  634. }
  635. //
  636. //If none of the commandline filter switches are specified, use
  637. //default filter
  638. //
  639. strLDAPFilter = L"(";
  640. if(bUseDefaultFilter)
  641. {
  642. strLDAPFilter += pObjectEntry->pszDefaultFilter;
  643. }
  644. else
  645. {
  646. if(pObjectEntry->pszPrefixFilter)
  647. {
  648. strLDAPFilter += pObjectEntry->pszPrefixFilter;
  649. strLDAPFilter += strFilter;
  650. }
  651. else
  652. strLDAPFilter += strFilter;
  653. }
  654. strLDAPFilter += L")";
  655. DEBUG_OUTPUT(LEVEL3_LOGGING, L"ldapfilter = %s", strLDAPFilter);
  656. return hr;
  657. }
  658. //+--------------------------------------------------------------------------
  659. //
  660. // Function: QLimitFilterFunc
  661. //
  662. // Synopsis: Filter Function for -qlimit switch in dsquery quota.
  663. //
  664. // Arguments: [pEntry - IN] : Not Used
  665. // [pRecord - IN] : Command Line value supplied by user
  666. // [pVoid - IN] : unused.
  667. // [strFilter - OUT] :Contains the output filter.
  668. // Returns: HRESULT : S_OK if everything succeeded
  669. //
  670. // History: 13-Aug-2002 ronmart Created
  671. //
  672. //---------------------------------------------------------------------------
  673. HRESULT QLimitFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
  674. IN ARG_RECORD* pRecord,
  675. IN CDSCmdBasePathsInfo& /*refBasePathsInfo*/,
  676. IN CDSCmdCredentialObject& /*refCredentialObject*/,
  677. IN PVOID,
  678. OUT CComBSTR& strFilter)
  679. {
  680. ENTER_FUNCTION_HR(LEVEL3_LOGGING, QLimitFilterFunc, hr);
  681. if( !pRecord || !pRecord->bDefined)
  682. {
  683. hr = E_INVALIDARG;
  684. return hr;
  685. }
  686. // Build the quotaAmount string
  687. strFilter = L"(msDS-QuotaAmount";
  688. strFilter += pRecord->strValue;
  689. strFilter += L")";
  690. return hr;
  691. }
  692. //+--------------------------------------------------------------------------
  693. //
  694. // Function: AccountFilterFunc
  695. //
  696. // Synopsis: Filter Function for -acct switch in dsquery quota.
  697. //
  698. // Arguments: [pEntry - IN] : Not Used
  699. // [pRecord - IN] : Command Line value supplied by user
  700. // [pVoid - IN] : Not Used
  701. // [strFilter - OUT] :Contains the output filter.
  702. // Returns: HRESULT : S_OK if everything succeeded
  703. //
  704. // History: 14-Aug-2002 ronmart Created
  705. //
  706. //---------------------------------------------------------------------------
  707. HRESULT AccountFilterFunc(IN DSQUERY_ATTR_TABLE_ENTRY *,
  708. IN ARG_RECORD* pRecord,
  709. IN CDSCmdBasePathsInfo& refBasePathsInfo,
  710. IN CDSCmdCredentialObject& refCredentialObject,
  711. IN PVOID ,
  712. OUT CComBSTR& strFilter)
  713. {
  714. ENTER_FUNCTION_HR(LEVEL3_LOGGING, AccountFilterFunc, hr);
  715. if( !pRecord || !pRecord->bDefined || !refBasePathsInfo.IsInitialized())
  716. {
  717. hr = E_INVALIDARG;
  718. return hr;
  719. }
  720. PWSTR* ppszArray = NULL; // Array of accts from param or STDIN
  721. do // false loop
  722. {
  723. // Get the accts (trustees)
  724. UINT nStrings = 0;
  725. ParseNullSeparatedString(pRecord->strValue,
  726. &ppszArray,
  727. &nStrings);
  728. if (nStrings < 1 ||
  729. !ppszArray)
  730. {
  731. ASSERT(false); // This should never happen
  732. hr = E_OUTOFMEMORY;
  733. break;
  734. }
  735. // Or the return values together
  736. strFilter = L"(|";
  737. // Get a trustee query for each acct
  738. for(UINT i = 0; i < nStrings; i++)
  739. {
  740. // Append (msDS-QuotaTrustee=<sid>) for this acct
  741. // to the filter
  742. hr = AddSingleAccountFilter(ppszArray[i], refBasePathsInfo,
  743. refCredentialObject, strFilter);
  744. if(FAILED(hr))
  745. {
  746. hr = E_UNEXPECTED;
  747. break;
  748. }
  749. }
  750. // Close the query string
  751. strFilter += L")";
  752. } while (false);
  753. // Free the Acct array
  754. if(ppszArray)
  755. LocalFree(ppszArray);
  756. // If we failed in the loop then clear out the filter string
  757. if(FAILED(hr))
  758. strFilter = L"";
  759. return hr;
  760. }
  761. //+--------------------------------------------------------------------------
  762. //
  763. // Function: AddSingleAccountFilter
  764. //
  765. // Synopsis: Appends an account string to strFilter for the specified user
  766. //
  767. // Arguments: [lpszUser - IN] : User whose sid string is requested
  768. // [strFilter - OUT] : Contains the output filter to append to
  769. // Returns: HRESULT : S_OK if everything succeeded
  770. //
  771. // History: 14-Aug-2002 ronmart Created
  772. //
  773. //---------------------------------------------------------------------------
  774. HRESULT AddSingleAccountFilter(IN LPCWSTR lpszUser,
  775. IN CDSCmdBasePathsInfo& refBasePathsInfo,
  776. IN CDSCmdCredentialObject& refCredentialObject,
  777. OUT CComBSTR& strFilter)
  778. {
  779. ENTER_FUNCTION_HR(LEVEL3_LOGGING, AddSingleAccountFilter, hr);
  780. if(!lpszUser)
  781. {
  782. hr = E_INVALIDARG;
  783. return hr;
  784. }
  785. PSID pSid = NULL;
  786. LPWSTR pszSid = NULL;
  787. LPWSTR lpszDN = NULL;
  788. do // false loop
  789. {
  790. // TODO: Need to provide the first param
  791. hr = ConvertTrusteeToDN(NULL, lpszUser, &lpszDN);
  792. if(FAILED(hr))
  793. {
  794. // 700068 - If the user doesn't exist or has been deleted then
  795. // give the user a clue as to what went wrong. 686693 addresses
  796. // the known issue of multiple error messages being displayed
  797. // and may not be addressed until a future release - ronmart
  798. hr = E_INVALIDARG;
  799. DisplayErrorMessage(g_pszDSCommandName, 0, hr, IDS_MSG_INVALID_ACCT_ERROR);
  800. break;
  801. }
  802. // Get the SID
  803. hr = GetDNSid(lpszDN,
  804. refBasePathsInfo,
  805. refCredentialObject,
  806. &pSid);
  807. if(FAILED(hr))
  808. {
  809. break;
  810. }
  811. // Convert the sid to a string
  812. if(ConvertSidToStringSid(pSid, &pszSid))
  813. {
  814. DEBUG_OUTPUT(LEVEL3_LOGGING, L"ConvertSidToStringSid = %s", pszSid);
  815. // APPEND the trustee query with the sid
  816. strFilter += L"(msDS-QuotaTrustee=";
  817. strFilter += pszSid;
  818. strFilter += L")";
  819. }
  820. else
  821. {
  822. DEBUG_OUTPUT(LEVEL3_LOGGING, L"ConvertSidToStringSid failed!");
  823. hr = E_FAIL;
  824. break;
  825. }
  826. } while (false);
  827. if(pSid)
  828. LocalFree(pSid);
  829. if(pszSid)
  830. LocalFree(pszSid);
  831. if(lpszDN)
  832. LocalFree(lpszDN);
  833. return hr;
  834. }