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.

899 lines
22 KiB

  1. /*--------------------------------------------------------------------------
  2. ldapber.cxx
  3. This module contains the implementation for the LDAP Basic Encoding
  4. Rules (BER) class. It is intended to be built for both client and
  5. server.
  6. Copyright (C) 1993 Microsoft Corporation
  7. All rights reserved.
  8. Authors:
  9. robertc Rob Carney
  10. History:
  11. 04-17-96 robertc Created.
  12. --------------------------------------------------------------------------*/
  13. #include "ldappch.h"
  14. #ifdef CLIENT
  15. #define ALLOCATE(cb) LocalAlloc(LMEM_FIXED, cb)
  16. #define FREE LocalFree
  17. #else
  18. //CPool CLdapBer::m_cpool(CLIENT_CONNECTION_SIGNATURE_VALID);
  19. //#define Assert(x) _ASSERT(x)
  20. #define ALLOCATE(cb) malloc(cb)
  21. #define FREE free
  22. #endif
  23. //
  24. // CLdapBer Implementation
  25. //
  26. CLdapBer::CLdapBer()
  27. {
  28. m_cbData = 0;
  29. m_cbDataMax = 0;
  30. m_pbData = NULL;
  31. m_iCurrPos = 0;
  32. m_cbSeq = 0;
  33. m_iSeqStart = 0;
  34. m_fLocalCopy = TRUE;
  35. m_iCurrSeqStack = 0;
  36. }
  37. CLdapBer::~CLdapBer()
  38. {
  39. Reset();
  40. if (m_pbData && m_fLocalCopy)
  41. FREE(m_pbData);
  42. m_cbDataMax = 0;
  43. }
  44. /*!-------------------------------------------------------------------------
  45. CLdapBer::Reset
  46. Resets the class.
  47. ------------------------------------------------------------------------*/
  48. void CLdapBer::Reset()
  49. {
  50. m_cbData = 0;
  51. m_iCurrPos = 0;
  52. m_cbSeq = 0;
  53. m_iSeqStart = 0;
  54. m_iCurrSeqStack = 0;
  55. }
  56. /*!-------------------------------------------------------------------------
  57. CLdapBer::HrLoadBer
  58. This routine loads the BER class from an input source data buffer
  59. that was received from the server.
  60. ------------------------------------------------------------------------*/
  61. HRESULT CLdapBer::HrLoadBer(BYTE *pbSrc, ULONG cbSrc, BOOL fLocalCopy/*=TRUE*/)
  62. {
  63. BYTE *pbEnd;
  64. ULONG iCurr, cbT;
  65. HRESULT hr;
  66. Reset();
  67. if (!fLocalCopy)
  68. {
  69. // Just keep a reference so free any memory we once had.
  70. if (m_pbData && m_fLocalCopy)
  71. {
  72. FREE(m_pbData);
  73. m_pbData = NULL;
  74. m_cbDataMax = 0;
  75. }
  76. m_pbData = pbSrc;
  77. m_fLocalCopy = FALSE;
  78. }
  79. else
  80. {
  81. m_fLocalCopy = TRUE;
  82. hr = HrEnsureBuffer(cbSrc, TRUE);
  83. if (FAILED(hr))
  84. return hr;
  85. CopyMemory(m_pbData, pbSrc, cbSrc);
  86. }
  87. m_cbData = cbSrc;
  88. //
  89. // Get at the sequence length and make sure we have all the data.
  90. HrSkipTag();
  91. GetCbLength(m_pbData + m_iCurrPos, &cbT);
  92. HrPeekLength(&m_cbSeq);
  93. if (m_cbSeq > (m_cbData - m_iCurrPos - cbT))
  94. return E_FAIL;
  95. HrUnSkipTag();
  96. m_cbSeq = m_cbData;
  97. return NOERROR;
  98. }
  99. /*!-------------------------------------------------------------------------
  100. CLdapBer::FCheckSequenceLength
  101. This is a static function that checks to see if the input buffer
  102. contains the full length field. If so, the length of the sequence
  103. is returned along with the position of the first value in the list.
  104. ------------------------------------------------------------------------*/
  105. BOOL CLdapBer::FCheckSequenceLength(BYTE *pbInput, ULONG cbInput, ULONG *pcbSeq, ULONG *piValuePos)
  106. {
  107. ULONG cbLen;
  108. // Assume Tag is 1 byte and length is at least 1 byte.
  109. if (cbInput >= 2)
  110. {
  111. GetCbLength(pbInput+1, &cbLen);
  112. if (cbInput >= (1 + cbLen))
  113. {
  114. *piValuePos = 1;
  115. if (SUCCEEDED(HrGetLength(pbInput, pcbSeq, piValuePos)))
  116. return TRUE;
  117. }
  118. }
  119. return FALSE;
  120. }
  121. /*!-------------------------------------------------------------------------
  122. CLdapBer::HrStartReadSequence
  123. Start a sequence for reading.
  124. ------------------------------------------------------------------------*/
  125. HRESULT CLdapBer::HrStartReadSequence(ULONG ulTag/*=BER_SEQUENCE*/)
  126. {
  127. HRESULT hr;
  128. ULONG iPos, cbLength;
  129. if ((ULONG)m_pbData[m_iCurrPos] != ulTag)
  130. {
  131. return E_INVALIDARG;
  132. }
  133. m_iCurrPos++; // Skip over the tag.
  134. GetCbLength(m_pbData + m_iCurrPos, &cbLength); // Get the # bytes in the length field.
  135. hr = HrPushSeqStack(m_iCurrPos, cbLength, m_iSeqStart, m_cbSeq);
  136. if (SUCCEEDED(hr))
  137. {
  138. // Get the length of the sequence.
  139. hr = HrGetLength(&m_cbSeq);
  140. if (FAILED(hr))
  141. HrPopSeqStack(&iPos, &cbLength, &m_iSeqStart, &m_cbSeq);
  142. else
  143. m_iSeqStart = m_iCurrPos; // Set to the first position in the sequence.
  144. }
  145. if (m_iCurrPos > m_cbData)
  146. {
  147. Assert(m_iCurrPos <= m_cbData);
  148. hr = E_INVALIDARG;
  149. }
  150. return hr;
  151. }
  152. /*!-------------------------------------------------------------------------
  153. CLdapBer::HrEndReadSequence
  154. Ends a read sequence and restores the current sequence counters.
  155. ------------------------------------------------------------------------*/
  156. HRESULT CLdapBer::HrEndReadSequence()
  157. {
  158. ULONG cbSeq;
  159. ULONG iPos, iPosSave, cbLength;
  160. SEQ_STACK seqstack;
  161. HRESULT hr;
  162. hr = HrPopSeqStack(&m_iCurrPos, &cbLength, &m_iSeqStart, &m_cbSeq);
  163. // Now position the current position to the end of the sequence.
  164. // m_iCurrPos is now pointing to the length field of the sequence.
  165. iPos = m_iCurrPos;
  166. if (SUCCEEDED(hr))
  167. {
  168. hr = HrGetLength(&cbSeq);
  169. if (SUCCEEDED(hr))
  170. {
  171. // Set the current position to the end of the sequence.
  172. m_iCurrPos = iPos + cbSeq + cbLength;
  173. if (m_iCurrPos > m_cbData)
  174. hr = E_INVALIDARG;
  175. }
  176. }
  177. return hr;
  178. }
  179. /*!-------------------------------------------------------------------------
  180. CLdapBer::HrStartWriteSequence
  181. Start a sequence for writing.
  182. ------------------------------------------------------------------------*/
  183. HRESULT CLdapBer::HrStartWriteSequence(ULONG ulTag/*=BER_SEQUENCE*/)
  184. {
  185. HRESULT hr;
  186. ULONG cbLength = 3; // BUGBUG: Defaults to 2 byte lengths
  187. if (FAILED(hr = HrEnsureBuffer(cbLength + 1)))
  188. return hr;
  189. m_pbData[m_iCurrPos++] = (BYTE)ulTag;
  190. hr = HrPushSeqStack(m_iCurrPos, cbLength, m_iSeqStart, m_cbSeq);
  191. m_iCurrPos += cbLength; // Skip over length
  192. m_cbData = m_iCurrPos;
  193. return hr;
  194. }
  195. /*!-------------------------------------------------------------------------
  196. CLdapBer::HrEndWriteSequence
  197. Ends a write sequence, by putting the sequence length field in.
  198. ------------------------------------------------------------------------*/
  199. HRESULT CLdapBer::HrEndWriteSequence()
  200. {
  201. HRESULT hr;
  202. ULONG cbSeq;
  203. ULONG iPos, iPosSave, cbLength;
  204. SEQ_STACK seqstack;
  205. hr = HrPopSeqStack(&iPos, &cbLength, &m_iSeqStart, &m_cbSeq);
  206. if (SUCCEEDED(hr))
  207. {
  208. // Get the length of the current sequence.
  209. cbSeq = m_iCurrPos - iPos - cbLength;
  210. // Save & set the current position.
  211. iPosSave = m_iCurrPos;
  212. m_iCurrPos = iPos;
  213. hr = HrSetLength(cbSeq, cbLength);
  214. m_iCurrPos = iPosSave;
  215. }
  216. return hr;
  217. }
  218. /*!-------------------------------------------------------------------------
  219. CLdapBer::HrPushSeqStack
  220. Pushes the current value on the sequence stack.
  221. ------------------------------------------------------------------------*/
  222. HRESULT CLdapBer::HrPushSeqStack(ULONG iPos, ULONG cbLength, ULONG iParentSeqStart, ULONG cbParentSeq)
  223. {
  224. ULONG cb;
  225. Assert(m_iCurrSeqStack < MAX_BER_STACK);
  226. if (m_iCurrSeqStack >= MAX_BER_STACK)
  227. return E_OUTOFMEMORY;
  228. m_rgiSeqStack[m_iCurrSeqStack].iPos = iPos;
  229. m_rgiSeqStack[m_iCurrSeqStack].cbLength = cbLength;
  230. m_rgiSeqStack[m_iCurrSeqStack].iParentSeqStart = iParentSeqStart;
  231. m_rgiSeqStack[m_iCurrSeqStack].cbParentSeq = cbParentSeq;
  232. m_iCurrSeqStack++;
  233. return NOERROR;
  234. }
  235. /*!-------------------------------------------------------------------------
  236. CLdapBer::HrPopSeqStack
  237. Ends a read sequence.
  238. ------------------------------------------------------------------------*/
  239. HRESULT CLdapBer::HrPopSeqStack(ULONG *piPos, ULONG *pcbLength, ULONG *piParentSeqStart, ULONG *pcbParentSeq)
  240. {
  241. if (m_iCurrSeqStack == 0)
  242. {
  243. Assert(m_iCurrSeqStack != 0);
  244. return E_INVALIDARG;
  245. }
  246. --m_iCurrSeqStack;
  247. *piPos = m_rgiSeqStack[m_iCurrSeqStack].iPos;
  248. *pcbLength = m_rgiSeqStack[m_iCurrSeqStack].cbLength;
  249. *piParentSeqStart = m_rgiSeqStack[m_iCurrSeqStack].iParentSeqStart;
  250. *pcbParentSeq = m_rgiSeqStack[m_iCurrSeqStack].cbParentSeq;
  251. return NOERROR;
  252. }
  253. /*!-------------------------------------------------------------------------
  254. CLdapBer::FSetCurrPos
  255. Sets the current position to the input position index.
  256. ------------------------------------------------------------------------*/
  257. HRESULT CLdapBer::FSetCurrPos(ULONG iCurrPos)
  258. {
  259. if (iCurrPos >= m_cbData)
  260. return E_FAIL;
  261. m_iCurrPos = iCurrPos;
  262. return NOERROR;
  263. }
  264. /*!-------------------------------------------------------------------------
  265. CLdapBer::HrSkipValue
  266. This routine skips over the current BER value.
  267. ------------------------------------------------------------------------*/
  268. HRESULT CLdapBer::HrSkipValue()
  269. {
  270. return E_NOTIMPL;
  271. }
  272. /*!-------------------------------------------------------------------------
  273. CLdapBer::HrSkipTag
  274. Skips over the current tag.
  275. ------------------------------------------------------------------------*/
  276. HRESULT CLdapBer::HrSkipTag()
  277. {
  278. m_iCurrPos++;
  279. return NOERROR;
  280. }
  281. /*!-------------------------------------------------------------------------
  282. CLdapBer::HrUnSkipTag
  283. Goes back to the tag given that we're currently at the length
  284. field.
  285. ------------------------------------------------------------------------*/
  286. HRESULT CLdapBer::HrUnSkipTag()
  287. {
  288. m_iCurrPos--;
  289. return NOERROR;
  290. }
  291. /*!-------------------------------------------------------------------------
  292. CLdapBer::HrPeekTag
  293. This routine gets the current tag, but doesn't increment the
  294. current position.
  295. ------------------------------------------------------------------------*/
  296. HRESULT CLdapBer::HrPeekTag(ULONG *pulTag)
  297. {
  298. ULONG iPos;
  299. iPos = m_iCurrPos;
  300. *pulTag = (ULONG)m_pbData[iPos];
  301. return NOERROR;
  302. }
  303. /*!-------------------------------------------------------------------------
  304. CLdapBer::HrGetValue
  305. This routine gets an integer value from the current BER entry. The
  306. default tag is an integer, but can Tagged with a different value
  307. via ulTag.
  308. Returns: NOERROR, E_INVALIDARG, E_OUTOFMEMORY
  309. ------------------------------------------------------------------------*/
  310. HRESULT CLdapBer::HrGetValue(LONG *pi, ULONG ulTag/*=BER_INTEGER*/)
  311. {
  312. HRESULT hr;
  313. ULONG cb;
  314. ULONG ul;
  315. ul = (ULONG)m_pbData[m_iCurrPos++]; // TAG
  316. if (ul != ulTag)
  317. {
  318. Assert(ul == ulTag);
  319. return E_INVALIDARG;
  320. }
  321. hr = HrGetLength(&cb);
  322. if (SUCCEEDED(hr) && (m_iCurrPos < m_cbData))
  323. {
  324. GetInt(m_pbData + m_iCurrPos, cb, pi);
  325. m_iCurrPos += cb;
  326. }
  327. return hr;
  328. }
  329. /*!-------------------------------------------------------------------------
  330. CLdapBer::HrGetValue
  331. This routine gets a string value from the current BER entry. If
  332. the current BER entry isn't an integer type, then E_INVALIDARG is
  333. returned.
  334. ------------------------------------------------------------------------*/
  335. HRESULT CLdapBer::HrGetValue(TCHAR *szValue, ULONG cbValue, ULONG ulTag/*=BER_OCTETSTRING*/)
  336. {
  337. HRESULT hr;
  338. ULONG cb, ul;
  339. ul = (ULONG)m_pbData[m_iCurrPos++]; // TAG
  340. if (ul != ulTag)
  341. {
  342. Assert(ul == ulTag);
  343. return E_INVALIDARG;
  344. }
  345. hr = HrGetLength(&cb);
  346. szValue[0] = '\0';
  347. if (SUCCEEDED(hr) && (m_iCurrPos < m_cbData))
  348. {
  349. if (cb >= cbValue)
  350. {
  351. Assert(cb < cbValue);
  352. hr = E_INVALIDARG;
  353. }
  354. else
  355. {
  356. // Get the string.
  357. CopyMemory(szValue, m_pbData + m_iCurrPos, cb);
  358. szValue[cb] = '\0';
  359. m_iCurrPos += cb;
  360. }
  361. }
  362. return hr;
  363. }
  364. /*!-------------------------------------------------------------------------
  365. CLdapBer::HrGetBinaryValue
  366. This routine gets a binary value from the current BER entry. If
  367. the current BER entry isn't the right type, then E_INVALIDARG is
  368. returned.
  369. ------------------------------------------------------------------------*/
  370. HRESULT CLdapBer::HrGetBinaryValue(BYTE *pbBuf, ULONG cbBuf, ULONG ulTag/*=BER_OCTETSTRING*/)
  371. {
  372. HRESULT hr;
  373. ULONG cb, ul;
  374. ul = (ULONG)m_pbData[m_iCurrPos++]; // TAG
  375. if (ul != ulTag)
  376. {
  377. Assert(ul == ulTag);
  378. return E_INVALIDARG;
  379. }
  380. hr = HrGetLength(&cb);
  381. if (SUCCEEDED(hr) && (m_iCurrPos < m_cbData))
  382. {
  383. if (cb >= cbBuf)
  384. {
  385. Assert(cb < cbBuf);
  386. hr = E_INVALIDARG;
  387. }
  388. else
  389. {
  390. // Get the string.
  391. CopyMemory(pbBuf, m_pbData + m_iCurrPos, cb);
  392. m_iCurrPos += cb;
  393. }
  394. }
  395. return hr;
  396. }
  397. /*!-------------------------------------------------------------------------
  398. CLdapBer::HrGetEnumValue
  399. This routine gets an enumerated value from the current BER entry. If
  400. the current BER entry isn't an enumerated type, then E_INVALIDARG is
  401. returned.
  402. ------------------------------------------------------------------------*/
  403. HRESULT CLdapBer::HrGetEnumValue(LONG *pi)
  404. {
  405. HRESULT hr;
  406. ULONG cb;
  407. ULONG cbLength;
  408. ULONG ul;
  409. ul = (ULONG)m_pbData[m_iCurrPos++]; // TAG
  410. if (ul != BER_ENUMERATED)
  411. {
  412. Assert(ul == BER_ENUMERATED);
  413. return E_INVALIDARG;
  414. }
  415. hr = HrGetLength(&cb);
  416. if (SUCCEEDED(hr) && (m_iCurrPos < m_cbData))
  417. {
  418. GetInt(m_pbData + m_iCurrPos, cb, pi);
  419. m_iCurrPos += cb;
  420. }
  421. return hr;
  422. }
  423. /*!-------------------------------------------------------------------------
  424. CLdapBer::HrGetStringLength
  425. This routine gets the length of the current BER entry, which is
  426. assumed to be a string. If the current BER entry's tag doesn't
  427. match ulTag, E_INVALIDARG is returned
  428. ------------------------------------------------------------------------*/
  429. HRESULT
  430. CLdapBer::HrGetStringLength(int *pcbValue, ULONG ulTag)
  431. {
  432. ULONG ul;
  433. ULONG cbLength;
  434. int iCurrPosSave = m_iCurrPos;
  435. HRESULT hr;
  436. ul = (ULONG)m_pbData[m_iCurrPos++]; // TAG
  437. if (ul != ulTag)
  438. {
  439. Assert(ul == ulTag);
  440. return E_INVALIDARG;
  441. }
  442. hr = HrGetLength((ULONG *)pcbValue);
  443. m_iCurrPos = iCurrPosSave;
  444. return hr;
  445. }
  446. /*!-------------------------------------------------------------------------
  447. CLdapBer::HrAddValue
  448. This routine puts an integer value in the BER buffer.
  449. ------------------------------------------------------------------------*/
  450. HRESULT CLdapBer::HrAddValue(LONG i, ULONG ulTag/*=BER_INTEGER*/)
  451. {
  452. HRESULT hr;
  453. LONG iValue;
  454. ULONG cbInt;
  455. DWORD dwMask = 0xff000000;
  456. DWORD dwHiBitMask = 0x80000000;
  457. if (i == 0)
  458. {
  459. cbInt = 1;
  460. }
  461. else
  462. {
  463. cbInt = sizeof(LONG);
  464. while (dwMask && !(i & dwMask))
  465. {
  466. dwHiBitMask >>= 8;
  467. dwMask >>= 8;
  468. cbInt--;
  469. }
  470. if (!(i & 0x80000000))
  471. {
  472. // It was a positive number so make sure we allow for upper most bit being set.
  473. // Make sure we send an extra byte since it's not a negative #.
  474. if (i & dwHiBitMask)
  475. cbInt++;
  476. }
  477. }
  478. hr = HrEnsureBuffer(1 + 3 + cbInt); // 1 for tag, 3 for length
  479. if (FAILED(hr))
  480. return hr;
  481. m_pbData[m_iCurrPos++] = (BYTE)ulTag;
  482. hr = HrSetLength(cbInt);
  483. if (SUCCEEDED(hr))
  484. {
  485. AddInt(m_pbData + m_iCurrPos, cbInt, i);
  486. m_iCurrPos += cbInt;
  487. m_cbData = m_iCurrPos;
  488. }
  489. return hr;
  490. }
  491. /*!-------------------------------------------------------------------------
  492. CLdapBer::HrAddValue
  493. Puts a string into the BER buffer.
  494. ------------------------------------------------------------------------*/
  495. HRESULT CLdapBer::HrAddValue(const TCHAR *szValue, ULONG ulTag)
  496. {
  497. HRESULT hr;
  498. ULONG cbValue = strlen(szValue);
  499. hr = HrEnsureBuffer(1 + 3 + cbValue); // 1 for tag, 3 for len
  500. if (FAILED(hr))
  501. return hr;
  502. m_pbData[m_iCurrPos++] = (BYTE)ulTag;
  503. hr = HrSetLength(cbValue);
  504. if (SUCCEEDED(hr))
  505. {
  506. CopyMemory(m_pbData + m_iCurrPos, szValue, cbValue);
  507. m_iCurrPos += cbValue;
  508. m_cbData = m_iCurrPos;
  509. }
  510. return hr;
  511. }
  512. /*!-------------------------------------------------------------------------
  513. CLdapBer::HrAddBinaryValue
  514. Puts a binary value into the BER buffer.
  515. ------------------------------------------------------------------------*/
  516. HRESULT CLdapBer::HrAddBinaryValue(BYTE *pbValue, ULONG cbValue, ULONG ulTag)
  517. {
  518. HRESULT hr;
  519. hr = HrEnsureBuffer(1 + 3 + cbValue); // 1 for tag, 3 for len
  520. if (FAILED(hr))
  521. return hr;
  522. m_pbData[m_iCurrPos++] = (BYTE)ulTag;
  523. hr = HrSetLength(cbValue);
  524. if (SUCCEEDED(hr))
  525. {
  526. CopyMemory(m_pbData + m_iCurrPos, pbValue, cbValue);
  527. m_iCurrPos += cbValue;
  528. m_cbData = m_iCurrPos;
  529. }
  530. return hr;
  531. }
  532. /*!-------------------------------------------------------------------------
  533. CLdapBer::HrSetLength
  534. Sets the length of cb to the current position in the BER buffer.
  535. ------------------------------------------------------------------------*/
  536. HRESULT CLdapBer::HrSetLength(ULONG cb, ULONG cbLength/*=0xffffffff*/)
  537. {
  538. // Short or long version of length ?
  539. if (((cb <= 0x7f) && (cbLength == 0xffffffff)) || (cbLength == 1))
  540. {
  541. m_pbData[m_iCurrPos++] = (BYTE)cb;
  542. }
  543. else if (((cb <= 0x7fff) && (cbLength == 0xffffffff)) || (cbLength == 3))
  544. {
  545. // Two byte length
  546. m_pbData[m_iCurrPos++] = 0x82;
  547. m_pbData[m_iCurrPos++] = (BYTE)((cb>>8) & 0x00ff);
  548. m_pbData[m_iCurrPos++] = (BYTE)(cb & 0x00ff);
  549. }
  550. else if (((cb < 0x7fffffff) && (cbLength == 0xffffffff)) || (cbLength == 5))
  551. {
  552. // Don't bother with 3 byte length, go directly to 4 byte.
  553. m_pbData[m_iCurrPos++] = 0x84;
  554. m_pbData[m_iCurrPos++] = (BYTE)((cb>>24) & 0x00ff);
  555. m_pbData[m_iCurrPos++] = (BYTE)((cb>>16) & 0x00ff);
  556. m_pbData[m_iCurrPos++] = (BYTE)((cb>>8) & 0x00ff);
  557. m_pbData[m_iCurrPos++] = (BYTE)(cb & 0x00ff);
  558. }
  559. else
  560. {
  561. Assert(cb < 0x7fffffff);
  562. return E_INVALIDARG;
  563. }
  564. return NOERROR;
  565. }
  566. /*!-------------------------------------------------------------------------
  567. CLdapBer::GetCbLength
  568. Gets the # of bytes required for the length field in the current
  569. position in the BER buffer.
  570. ------------------------------------------------------------------------*/
  571. void CLdapBer::GetCbLength(BYTE *pbData, ULONG *pcbLength)
  572. {
  573. ULONG cbLength;
  574. ULONG i, cb;
  575. // Short or long version of the length ?
  576. if (*pbData & 0x80)
  577. {
  578. *pcbLength = 1;
  579. *pcbLength += *pbData & 0x7f;
  580. }
  581. else
  582. {
  583. // Short version of the length.
  584. *pcbLength = 1;
  585. }
  586. }
  587. /*!-------------------------------------------------------------------------
  588. CLdapBer::HrGetLength
  589. Gets the length from the current position in the BER buffer. Only
  590. definite lengths are supported.
  591. ------------------------------------------------------------------------*/
  592. HRESULT CLdapBer::HrGetLength(ULONG *pcb)
  593. {
  594. return HrGetLength(m_pbData, pcb, &m_iCurrPos);
  595. }
  596. /*!-------------------------------------------------------------------------
  597. CLdapBer::HrPeekLength
  598. Gets the length from the current position in the BER buffer without
  599. incrementing the current pointer.
  600. ------------------------------------------------------------------------*/
  601. HRESULT CLdapBer::HrPeekLength(ULONG *pcb)
  602. {
  603. ULONG iPos = m_iCurrPos;
  604. return HrGetLength(m_pbData, pcb, &iPos);
  605. }
  606. /*!-------------------------------------------------------------------------
  607. CLdapBer::HrGetLength
  608. This is a private function that gets the length given a current
  609. input position.
  610. ------------------------------------------------------------------------*/
  611. HRESULT CLdapBer::HrGetLength(BYTE *pbData, ULONG *pcb, ULONG *piPos)
  612. {
  613. ULONG cbLength;
  614. ULONG i, cb, iPos;
  615. iPos = *piPos;
  616. GetCbLength(pbData + iPos, &cbLength);
  617. // Short or long version of the length ?
  618. if (cbLength == 1)
  619. {
  620. cb = pbData[iPos++] & 0x7f;
  621. }
  622. else if (cbLength <= 5)
  623. {
  624. // Account for the overhead byte.cbLength field.
  625. cbLength--;
  626. iPos++;
  627. cb = pbData[iPos++];
  628. for (i=1; i < cbLength; i++)
  629. {
  630. cb <<= 8;
  631. cb |= pbData[iPos++];
  632. }
  633. }
  634. else
  635. {
  636. // We don't support lengths > 2^32.
  637. Assert(cbLength <= 5);
  638. return E_INVALIDARG;
  639. }
  640. *piPos = iPos;
  641. *pcb = cb;
  642. return NOERROR;
  643. }
  644. /*!-------------------------------------------------------------------------
  645. CLdapBer::GetInt
  646. Gets an integer from a BER buffer.
  647. ------------------------------------------------------------------------*/
  648. void CLdapBer::GetInt(BYTE *pbData, ULONG cbValue, LONG *plValue)
  649. {
  650. ULONG ulVal=0, ulTmp=0;
  651. ULONG cbDiff;
  652. BOOL fSign = FALSE;
  653. // We assume the tag & length have already been taken off and we're
  654. // at the value part.
  655. cbDiff = sizeof(LONG) - cbValue;
  656. // See if we need to sign extend;
  657. if ((cbDiff > 0) && (*pbData & 0x80))
  658. fSign = TRUE;
  659. while (cbValue > 0)
  660. {
  661. ulVal <<= 8;
  662. ulVal |= (ULONG)*pbData++;
  663. cbValue--;
  664. }
  665. // Sign extend if necessary.
  666. if (fSign)
  667. {
  668. *plValue = 0x80000000;
  669. *plValue >>= cbDiff * 8;
  670. }
  671. else
  672. *plValue = (LONG) ulVal;
  673. }
  674. /*!-------------------------------------------------------------------------
  675. CLdapBer::AddInt
  676. Adds an integer to the input pbData buffer.
  677. ------------------------------------------------------------------------*/
  678. void CLdapBer::AddInt(BYTE *pbData, ULONG cbValue, LONG lValue)
  679. {
  680. ULONG i;
  681. for (i=cbValue; i > 0; i--)
  682. {
  683. *pbData++ = (BYTE)(lValue >> ((i - 1) * 8)) & 0xff;
  684. }
  685. }
  686. /*!-------------------------------------------------------------------------
  687. CLdapBer::HrEnsureBuffer
  688. Ensures that we've got room to put cbNeeded more bytes into the buffer.
  689. ------------------------------------------------------------------------*/
  690. HRESULT
  691. CLdapBer::HrEnsureBuffer(ULONG cbNeeded, BOOL fExact)
  692. {
  693. ULONG cbNew;
  694. BYTE *pbT;
  695. if (cbNeeded + m_cbData < m_cbDataMax)
  696. return NOERROR;
  697. Assert(m_fLocalCopy == TRUE);
  698. if (!m_fLocalCopy)
  699. return E_INVALIDARG;
  700. if (fExact)
  701. {
  702. cbNew = cbNeeded + m_cbData;
  703. }
  704. else
  705. {
  706. if (cbNeeded > CB_DATA_GROW)
  707. cbNew = m_cbDataMax + cbNeeded;
  708. else
  709. cbNew = m_cbDataMax + CB_DATA_GROW;
  710. }
  711. pbT = (BYTE *)ALLOCATE(cbNew);
  712. if (!pbT)
  713. return E_OUTOFMEMORY;
  714. if (m_pbData)
  715. {
  716. CopyMemory(pbT, m_pbData, m_cbData);
  717. FREE(m_pbData);
  718. }
  719. m_pbData = pbT;
  720. m_cbDataMax = cbNew;
  721. return NOERROR;
  722. }