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.

602 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996
  5. //
  6. // File: putget.cxx
  7. //
  8. // Contents:
  9. //
  10. //
  11. // History: 01-14-97 krishnaG Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "ldap.hxx"
  15. #pragma hdrstop
  16. STDMETHODIMP
  17. CLDAPGenObject::Get(
  18. THIS_ BSTR bstrName,
  19. VARIANT FAR* pvProp
  20. )
  21. {
  22. HRESULT hr = S_OK;
  23. DWORD dwSyntaxId;
  24. DWORD dwStatus = 0;
  25. LDAPOBJECTARRAY ldapSrcObjects;
  26. LDAPOBJECTARRAY_INIT(ldapSrcObjects);
  27. //
  28. // Make sure that the last error is reset
  29. //
  30. Macro_ClearADsLastError(L"LDAP Provider");
  31. //
  32. // In case some person decides to randomize us with a NULL
  33. //
  34. if (!pvProp || !bstrName) {
  35. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  36. }
  37. //
  38. // retrieve data object from cache; if one exists
  39. //
  40. if ( GetObjectState() == ADS_OBJECT_UNBOUND) {
  41. hr = _pPropertyCache->unboundgetproperty(
  42. bstrName,
  43. &dwSyntaxId,
  44. &dwStatus,
  45. &ldapSrcObjects
  46. );
  47. // For backward compatibility
  48. if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
  49. hr = E_FAIL;
  50. }
  51. } else {
  52. hr = _pPropertyCache->getproperty(
  53. bstrName,
  54. &dwSyntaxId,
  55. &dwStatus,
  56. &ldapSrcObjects
  57. );
  58. // this will make sure we do not break existing code
  59. if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
  60. hr = E_ADS_PROPERTY_NOT_FOUND;
  61. }
  62. }
  63. BAIL_ON_FAILURE(hr);
  64. //
  65. // translate the Ldap objects to variants
  66. //
  67. if ( ldapSrcObjects.dwCount == 1 ) {
  68. hr = LdapTypeToVarTypeCopy(
  69. _pszLDAPServer,
  70. _Credentials,
  71. ldapSrcObjects.pLdapObjects,
  72. dwSyntaxId,
  73. pvProp
  74. );
  75. } else {
  76. hr = LdapTypeToVarTypeCopyConstruct(
  77. _pszLDAPServer,
  78. _Credentials,
  79. ldapSrcObjects,
  80. dwSyntaxId,
  81. pvProp
  82. );
  83. }
  84. BAIL_ON_FAILURE(hr);
  85. error:
  86. LdapTypeFreeLdapObjects( &ldapSrcObjects );
  87. RRETURN_EXP_IF_ERR(hr);
  88. }
  89. STDMETHODIMP
  90. CLDAPGenObject::Put(
  91. THIS_ BSTR bstrName,
  92. VARIANT vProp
  93. )
  94. {
  95. HRESULT hr = S_OK;
  96. DWORD dwSyntaxId = 0;
  97. DWORD dwIndex = 0;
  98. LDAPOBJECTARRAY ldapDestObjects;
  99. DWORD dwNumValues = 0;
  100. VARIANT * pVarArray = NULL;
  101. VARIANT * pvProp = NULL;
  102. BOOL fIndexValid = TRUE;
  103. LDAPOBJECTARRAY_INIT(ldapDestObjects);
  104. //
  105. // Make sure that the last error is reset
  106. //
  107. Macro_ClearADsLastError(L"LDAP Provider");
  108. //
  109. // In case some person decides to randomize us with a NULL
  110. //
  111. if (!bstrName) {
  112. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  113. }
  114. //
  115. // A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
  116. // We should dereference a VT_BYREF|VT_VARIANT once and see
  117. // what's inside.
  118. //
  119. pvProp = &vProp;
  120. if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
  121. pvProp = V_VARIANTREF(&vProp);
  122. }
  123. if ((V_VT(pvProp) & VT_VARIANT) && V_ISARRAY(pvProp) && V_ISBYREF(pvProp)){
  124. hr = ConvertByRefSafeArrayToVariantArray(
  125. *pvProp,
  126. &pVarArray,
  127. &dwNumValues
  128. );
  129. BAIL_ON_FAILURE(hr);
  130. pvProp = pVarArray;
  131. }else if ((V_VT(pvProp) & VT_VARIANT) && V_ISARRAY(pvProp)) {
  132. hr = ConvertSafeArrayToVariantArray(
  133. *pvProp,
  134. &pVarArray,
  135. &dwNumValues
  136. );
  137. // returns E_FAIL if *pvProp is invalid
  138. if (hr == E_FAIL)
  139. hr = E_ADS_BAD_PARAMETER;
  140. BAIL_ON_FAILURE(hr);
  141. pvProp = pVarArray;
  142. }
  143. else {
  144. dwNumValues = 1;
  145. }
  146. if (pvProp == NULL) {
  147. dwSyntaxId = LDAPTYPE_UNKNOWN;
  148. }
  149. else {
  150. hr = GetLdapSyntaxFromVariant(
  151. pvProp,
  152. &dwSyntaxId,
  153. _pszLDAPServer,
  154. bstrName,
  155. _Credentials,
  156. _dwPort
  157. );
  158. BAIL_ON_FAILURE(hr);
  159. if ( dwSyntaxId == LDAPTYPE_UNKNOWN )
  160. {
  161. hr = E_ADS_CANT_CONVERT_DATATYPE;
  162. BAIL_ON_FAILURE(hr);
  163. }
  164. }
  165. if (!_wcsicmp(bstrName, L"ntSecurityDescriptor")){
  166. dwSyntaxId = LDAPTYPE_SECURITY_DESCRIPTOR;
  167. }
  168. #if 0
  169. //
  170. // check if this is a legal property for this object,
  171. //
  172. // No Schema??
  173. // mattrim 5/16/00 - doesn't matter if no schema since
  174. // this isn't getting built, it's #if'ed out
  175. //
  176. hr = ValidatePropertyinCache(
  177. szLDAPTreeName,
  178. _ADsClass,
  179. bstrName,
  180. &dwSyntaxId
  181. );
  182. BAIL_ON_FAILURE(hr);
  183. #endif
  184. //
  185. // check if the variant maps to the syntax of this property
  186. //
  187. if ( dwNumValues > 0 )
  188. {
  189. hr = VarTypeToLdapTypeCopyConstruct(
  190. _pszLDAPServer,
  191. _Credentials,
  192. dwSyntaxId,
  193. pvProp,
  194. dwNumValues,
  195. &ldapDestObjects
  196. );
  197. BAIL_ON_FAILURE(hr);
  198. }
  199. //
  200. // Find this property in the cache
  201. //
  202. hr = _pPropertyCache->findproperty(
  203. bstrName,
  204. &dwIndex
  205. );
  206. //
  207. // If this property does not exist in the
  208. // cache, add this property into the cache.
  209. //
  210. if (FAILED(hr)) {
  211. hr = _pPropertyCache->addproperty( bstrName );
  212. //
  213. // If dwNumValues == 0 ( delete the property ) but couldn't find
  214. // the property, or if the add operation fails, return the error.
  215. //
  216. BAIL_ON_FAILURE(hr);
  217. // Set the flag as the dwIndex is not valid in this case
  218. fIndexValid = FALSE;
  219. }
  220. //
  221. // Now update the property in the cache
  222. //
  223. if (fIndexValid) {
  224. // do an optimized put
  225. hr = _pPropertyCache->putproperty(
  226. dwIndex,
  227. PROPERTY_UPDATE,
  228. dwSyntaxId,
  229. ldapDestObjects
  230. );
  231. } else {
  232. // Index is not valid so let the cache figure it out.
  233. hr = _pPropertyCache->putproperty(
  234. bstrName,
  235. PROPERTY_UPDATE,
  236. dwSyntaxId,
  237. ldapDestObjects
  238. );
  239. }
  240. BAIL_ON_FAILURE(hr);
  241. error:
  242. LdapTypeFreeLdapObjects( &ldapDestObjects );
  243. if (pVarArray) {
  244. DWORD i = 0;
  245. for (i = 0; i < dwNumValues; i++) {
  246. VariantClear(pVarArray + i);
  247. }
  248. FreeADsMem(pVarArray);
  249. }
  250. RRETURN(hr);
  251. }
  252. STDMETHODIMP
  253. CLDAPGenObject::GetEx(
  254. THIS_ BSTR bstrName,
  255. VARIANT FAR* pvProp
  256. )
  257. {
  258. HRESULT hr = S_OK;
  259. DWORD dwSyntaxId;
  260. DWORD dwStatus = 0;
  261. LDAPOBJECTARRAY ldapSrcObjects;
  262. LDAPOBJECTARRAY_INIT(ldapSrcObjects);
  263. //
  264. // Make sure that the last error is reset
  265. //
  266. Macro_ClearADsLastError(L"LDAP Provider");
  267. //
  268. // For those who know no not what they do
  269. //
  270. if (!pvProp || !bstrName) {
  271. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  272. }
  273. //
  274. // retrieve data object from cache; if one exists
  275. //
  276. if ( GetObjectState() == ADS_OBJECT_UNBOUND) {
  277. hr = _pPropertyCache->unboundgetproperty(
  278. bstrName,
  279. &dwSyntaxId,
  280. &dwStatus,
  281. &ldapSrcObjects
  282. );
  283. // this will make sure we do not break existing code
  284. if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
  285. hr = E_FAIL;
  286. }
  287. } else {
  288. hr = _pPropertyCache->getproperty(
  289. bstrName,
  290. &dwSyntaxId,
  291. &dwStatus,
  292. &ldapSrcObjects
  293. );
  294. // this will make sure we do not break existing code
  295. if (!ldapSrcObjects.pLdapObjects && SUCCEEDED(hr)) {
  296. hr = E_ADS_PROPERTY_NOT_FOUND;
  297. }
  298. }
  299. BAIL_ON_FAILURE(hr);
  300. //
  301. // translate the Ldap objects to variants
  302. //
  303. hr = LdapTypeToVarTypeCopyConstruct(
  304. _pszLDAPServer,
  305. _Credentials,
  306. ldapSrcObjects,
  307. dwSyntaxId,
  308. pvProp
  309. );
  310. BAIL_ON_FAILURE(hr);
  311. error:
  312. LdapTypeFreeLdapObjects( &ldapSrcObjects );
  313. RRETURN_EXP_IF_ERR(hr);
  314. }
  315. STDMETHODIMP
  316. CLDAPGenObject::PutEx(
  317. THIS_ long lnControlCode,
  318. BSTR bstrName,
  319. VARIANT vProp
  320. )
  321. {
  322. HRESULT hr = S_OK;
  323. DWORD dwSyntaxId = 0;
  324. DWORD dwFlags = 0;
  325. DWORD dwIndex = 0;
  326. LDAPOBJECTARRAY ldapDestObjects;
  327. DWORD dwNumValues = 0;
  328. VARIANT * pVarArray = NULL;
  329. VARIANT * pvProp = NULL;
  330. BOOL fIndexValid = TRUE;
  331. LDAPOBJECTARRAY_INIT(ldapDestObjects);
  332. //
  333. // Make sure that the last error is reset
  334. //
  335. Macro_ClearADsLastError(L"LDAP Provider");
  336. //
  337. // In case some person decides to randomize us with a NULL
  338. //
  339. if (!bstrName) {
  340. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  341. }
  342. switch ( lnControlCode ) {
  343. case ADS_PROPERTY_CLEAR:
  344. dwFlags = PROPERTY_DELETE;
  345. break;
  346. case ADS_PROPERTY_UPDATE:
  347. dwFlags = PROPERTY_UPDATE;
  348. break;
  349. case ADS_PROPERTY_APPEND:
  350. dwFlags = PROPERTY_ADD;
  351. break;
  352. case ADS_PROPERTY_DELETE:
  353. dwFlags = PROPERTY_DELETE_VALUE;
  354. break;
  355. default:
  356. RRETURN_EXP_IF_ERR(hr = E_ADS_BAD_PARAMETER);
  357. }
  358. if ( dwFlags != PROPERTY_DELETE )
  359. {
  360. //
  361. // A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
  362. // We should dereference a VT_BYREF|VT_VARIANT once and see
  363. // what's inside.
  364. //
  365. pvProp = &vProp;
  366. if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
  367. pvProp = V_VARIANTREF(&vProp);
  368. }
  369. if ((V_VT(pvProp) == (VT_VARIANT|VT_ARRAY|VT_BYREF)) ||
  370. (V_VT(pvProp) == (VT_VARIANT|VT_ARRAY))) {
  371. hr = ConvertSafeArrayToVariantArray(
  372. *pvProp,
  373. &pVarArray,
  374. &dwNumValues
  375. );
  376. // returns E_FAIL if *pvProp is invalid
  377. if (hr == E_FAIL)
  378. hr = E_ADS_BAD_PARAMETER;
  379. BAIL_ON_FAILURE(hr);
  380. pvProp = pVarArray;
  381. } else {
  382. hr = E_FAIL;
  383. BAIL_ON_FAILURE(hr);
  384. }
  385. if (pvProp == NULL) {
  386. //
  387. // If array is empty, set dwSyntaxId to Unknown. This value will not be used
  388. //
  389. dwSyntaxId = LDAPTYPE_UNKNOWN;
  390. }
  391. else {
  392. hr = GetLdapSyntaxFromVariant(
  393. pvProp,
  394. &dwSyntaxId,
  395. _pszLDAPServer,
  396. bstrName,
  397. _Credentials,
  398. _dwPort
  399. );
  400. BAIL_ON_FAILURE(hr);
  401. if ( dwSyntaxId == LDAPTYPE_UNKNOWN )
  402. {
  403. //
  404. // If array is empty, set dwSyntaxId to Unknown. This value will
  405. // not be used
  406. //
  407. hr = E_ADS_CANT_CONVERT_DATATYPE;
  408. BAIL_ON_FAILURE(hr);
  409. }
  410. }
  411. //
  412. // check if the variant maps to the syntax of this property
  413. //
  414. if ( dwNumValues > 0 )
  415. {
  416. hr = VarTypeToLdapTypeCopyConstruct(
  417. _pszLDAPServer,
  418. _Credentials,
  419. dwSyntaxId,
  420. pvProp,
  421. dwNumValues,
  422. &ldapDestObjects
  423. );
  424. BAIL_ON_FAILURE(hr);
  425. }
  426. }
  427. //
  428. // Find this property in the cache
  429. //
  430. hr = _pPropertyCache->findproperty(
  431. bstrName,
  432. &dwIndex
  433. );
  434. //
  435. // If this property does not exist in the
  436. // cache, add this property into the cache.
  437. //
  438. if (FAILED(hr)) {
  439. hr = _pPropertyCache->addproperty( bstrName );
  440. //
  441. // If dwNumValues == 0 ( delete the property ) but couldn't find
  442. // the property, or if the add operation fails, return the error.
  443. //
  444. BAIL_ON_FAILURE(hr);
  445. fIndexValid = FALSE;
  446. }
  447. //
  448. // Now update the property in the cache
  449. //
  450. if (fIndexValid) {
  451. // do an optimized put property with the index
  452. hr = _pPropertyCache->putproperty(
  453. dwIndex,
  454. dwFlags,
  455. dwSyntaxId,
  456. ldapDestObjects
  457. );
  458. } else {
  459. // we need to use the property name in this case
  460. hr = _pPropertyCache->putproperty(
  461. bstrName,
  462. dwFlags,
  463. dwSyntaxId,
  464. ldapDestObjects
  465. );
  466. }
  467. BAIL_ON_FAILURE(hr);
  468. error:
  469. LdapTypeFreeLdapObjects( &ldapDestObjects );
  470. if (pVarArray) {
  471. DWORD i = 0;
  472. for (i = 0; i < dwNumValues; i++) {
  473. VariantClear(pVarArray + i);
  474. }
  475. FreeADsMem(pVarArray);
  476. }
  477. RRETURN_EXP_IF_ERR(hr);
  478. }