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.

1233 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: ldap2ods.cxx
  7. //
  8. // Contents: LDAP Object to DSObject Copy Routines
  9. //
  10. // Functions:
  11. //
  12. // History: 2/20/96 yihsins Created.
  13. //
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "ldapc.hxx"
  17. void
  18. AdsTypeFreeAdsObjects(
  19. PADSVALUE pAdsDestValues,
  20. DWORD dwNumObjects
  21. )
  22. {
  23. LPBYTE pMem = NULL;
  24. PADS_DN_WITH_BINARY pDNBin = NULL;
  25. PADS_DN_WITH_STRING pDNStr = NULL;
  26. for ( DWORD i = 0; i < dwNumObjects; i++ )
  27. {
  28. pMem = NULL;
  29. switch ( pAdsDestValues[i].dwType )
  30. {
  31. case ADSTYPE_DN_STRING:
  32. pMem = (LPBYTE) pAdsDestValues[i].DNString;
  33. break;
  34. case ADSTYPE_CASE_EXACT_STRING:
  35. pMem = (LPBYTE) pAdsDestValues[i].CaseExactString;
  36. break;
  37. case ADSTYPE_CASE_IGNORE_STRING:
  38. pMem = (LPBYTE) pAdsDestValues[i].CaseIgnoreString;
  39. break;
  40. case ADSTYPE_PRINTABLE_STRING:
  41. pMem = (LPBYTE) pAdsDestValues[i].PrintableString;
  42. break;
  43. case ADSTYPE_NUMERIC_STRING:
  44. pMem = (LPBYTE) pAdsDestValues[i].NumericString;
  45. break;
  46. case ADSTYPE_OCTET_STRING:
  47. pMem = pAdsDestValues[i].OctetString.lpValue;
  48. break;
  49. case ADSTYPE_PROV_SPECIFIC:
  50. pMem = pAdsDestValues[i].ProviderSpecific.lpValue;
  51. break;
  52. case ADSTYPE_NT_SECURITY_DESCRIPTOR:
  53. pMem = pAdsDestValues[i].SecurityDescriptor.lpValue;
  54. break;
  55. case ADSTYPE_DN_WITH_STRING:
  56. pDNStr = pAdsDestValues[i].pDNWithString;
  57. if (pDNStr) {
  58. if (pDNStr->pszStringValue) {
  59. FreeADsStr(pDNStr->pszStringValue);
  60. }
  61. if (pDNStr->pszDNString) {
  62. FreeADsStr(pDNStr->pszDNString);
  63. }
  64. }
  65. FreeADsMem(pDNStr);
  66. pDNStr = NULL;
  67. break;
  68. case ADSTYPE_DN_WITH_BINARY:
  69. pDNBin = pAdsDestValues[i].pDNWithBinary;
  70. if (pDNBin) {
  71. if (pDNBin->lpBinaryValue) {
  72. FreeADsMem(pDNBin->lpBinaryValue);
  73. }
  74. if (pDNBin->pszDNString) {
  75. FreeADsStr(pDNBin->pszDNString);
  76. }
  77. }
  78. FreeADsMem(pDNBin);
  79. pDNBin = NULL;
  80. break;
  81. default:
  82. break;
  83. }
  84. if ( pMem )
  85. FreeADsMem( pMem );
  86. }
  87. FreeADsMem( pAdsDestValues );
  88. return;
  89. }
  90. HRESULT
  91. LdapTypeToAdsTypeDNString(
  92. PLDAPOBJECT pLdapSrcObject,
  93. PADSVALUE pAdsDestValue
  94. )
  95. {
  96. HRESULT hr = S_OK;
  97. pAdsDestValue->dwType = ADSTYPE_DN_STRING;
  98. pAdsDestValue->DNString = AllocADsStr( LDAPOBJECT_STRING(pLdapSrcObject));
  99. if ( pAdsDestValue->DNString == NULL )
  100. hr = E_OUTOFMEMORY;
  101. RRETURN(hr);
  102. }
  103. HRESULT
  104. LdapTypeToAdsTypeCaseExactString(
  105. PLDAPOBJECT pLdapSrcObject,
  106. PADSVALUE pAdsDestValue
  107. )
  108. {
  109. HRESULT hr = S_OK;
  110. pAdsDestValue->dwType = ADSTYPE_CASE_EXACT_STRING;
  111. pAdsDestValue->CaseExactString =
  112. AllocADsStr( LDAPOBJECT_STRING(pLdapSrcObject));
  113. if ( pAdsDestValue->CaseExactString == NULL )
  114. hr = E_OUTOFMEMORY;
  115. RRETURN(hr);
  116. }
  117. HRESULT
  118. LdapTypeToAdsTypeCaseIgnoreString(
  119. PLDAPOBJECT pLdapSrcObject,
  120. PADSVALUE pAdsDestValue
  121. )
  122. {
  123. HRESULT hr = S_OK;
  124. pAdsDestValue->dwType = ADSTYPE_CASE_IGNORE_STRING;
  125. pAdsDestValue->CaseIgnoreString =
  126. AllocADsStr( LDAPOBJECT_STRING(pLdapSrcObject));
  127. if ( pAdsDestValue->CaseIgnoreString == NULL )
  128. hr = E_OUTOFMEMORY;
  129. RRETURN(hr);
  130. }
  131. HRESULT
  132. LdapTypeToAdsTypePrintableString(
  133. PLDAPOBJECT pLdapSrcObject,
  134. PADSVALUE pAdsDestValue
  135. )
  136. {
  137. HRESULT hr = S_OK;
  138. pAdsDestValue->dwType = ADSTYPE_PRINTABLE_STRING;
  139. pAdsDestValue->PrintableString =
  140. AllocADsStr( LDAPOBJECT_STRING(pLdapSrcObject));
  141. if ( pAdsDestValue->PrintableString == NULL )
  142. hr = E_OUTOFMEMORY;
  143. RRETURN(hr);
  144. }
  145. HRESULT
  146. LdapTypeToAdsTypeNumericString(
  147. PLDAPOBJECT pLdapSrcObject,
  148. PADSVALUE pAdsDestValue
  149. )
  150. {
  151. HRESULT hr = S_OK;
  152. pAdsDestValue->dwType = ADSTYPE_NUMERIC_STRING;
  153. pAdsDestValue->NumericString =
  154. AllocADsStr( LDAPOBJECT_STRING(pLdapSrcObject));
  155. if ( pAdsDestValue->NumericString == NULL )
  156. hr = E_OUTOFMEMORY;
  157. RRETURN(hr);
  158. }
  159. HRESULT
  160. LdapTypeToAdsTypeBoolean(
  161. PLDAPOBJECT pLdapSrcObject,
  162. PADSVALUE pAdsDestValue
  163. )
  164. {
  165. HRESULT hr = S_OK;
  166. LPTSTR pszSrc = LDAPOBJECT_STRING(pLdapSrcObject);
  167. pAdsDestValue->dwType = ADSTYPE_BOOLEAN;
  168. if ( _tcsicmp( pszSrc, TEXT("TRUE")) == 0 )
  169. {
  170. pAdsDestValue->Boolean = TRUE;
  171. }
  172. else if ( _tcsicmp( pszSrc, TEXT("FALSE")) == 0 )
  173. {
  174. pAdsDestValue->Boolean = FALSE;
  175. }
  176. else
  177. {
  178. hr = E_ADS_CANT_CONVERT_DATATYPE;
  179. }
  180. RRETURN(hr);
  181. }
  182. HRESULT
  183. LdapTypeToAdsTypeInteger(
  184. PLDAPOBJECT pLdapSrcObject,
  185. PADSVALUE pAdsDestValue
  186. )
  187. {
  188. HRESULT hr = S_OK;
  189. pAdsDestValue->dwType = ADSTYPE_INTEGER;
  190. pAdsDestValue->Integer = _ttol(LDAPOBJECT_STRING(pLdapSrcObject));
  191. RRETURN(hr);
  192. }
  193. HRESULT
  194. LdapTypeToAdsTypeOctetString(
  195. PLDAPOBJECT pLdapSrcObject,
  196. PADSVALUE pAdsDestValue
  197. )
  198. {
  199. HRESULT hr = S_OK;
  200. DWORD dwLen = LDAPOBJECT_BERVAL_LEN(pLdapSrcObject);
  201. LPBYTE pBuffer = NULL;
  202. pAdsDestValue->dwType = ADSTYPE_OCTET_STRING;
  203. if ( (pBuffer = (LPBYTE) AllocADsMem( dwLen )) == NULL )
  204. RRETURN(E_OUTOFMEMORY);
  205. memcpy( pBuffer, LDAPOBJECT_BERVAL_VAL(pLdapSrcObject), dwLen );
  206. pAdsDestValue->OctetString.dwLength = dwLen;
  207. pAdsDestValue->OctetString.lpValue = pBuffer;
  208. RRETURN(hr);
  209. }
  210. HRESULT
  211. LdapTypeToAdsTypeNTSecurityDescriptor(
  212. PLDAPOBJECT pLdapSrcObject,
  213. PADSVALUE pAdsDestValue
  214. )
  215. {
  216. HRESULT hr = S_OK;
  217. DWORD dwLen = LDAPOBJECT_BERVAL_LEN(pLdapSrcObject);
  218. LPBYTE pBuffer = NULL;
  219. pAdsDestValue->dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  220. if ( (pBuffer = (LPBYTE) AllocADsMem( dwLen )) == NULL )
  221. RRETURN(E_OUTOFMEMORY);
  222. memcpy( pBuffer, LDAPOBJECT_BERVAL_VAL(pLdapSrcObject), dwLen );
  223. pAdsDestValue->SecurityDescriptor.dwLength = dwLen;
  224. pAdsDestValue->SecurityDescriptor.lpValue = pBuffer;
  225. RRETURN(hr);
  226. }
  227. HRESULT
  228. UTCTimeStringToUTCTime(
  229. LPWSTR szTime,
  230. SYSTEMTIME *pst)
  231. {
  232. FILETIME ft;
  233. TCHAR sz[3];
  234. LPWSTR pszSrc = szTime;
  235. SYSTEMTIME st;
  236. BOOL fSucceeded = FALSE;
  237. HRESULT hr = S_OK;
  238. //
  239. // Year
  240. //
  241. sz[0] = pszSrc[0];
  242. sz[1] = pszSrc[1];
  243. sz[2] = TEXT('\0');
  244. st.wYear = (WORD)_ttoi(sz);
  245. if (st.wYear < 50)
  246. {
  247. st.wYear += 2000;
  248. }
  249. else
  250. {
  251. st.wYear += 1900;
  252. }
  253. //
  254. // Month
  255. //
  256. sz[0] = pszSrc[2];
  257. sz[1] = pszSrc[3];
  258. st.wMonth = (WORD)_ttoi(sz);
  259. //
  260. // Day
  261. //
  262. sz[0] = pszSrc[4];
  263. sz[1] = pszSrc[5];
  264. st.wDay = (WORD)_ttoi(sz);
  265. //
  266. // Hour
  267. //
  268. sz[0] = pszSrc[6];
  269. sz[1] = pszSrc[7];
  270. st.wHour = (WORD)_ttoi(sz);
  271. //
  272. // Minute
  273. //
  274. sz[0] = pszSrc[8];
  275. sz[1] = pszSrc[9];
  276. st.wMinute = (WORD)_ttoi(sz);
  277. //
  278. // Second
  279. //
  280. sz[0] = pszSrc[10];
  281. sz[1] = pszSrc[11];
  282. st.wSecond = (WORD)_ttoi(sz);
  283. st.wMilliseconds = 0;
  284. //
  285. // This gets us the day of week, as per bug 87387.
  286. // SystemTimeToFileTime ignores the wDayOfWeek member, and
  287. // FileTimeToSystemTime sets it. A FileTime is precise down to
  288. // 100 nanoseconds, so there will never be conversion loss.
  289. //
  290. fSucceeded = SystemTimeToFileTime(&st, &ft);
  291. if (!fSucceeded) {
  292. BAIL_ON_FAILURE (hr = HRESULT_FROM_WIN32(GetLastError()));
  293. }
  294. fSucceeded = FileTimeToSystemTime(&ft, &st);
  295. if (!fSucceeded) {
  296. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  297. }
  298. *pst = st;
  299. error:
  300. RRETURN(hr);
  301. }
  302. //
  303. // GenTimeStringToUTCTime -- parse a GeneralizedTime string.
  304. //
  305. // An LDAP GeneralizedTime is the same as the ASN.1 GeneralizedTime.
  306. // Format given by:
  307. //
  308. // Type GeneralizedTime takes values of the year, month, day, hour,
  309. // time, minute, second, and second fraction in any of three forms.
  310. // 1. Local time only. "YYYYMMDDHHMMSS.fff", where the optional fff
  311. // is accurate to three decimal places.
  312. // 2. Universal time (UTC time) only. "YYYYMMDDHHMMSS.fffZ".
  313. // 3. Difference between local and UTC times.
  314. // "YYYYMMDDHHMMSS.fff+-HHMM".
  315. //
  316. // I'm being a little more lenient; if the string ends "early", i.e.
  317. // doesn't fill in all the required fields, it sets the rest to zero.
  318. // I'm doing this in particular because it's not clear if the "SS" for
  319. // seconds is optional. If this is a bad thing, change the #if below so
  320. // it signals an error conditions.
  321. //
  322. #if 1
  323. #define FINISH goto cleanup
  324. #else
  325. #define FINISH do { BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE); } while(0)
  326. #endif
  327. HRESULT
  328. GenTimeStringToUTCTime(
  329. LPWSTR szTime,
  330. SYSTEMTIME *pst)
  331. {
  332. HRESULT hr = S_OK;
  333. PWSTR pszSrc = szTime;
  334. DWORD dwStrlen = wcslen(pszSrc);
  335. SYSTEMTIME st, stZulu;
  336. WCHAR sz[5];
  337. // Make sure everything is zero first, in case we bail.
  338. memset((void *)&st, 0, sizeof(st));
  339. //
  340. // Year
  341. //
  342. if (dwStrlen < 4) FINISH;
  343. sz[0] = pszSrc[0];
  344. sz[1] = pszSrc[1];
  345. sz[2] = pszSrc[2];
  346. sz[3] = pszSrc[3];
  347. sz[4] = TEXT('\0');
  348. st.wYear = (WORD)_wtoi(sz);
  349. //
  350. // Month
  351. //
  352. if (dwStrlen < 6)
  353. goto cleanup;
  354. sz[0] = pszSrc[4];
  355. sz[1] = pszSrc[5];
  356. sz[2] = TEXT('\0');
  357. st.wMonth = (WORD)_wtoi(sz);
  358. //
  359. // Day
  360. //
  361. if (dwStrlen < 8) FINISH;
  362. sz[0] = pszSrc[6];
  363. sz[1] = pszSrc[7];
  364. st.wDay = (WORD)_wtoi(sz);
  365. //
  366. // Hour
  367. //
  368. if (dwStrlen < 10) FINISH;
  369. sz[0] = pszSrc[8];
  370. sz[1] = pszSrc[9];
  371. st.wHour = (WORD)_wtoi(sz);
  372. //
  373. // Minute
  374. //
  375. if (dwStrlen < 12) FINISH;
  376. sz[0] = pszSrc[10];
  377. sz[1] = pszSrc[11];
  378. st.wMinute = (WORD)_wtoi(sz);
  379. //
  380. // Second
  381. //
  382. if (dwStrlen < 14) FINISH;
  383. sz[0] = pszSrc[12];
  384. sz[1] = pszSrc[13];
  385. st.wSecond = (WORD)_wtoi(sz);
  386. //
  387. // Check for milliseconds.
  388. //
  389. pszSrc = pszSrc + 14; // we've read the first 14 characters
  390. if (*pszSrc == TEXT('.')) {
  391. pszSrc++;
  392. //
  393. // Milliseconds are defined as "optional", but it's unclear if this
  394. // means "all three digits or none at all". So play it safe.
  395. //
  396. PWSTR psz = sz;
  397. WORD wDigits = 0;
  398. while (*pszSrc != TEXT('\0') && iswdigit(*pszSrc) && wDigits < 3) {
  399. wDigits++;
  400. *psz++ = *pszSrc++;
  401. }
  402. while (wDigits < 3) {
  403. wDigits++;
  404. *psz++ = TEXT('0');
  405. }
  406. *psz = TEXT('\0');
  407. st.wMilliseconds = (WORD)_wtoi(sz);
  408. }
  409. //
  410. // Copy the systemTime into stZulu so it has the correct val.
  411. //
  412. memcpy((void *)&stZulu,(const void *)&st, sizeof(SYSTEMTIME));
  413. //
  414. // Now check if there's a time zone listed.
  415. //
  416. if (*pszSrc != TEXT('\0')) {
  417. switch (*pszSrc) {
  418. case TEXT('-'):
  419. case TEXT('+'):
  420. {
  421. BOOL fPositive = (*pszSrc == (TEXT('+')));
  422. pszSrc++;
  423. WORD wHours, wMinutes;
  424. sz[0] = *pszSrc++;
  425. sz[1] = *pszSrc++;
  426. sz[2] = 0;
  427. wHours = (WORD)_wtoi(sz);
  428. sz[0] = *pszSrc++;
  429. sz[1] = *pszSrc++;
  430. wMinutes = _wtoi(sz) + 60 * wHours;
  431. TIME_ZONE_INFORMATION tziOffset;
  432. tziOffset.Bias = wMinutes * (fPositive ? 1 : -1);
  433. tziOffset.StandardName[0] = TEXT('0');
  434. tziOffset.StandardDate.wMonth = 0;
  435. tziOffset.DaylightName[0] = TEXT('0');
  436. tziOffset.DaylightDate.wMonth = 0;
  437. if (!SystemTimeToTzSpecificLocalTime(
  438. &tziOffset,
  439. &st,
  440. &stZulu)) {
  441. RRETURN(hr = GetLastError());
  442. }
  443. }
  444. //
  445. // Now it's converted to Zulu time, so convert it back
  446. // to local time.
  447. //
  448. /*FALLTHROUGH*/
  449. case TEXT('Z'):
  450. {
  451. /*
  452. //
  453. // We want to return zulu time
  454. // not local uncomment to enable conversion
  455. // to localTime.
  456. //
  457. if (*pszSrc == TEXT('Z'))
  458. // and not '+' or '-'...
  459. memcpy((void *)&stZulu,
  460. (const void *)&st,
  461. sizeof(SYSTEMTIME));
  462. TIME_ZONE_INFORMATION tziLocal;
  463. GetTimeZoneInformation(&tziLocal);
  464. if (!SystemTimeToTzSpecificLocalTime(
  465. &tziLocal,
  466. &stZulu,
  467. &st)) {
  468. RRETURN(hr = GetLastError());
  469. }
  470. */
  471. //
  472. // At this point we have the correct value
  473. // in stZulu either way.
  474. //
  475. memcpy(
  476. (void *) &st,
  477. (const void *)&stZulu,
  478. sizeof(SYSTEMTIME)
  479. );
  480. }
  481. break;
  482. default:
  483. RRETURN(hr = E_ADS_CANT_CONVERT_DATATYPE);
  484. }
  485. }
  486. cleanup:
  487. *pst = st;
  488. RRETURN(hr);
  489. }
  490. HRESULT
  491. LdapTypeToAdsTypeUTCTime(
  492. PLDAPOBJECT pLdapSrcObject,
  493. PADSVALUE pAdsDestValue
  494. )
  495. {
  496. HRESULT hr = S_OK;
  497. SYSTEMTIME st;
  498. PTSTR pszSrc = LDAPOBJECT_STRING(pLdapSrcObject);
  499. hr = UTCTimeStringToUTCTime(pszSrc,
  500. &st);
  501. BAIL_ON_FAILURE(hr);
  502. pAdsDestValue->dwType = ADSTYPE_UTC_TIME;
  503. pAdsDestValue->UTCTime = st;
  504. error:
  505. RRETURN(hr);
  506. }
  507. HRESULT
  508. LdapTypeToAdsTypeGeneralizedTime(
  509. PLDAPOBJECT pLdapSrcObject,
  510. PADSVALUE pAdsDestValue
  511. )
  512. {
  513. HRESULT hr = S_OK;
  514. SYSTEMTIME st;
  515. PWSTR pszSrc = LDAPOBJECT_STRING(pLdapSrcObject);
  516. hr = GenTimeStringToUTCTime(pszSrc,
  517. &st);
  518. BAIL_ON_FAILURE(hr);
  519. pAdsDestValue->dwType = ADSTYPE_UTC_TIME;
  520. pAdsDestValue->UTCTime = st;
  521. error:
  522. RRETURN(hr);
  523. }
  524. HRESULT
  525. LdapTypeToAdsTypeLargeInteger(
  526. PLDAPOBJECT pLdapSrcObject,
  527. PADSVALUE pAdsDestValue
  528. )
  529. {
  530. HRESULT hr = S_OK;
  531. pAdsDestValue->dwType = ADSTYPE_LARGE_INTEGER;
  532. swscanf (LDAPOBJECT_STRING(pLdapSrcObject), L"%I64d", &pAdsDestValue->LargeInteger);
  533. RRETURN(hr);
  534. }
  535. //
  536. // Just calls the helper routine - the helper is needed
  537. // because of the way in which IDirectorySearch works
  538. //
  539. HRESULT
  540. LdapTypeToAdsTypeDNWithBinary(
  541. PLDAPOBJECT pLdapSrcObject,
  542. PADSVALUE pAdsDestValue
  543. )
  544. {
  545. RRETURN(LdapDNWithBinToAdsTypeHelper(
  546. LDAPOBJECT_STRING(pLdapSrcObject),
  547. pAdsDestValue
  548. )
  549. );
  550. }
  551. //
  552. // Wire format of DNWithBinary is :
  553. // B:32:a9d1ca15768811d1aded00c04fd8d5cd:dc=ntdev,dc=microsoft,dc=com
  554. //
  555. HRESULT
  556. LdapDNWithBinToAdsTypeHelper(
  557. LPWSTR pszLdapSrcString,
  558. PADSVALUE pAdsDestValue
  559. )
  560. {
  561. HRESULT hr = S_OK;
  562. DWORD dwCount = 0;
  563. DWORD dwBinLen = 0;
  564. LPWSTR pszLdapStr = NULL;
  565. LPBYTE lpByte = NULL;
  566. PADS_DN_WITH_BINARY pDNBin = NULL;
  567. WCHAR wCurChar;
  568. pAdsDestValue->dwType = ADSTYPE_DN_WITH_BINARY;
  569. pDNBin = (PADS_DN_WITH_BINARY) AllocADsMem(sizeof(ADS_DN_WITH_BINARY));
  570. if (!pDNBin) {
  571. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  572. }
  573. pszLdapStr = pszLdapSrcString;
  574. if (!pszLdapStr) {
  575. //
  576. // NULL value
  577. //
  578. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  579. }
  580. if (wcslen(pszLdapStr) < 5 ) {
  581. //
  582. // B:x:: is the smallest string
  583. //
  584. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  585. }
  586. wCurChar = *pszLdapStr++;
  587. //
  588. // String should begin with B
  589. //
  590. if (wCurChar != L'B') {
  591. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  592. }
  593. //
  594. // Skip the : and get the length
  595. //
  596. *pszLdapStr++;
  597. dwCount = swscanf(pszLdapStr, L"%ld", &dwBinLen);
  598. //
  599. // This is the actual length of the byte array
  600. //
  601. dwBinLen /= 2;
  602. if (dwCount != 1) {
  603. //
  604. // Trouble reading the length
  605. //
  606. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  607. }
  608. //
  609. // Go onto the start of the encoded string
  610. //
  611. while(*pszLdapStr && (wCurChar != L':')) {
  612. wCurChar = *pszLdapStr++;
  613. }
  614. if (wCurChar != L':') {
  615. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  616. }
  617. //
  618. // Get the byte array from string if there are any elements in it
  619. //
  620. if (dwCount != 0) {
  621. //
  622. // The DWORD cushion is to make sure we do not overwrite
  623. // the buffer while reading from the string.
  624. //
  625. lpByte = (LPBYTE) AllocADsMem(dwBinLen + sizeof(DWORD));
  626. if (!lpByte) {
  627. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  628. }
  629. for (dwCount = 0; dwCount < dwBinLen; dwCount++) {
  630. swscanf(pszLdapStr, L"%02X", &lpByte[dwCount]);
  631. pszLdapStr += 2;
  632. }
  633. pDNBin->lpBinaryValue = lpByte;
  634. }
  635. //
  636. // Get the DN
  637. //
  638. wCurChar = *pszLdapStr++;
  639. if (wCurChar != L':') {
  640. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  641. }
  642. pDNBin->pszDNString = AllocADsStr(pszLdapStr);
  643. if (!pszLdapStr && !pDNBin->pszDNString) {
  644. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  645. }
  646. pDNBin->dwLength = dwBinLen;
  647. pAdsDestValue->pDNWithBinary = pDNBin;
  648. RRETURN(hr);
  649. error:
  650. if (pDNBin) {
  651. if (pDNBin->pszDNString) {
  652. FreeADsStr(pDNBin->pszDNString);
  653. }
  654. FreeADsMem(pDNBin);
  655. }
  656. if (lpByte) {
  657. FreeADsMem(lpByte);
  658. }
  659. RRETURN(hr);
  660. }
  661. //
  662. // Calls the helper that does the work - helper is needed by
  663. // IDirectorySearch when returning columns.
  664. //
  665. HRESULT
  666. LdapTypeToAdsTypeDNWithString(
  667. PLDAPOBJECT pLdapSrcObject,
  668. PADSVALUE pAdsDestValue
  669. )
  670. {
  671. RRETURN(LdapDNWithStrToAdsTypeHelper(
  672. LDAPOBJECT_STRING(pLdapSrcObject),
  673. pAdsDestValue
  674. )
  675. );
  676. }
  677. //
  678. // Wire format of DNWithString is :
  679. // S:9:OurDomain:dc=ntdev,dc=microsoft,dc=com
  680. //
  681. HRESULT
  682. LdapDNWithStrToAdsTypeHelper(
  683. LPWSTR pszLdapSrcString,
  684. PADSVALUE pAdsDestValue
  685. )
  686. {
  687. HRESULT hr = S_OK;
  688. DWORD dwCount = 0;
  689. DWORD dwStrLen = 0;
  690. LPWSTR pszLdapStr = NULL;
  691. PADS_DN_WITH_STRING pDNStr = NULL;
  692. WCHAR wCurChar;
  693. pAdsDestValue->dwType = ADSTYPE_DN_WITH_STRING;
  694. pDNStr = (PADS_DN_WITH_STRING) AllocADsMem(sizeof(ADS_DN_WITH_STRING));
  695. if (!pDNStr) {
  696. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  697. }
  698. pszLdapStr = pszLdapSrcString;
  699. if (!pszLdapStr) {
  700. //
  701. // NULL value
  702. //
  703. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  704. }
  705. if (wcslen(pszLdapStr) < 5) {
  706. //
  707. // S:x:: being the minimum
  708. //
  709. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  710. }
  711. wCurChar = *pszLdapStr++;
  712. if (wCurChar != L'S') {
  713. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  714. }
  715. //
  716. // Skip : and go onto the length
  717. //
  718. *pszLdapStr++;
  719. dwCount = swscanf(pszLdapStr, L"%ld:", &dwStrLen);
  720. wCurChar = *pszLdapStr;
  721. //
  722. // Go onto the start of the string
  723. //
  724. while (*pszLdapStr && (wCurChar != L':')) {
  725. wCurChar = *pszLdapStr++;
  726. }
  727. if (wCurChar != L':') {
  728. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  729. }
  730. //
  731. // Copy over the string value if applicable
  732. //
  733. if (dwStrLen != 0) {
  734. pDNStr->pszStringValue = (LPWSTR)
  735. AllocADsMem((dwStrLen + 1) * sizeof(WCHAR));
  736. if (!pDNStr->pszStringValue) {
  737. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  738. }
  739. wcsncat(pDNStr->pszStringValue, pszLdapStr, dwStrLen);
  740. }
  741. //
  742. // Move past to begining of the DN
  743. //
  744. pszLdapStr += (dwStrLen+1);
  745. pDNStr->pszDNString = AllocADsStr(pszLdapStr);
  746. if (pszLdapStr && !pDNStr->pszDNString) {
  747. //
  748. // DN was not NULL and we could not alloc.
  749. //
  750. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  751. }
  752. pAdsDestValue->pDNWithString = pDNStr;
  753. RRETURN(hr);
  754. error:
  755. if (pDNStr) {
  756. if (pDNStr->pszStringValue) {
  757. FreeADsStr(pDNStr->pszStringValue);
  758. }
  759. if (pDNStr->pszDNString) {
  760. FreeADsStr(pDNStr->pszDNString);
  761. }
  762. FreeADsMem(pDNStr);
  763. }
  764. RRETURN(hr);
  765. }
  766. HRESULT
  767. LdapTypeToAdsTypeProvSpecific(
  768. PLDAPOBJECT pLdapSrcObject,
  769. PADSVALUE pAdsDestValue
  770. )
  771. {
  772. HRESULT hr = S_OK;
  773. DWORD dwLen = LDAPOBJECT_BERVAL_LEN(pLdapSrcObject);
  774. LPBYTE pBuffer = NULL;
  775. pAdsDestValue->dwType = ADSTYPE_PROV_SPECIFIC;
  776. if ( (pBuffer = (LPBYTE) AllocADsMem( dwLen )) == NULL )
  777. RRETURN(E_OUTOFMEMORY);
  778. memcpy( pBuffer, LDAPOBJECT_BERVAL_VAL(pLdapSrcObject), dwLen );
  779. pAdsDestValue->ProviderSpecific.dwLength = dwLen;
  780. pAdsDestValue->ProviderSpecific.lpValue = pBuffer;
  781. RRETURN(hr);
  782. }
  783. HRESULT
  784. LdapTypeToAdsTypeCopy(
  785. PLDAPOBJECT pLdapSrcObject,
  786. DWORD dwSyntaxId,
  787. PADSVALUE pAdsDestValue
  788. )
  789. {
  790. HRESULT hr = S_OK;
  791. switch ( dwSyntaxId ) {
  792. case LDAPTYPE_DN:
  793. hr = LdapTypeToAdsTypeDNString(
  794. pLdapSrcObject,
  795. pAdsDestValue
  796. );
  797. break;
  798. case LDAPTYPE_CASEEXACTSTRING:
  799. hr = LdapTypeToAdsTypeCaseExactString(
  800. pLdapSrcObject,
  801. pAdsDestValue
  802. );
  803. break;
  804. case LDAPTYPE_CASEIGNORESTRING:
  805. // case LDAPTYPE_CASEIGNOREIA5STRING:
  806. case LDAPTYPE_BITSTRING:
  807. case LDAPTYPE_DIRECTORYSTRING:
  808. case LDAPTYPE_COUNTRYSTRING:
  809. case LDAPTYPE_IA5STRING:
  810. case LDAPTYPE_OID:
  811. case LDAPTYPE_TELEPHONENUMBER:
  812. case LDAPTYPE_ATTRIBUTETYPEDESCRIPTION:
  813. case LDAPTYPE_OBJECTCLASSDESCRIPTION:
  814. case LDAPTYPE_POSTALADDRESS:
  815. case LDAPTYPE_DELIVERYMETHOD:
  816. case LDAPTYPE_ENHANCEDGUIDE:
  817. case LDAPTYPE_FACSIMILETELEPHONENUMBER:
  818. case LDAPTYPE_GUIDE:
  819. case LDAPTYPE_NAMEANDOPTIONALUID:
  820. case LDAPTYPE_PRESENTATIONADDRESS:
  821. case LDAPTYPE_TELEXNUMBER:
  822. case LDAPTYPE_DSAQUALITYSYNTAX:
  823. case LDAPTYPE_DATAQUALITYSYNTAX:
  824. case LDAPTYPE_MAILPREFERENCE:
  825. case LDAPTYPE_OTHERMAILBOX:
  826. case LDAPTYPE_ACCESSPOINTDN:
  827. case LDAPTYPE_ORNAME:
  828. case LDAPTYPE_ORADDRESS:
  829. hr = LdapTypeToAdsTypeCaseIgnoreString(
  830. pLdapSrcObject,
  831. pAdsDestValue
  832. );
  833. break;
  834. case LDAPTYPE_PRINTABLESTRING:
  835. hr = LdapTypeToAdsTypePrintableString(
  836. pLdapSrcObject,
  837. pAdsDestValue
  838. );
  839. break;
  840. case LDAPTYPE_NUMERICSTRING:
  841. hr = LdapTypeToAdsTypeNumericString(
  842. pLdapSrcObject,
  843. pAdsDestValue
  844. );
  845. break;
  846. case LDAPTYPE_BOOLEAN:
  847. hr = LdapTypeToAdsTypeBoolean(
  848. pLdapSrcObject,
  849. pAdsDestValue
  850. );
  851. break;
  852. case LDAPTYPE_INTEGER:
  853. hr = LdapTypeToAdsTypeInteger(
  854. pLdapSrcObject,
  855. pAdsDestValue
  856. );
  857. break;
  858. case LDAPTYPE_OCTETSTRING:
  859. case LDAPTYPE_CERTIFICATE:
  860. case LDAPTYPE_CERTIFICATELIST:
  861. case LDAPTYPE_CERTIFICATEPAIR:
  862. case LDAPTYPE_PASSWORD:
  863. case LDAPTYPE_TELETEXTERMINALIDENTIFIER:
  864. case LDAPTYPE_AUDIO:
  865. case LDAPTYPE_JPEG:
  866. case LDAPTYPE_FAX:
  867. hr = LdapTypeToAdsTypeOctetString(
  868. pLdapSrcObject,
  869. pAdsDestValue
  870. );
  871. break;
  872. case LDAPTYPE_SECURITY_DESCRIPTOR:
  873. hr = LdapTypeToAdsTypeNTSecurityDescriptor(
  874. pLdapSrcObject,
  875. pAdsDestValue
  876. );
  877. break;
  878. case LDAPTYPE_UTCTIME:
  879. hr = LdapTypeToAdsTypeUTCTime(
  880. pLdapSrcObject,
  881. pAdsDestValue
  882. );
  883. break;
  884. case LDAPTYPE_GENERALIZEDTIME:
  885. hr = LdapTypeToAdsTypeGeneralizedTime(
  886. pLdapSrcObject,
  887. pAdsDestValue
  888. );
  889. break;
  890. case LDAPTYPE_INTEGER8:
  891. hr = LdapTypeToAdsTypeLargeInteger(
  892. pLdapSrcObject,
  893. pAdsDestValue
  894. );
  895. break;
  896. #if 0
  897. case LDAPTYPE_CASEEXACTLIST:
  898. case LDAPTYPE_CASEIGNORELIST:
  899. #endif
  900. case LDAPTYPE_DNWITHBINARY:
  901. hr = LdapTypeToAdsTypeDNWithBinary(
  902. pLdapSrcObject,
  903. pAdsDestValue
  904. );
  905. break;
  906. case LDAPTYPE_DNWITHSTRING:
  907. hr = LdapTypeToAdsTypeDNWithString(
  908. pLdapSrcObject,
  909. pAdsDestValue
  910. );
  911. break;
  912. //
  913. // Treat unknown as provider specific blob.
  914. //
  915. case LDAPTYPE_UNKNOWN:
  916. hr = LdapTypeToAdsTypeProvSpecific(
  917. pLdapSrcObject,
  918. pAdsDestValue
  919. );
  920. break;
  921. default:
  922. //
  923. // LDPATYPE_UNKNOWN (e.g schemaless server property)
  924. //
  925. hr = E_ADS_CANT_CONVERT_DATATYPE;
  926. break;
  927. }
  928. RRETURN(hr);
  929. }
  930. HRESULT
  931. LdapTypeToAdsTypeCopyConstruct(
  932. LDAPOBJECTARRAY ldapSrcObjects,
  933. DWORD dwSyntaxId,
  934. LPADSVALUE *ppAdsDestValues,
  935. PDWORD pdwNumAdsValues,
  936. PDWORD pdwAdsType
  937. )
  938. {
  939. DWORD i = 0;
  940. LPADSVALUE pAdsDestValues = NULL;
  941. HRESULT hr = S_OK;
  942. DWORD dwNumObjects = ldapSrcObjects.dwCount;
  943. *ppAdsDestValues = NULL;
  944. *pdwNumAdsValues = dwNumObjects;
  945. *pdwAdsType = ADSTYPE_UNKNOWN;
  946. if (dwNumObjects != 0) {
  947. pAdsDestValues = (LPADSVALUE) AllocADsMem(
  948. dwNumObjects * sizeof(ADSVALUE)
  949. );
  950. if (!pAdsDestValues)
  951. RRETURN(E_OUTOFMEMORY);
  952. for ( i = 0; i < dwNumObjects; i++ ) {
  953. hr = LdapTypeToAdsTypeCopy(
  954. ldapSrcObjects.pLdapObjects + i,
  955. dwSyntaxId,
  956. pAdsDestValues + i
  957. );
  958. BAIL_ON_FAILURE(hr);
  959. }
  960. *ppAdsDestValues = pAdsDestValues;
  961. //
  962. // We will set the pdwAdsType value to the first type
  963. //
  964. *pdwAdsType = (pAdsDestValues)->dwType;
  965. } else {
  966. // Set the pddwAdsType appropriately, values are null.
  967. *pdwAdsType = MapLDAPTypeToADSType(dwSyntaxId);
  968. }
  969. RRETURN(S_OK);
  970. error:
  971. if (pAdsDestValues) {
  972. AdsTypeFreeAdsObjects(
  973. pAdsDestValues,
  974. i
  975. );
  976. }
  977. *ppAdsDestValues = NULL;
  978. RRETURN(hr);
  979. }