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.

849 lines
20 KiB

  1. #include "stdafx.h"
  2. #include "dynarray.h"
  3. #include "q931msg.h"
  4. #include "h323asn1.h"
  5. struct Q931_ENCODE_CONTEXT
  6. {
  7. LPBYTE Pos; // next storage position, MAY EXCEED End!
  8. LPBYTE End; // end of storage buffer
  9. // if returns FALSE, then buffer is in overflow condition
  10. BOOL StoreData (
  11. IN LPBYTE Data,
  12. IN DWORD Length);
  13. BOOL HasOverflowed (void) { return Pos > End; }
  14. // if returns FALSE, then buffer is in overflow condition, or would be
  15. BOOL AllocData (
  16. IN DWORD Length,
  17. OUT LPBYTE * ReturnData);
  18. };
  19. BOOL Q931_ENCODE_CONTEXT::StoreData (
  20. IN LPBYTE Data,
  21. IN DWORD Length)
  22. {
  23. if (Pos + Length > End) {
  24. Pos += Length;
  25. return FALSE;
  26. }
  27. memcpy (Pos, Data, Length);
  28. Pos += Length;
  29. return TRUE;
  30. }
  31. BOOL Q931_ENCODE_CONTEXT::AllocData (
  32. IN DWORD Length,
  33. OUT LPBYTE * ReturnData)
  34. {
  35. if (Pos + Length > End) {
  36. Pos += Length;
  37. *ReturnData = NULL;
  38. return FALSE;
  39. }
  40. else {
  41. *ReturnData = Pos;
  42. Pos += Length;
  43. return TRUE;
  44. }
  45. }
  46. #if DBG
  47. void Q931TestDecoder (
  48. IN LPBYTE PduData,
  49. IN DWORD PduLength)
  50. {
  51. Q931_MESSAGE Message;
  52. HRESULT Result;
  53. Q931_MESSAGE NewMessage;
  54. BYTE NewData [0x400];
  55. DWORD NewLength;
  56. Debug (_T("Q931TestDecoder --------------------------------------------------------------------\n"));
  57. DebugF (_T("- processing Q.931 PDU, length %d, contents:\n"), PduLength);
  58. DumpMemory (PduData, PduLength);
  59. Result = Message.AttachDecodePdu (PduData, PduLength, FALSE);
  60. if (Result != S_OK) {
  61. DebugError (Result, _T("- failed to decode Q.931 PDU\n"));
  62. return;
  63. }
  64. Debug (_T("- successfully decoded Q.931 PDU\n"));
  65. // now, try to re-encode the same PDU
  66. if (Message.MessageType == Q931_MESSAGE_TYPE_SETUP) {
  67. // there is an issue with decoding and re-encoding ASN.1 UUIE for Setup from TAPI
  68. // long, boring story
  69. Debug (_T("- it's a Setup PDU, will not attempt to re-encode (due to ASN.1 compatability issue)\n"));
  70. }
  71. else {
  72. Debug (_T("- will now attempt to re-encode\n"));
  73. NewLength = 0x400;
  74. Result = Message.EncodePdu (NewData, &NewLength);
  75. if (Result == S_OK) {
  76. DebugF (_T("- successfully re-encoded copy of Q.931 PDU, length %d, contents:\n"), NewLength);
  77. if (PduLength != NewLength) {
  78. DebugF (_T("- *** warning: original pdu length (%d) is different from re-encoded pdu length (%d), re-encoded contents:\n"),
  79. PduLength, NewLength);
  80. DumpMemory (NewData, NewLength);
  81. }
  82. else {
  83. if (memcmp (PduData, NewData, NewLength) != 0) {
  84. DebugF (_T("- *** warning: original pdu contents differ from re-encoded pdu contents, which follow:\n"));
  85. DumpMemory (NewData, NewLength);
  86. }
  87. else {
  88. DebugF (_T("- re-encoded pdu is identical to original pdu -- success!\n"));
  89. }
  90. }
  91. Debug (_T("- will now attempt to decode re-encoded PDU\n"));
  92. Result = NewMessage.AttachDecodePdu (NewData, NewLength, FALSE);
  93. if (Result == S_OK) {
  94. Debug (_T("- successfully decoded copy of Q.931 PDU\n"));
  95. }
  96. else {
  97. DebugError (Result, _T("- failed to decode copy of Q.931 PDU\n"));
  98. }
  99. }
  100. else {
  101. DebugError (Result, _T("- failed to re-encode Q.931 PDU\n"));
  102. }
  103. }
  104. Message.Detach();
  105. NewMessage.Detach();
  106. Debug (_T("\n"));
  107. }
  108. #endif
  109. // Q931_MESSAGE -----------------------------------------------------------------------------
  110. Q931_MESSAGE::Q931_MESSAGE (void)
  111. {
  112. Buffer = NULL;
  113. BufferLength = 0;
  114. }
  115. Q931_MESSAGE::~Q931_MESSAGE (void)
  116. {
  117. Detach();
  118. assert (!InfoElementArray.m_Length);
  119. assert (!Buffer);
  120. }
  121. void Q931_MESSAGE::Detach (void)
  122. {
  123. FreeInfoElementArray();
  124. if (Buffer) {
  125. if (BufferIsOwner) {
  126. LocalFree (Buffer);
  127. }
  128. Buffer = NULL;
  129. BufferLength = 0;
  130. BufferIsOwner = FALSE;
  131. }
  132. }
  133. HRESULT Q931_MESSAGE::Detach (
  134. OUT LPBYTE * ReturnBuffer,
  135. OUT DWORD * ReturnBufferLength)
  136. {
  137. HRESULT Result;
  138. assert (ReturnBuffer);
  139. assert (ReturnBufferLength);
  140. if (Buffer) {
  141. *ReturnBuffer = Buffer;
  142. *ReturnBufferLength = BufferLength;
  143. Result = S_OK;
  144. }
  145. else {
  146. Result = S_FALSE;
  147. }
  148. Detach();
  149. return Result;
  150. }
  151. void Q931_MESSAGE::FreeInfoElementArray (void)
  152. {
  153. Q931_IE * Pos;
  154. Q931_IE * End;
  155. InfoElementArray.GetExtents (&Pos, &End);
  156. for (; Pos < End; Pos++) {
  157. FreeInfoElement (Pos);
  158. }
  159. InfoElementArray.Clear();
  160. }
  161. void Q931_MESSAGE::FreeInfoElement (Q931_IE * InfoElement)
  162. {
  163. assert (InfoElement);
  164. switch (InfoElement -> Identifier) {
  165. case Q931_IE_USER_TO_USER:
  166. assert (InfoElement -> Data.UserToUser.PduStructure);
  167. if (InfoElement -> Data.UserToUser.IsOwner) {
  168. H225FreePdu_H323_UserInformation (
  169. InfoElement -> Data.UserToUser.PduStructure);
  170. }
  171. break;
  172. }
  173. }
  174. HRESULT Q931_MESSAGE::DecodeInfoElement (
  175. IN OUT LPBYTE * ArgPos,
  176. IN LPBYTE End,
  177. OUT Q931_IE * ReturnInfoElement)
  178. {
  179. LPBYTE Pos;
  180. BYTE Identifier;
  181. DWORD LengthLength; // length of the IE length element, in bytes!
  182. LPBYTE VariableData; // payload of variable-length data
  183. DWORD VariableDataLength;
  184. BYTE FixedData; // payload of fixed-length data
  185. HRESULT Result;
  186. assert (ArgPos);
  187. assert (End);
  188. Pos = *ArgPos;
  189. if (Pos >= End) {
  190. Debug (_T("Q931_MESSAGE::DecodeInfoElement: should never have been called\n"));
  191. return E_INVALIDARG;
  192. }
  193. Identifier = *Pos;
  194. Pos++;
  195. // is it a single-byte IE?
  196. // if so, then bit 7 of the first byte = 1
  197. if (Identifier & 0x80) {
  198. // there are two types of single-byte IEs
  199. // Type 1 has a four-bit identifier and a four-bit value
  200. // Type 2 has only an identifier, and no value
  201. switch (Identifier & 0xF0) {
  202. case Q931_IE_MORE_DATA:
  203. case Q931_IE_SENDING_COMPLETE:
  204. // these IEs have an identifier, but no value
  205. ReturnInfoElement -> Identifier = (Q931_IE_IDENTIFIER) Identifier;
  206. DebugF (_T("Q931_MESSAGE::DecodeInfoElement: fixed-length IE, id %02XH, no value\n"),
  207. Identifier);
  208. break;
  209. default:
  210. // the other single-byte IEs have a value in the lower four bits
  211. ReturnInfoElement -> Identifier = (Q931_IE_IDENTIFIER) (Identifier & 0xF0);
  212. ReturnInfoElement -> Data.UnknownFixed.Value = Identifier & 0x0F;
  213. DebugF (_T("Q931_MESSAGE::DecodeInfoElement: fixed-length IE, id %02XH value %01XH\n"),
  214. ReturnInfoElement -> Identifier,
  215. ReturnInfoElement -> Data.UnknownFixed.Value);
  216. break;
  217. }
  218. // we don't currently parse any fixed-length IEs
  219. Result = S_OK;
  220. }
  221. else {
  222. // the next byte indicates the length of the info element
  223. // unfortunately, the number of octets that make up the length
  224. // depends on the identifier.
  225. // -XXX- is this because I don't understand the octet extension mechanism?
  226. ReturnInfoElement -> Identifier = (Q931_IE_IDENTIFIER) Identifier;
  227. switch (Identifier) {
  228. case Q931_IE_USER_TO_USER:
  229. LengthLength = 2;
  230. break;
  231. default:
  232. LengthLength = 1;
  233. break;
  234. }
  235. if (Pos + LengthLength > End) {
  236. Debug (_T("Q931_MESSAGE::DecodeInfoElement: insufficient data for header of variable-length IE\n"));
  237. return E_INVALIDARG;
  238. }
  239. if (LengthLength == 1) {
  240. VariableDataLength = *Pos;
  241. }
  242. else {
  243. VariableDataLength = Pos [1] + (((WORD) Pos [0]) << 8);
  244. }
  245. Pos += LengthLength;
  246. if (Pos + VariableDataLength > End) {
  247. Debug (_T("Q931_MESSAGE::DecodeInfoElement: insufficient data for body of variable-length IE\n"));
  248. return E_INVALIDARG;
  249. }
  250. VariableData = (LPBYTE) Pos;
  251. Pos += VariableDataLength;
  252. // DebugF (_T("Q931_MESSAGE::DecodeInfoElement: variable-length IE, id %02XH length %d\n"),
  253. // Identifier, VariableDataLength);
  254. ReturnInfoElement -> Data.UnknownVariable.Data = VariableData;
  255. ReturnInfoElement -> Data.UnknownVariable.Length = VariableDataLength;
  256. Result = ParseIE (ReturnInfoElement);
  257. if (Result != S_OK) {
  258. DebugError (Result, _T("Q931_MESSAGE::DecodeInfoElement: IE was located, but failed to parse\n"));
  259. }
  260. }
  261. *ArgPos = Pos;
  262. return Result;
  263. }
  264. HRESULT Q931_MESSAGE::AppendInfoElement (
  265. IN Q931_IE * InfoElement)
  266. {
  267. Q931_IE * ArrayEntry;
  268. ArrayEntry = InfoElementArray.AllocAtEnd();
  269. if (ArrayEntry) {
  270. *ArrayEntry = *InfoElement;
  271. return S_OK;
  272. }
  273. else {
  274. Debug (_T("Q931_MESSAGE::AppendInfoElement: allocation failure\n"));
  275. return E_OUTOFMEMORY;
  276. }
  277. }
  278. HRESULT Q931_MESSAGE::ParseIE_UUIE (
  279. IN Q931_IE * InfoElement)
  280. {
  281. LPBYTE Data;
  282. DWORD Length;
  283. DWORD Status;
  284. // be careful to copy out all parameters from one branch of the union
  285. // before you start stomping on another branch
  286. Data = InfoElement -> Data.UnknownVariable.Data;
  287. Length = InfoElement -> Data.UnknownVariable.Length;
  288. if (Length < 1) {
  289. Debug (_T("Q931_MESSAGE::ParseIE_UUIE: IE payload is too short to contain UUIE\n"));
  290. return E_INVALIDARG;
  291. }
  292. InfoElement -> Data.UserToUser.Type = (Q931_UUIE_TYPE) *Data++;
  293. Length--;
  294. InfoElement -> Data.UserToUser.PduStructure = NULL;
  295. Status = H225DecodePdu_H323_UserInformation (Data, Length,
  296. &InfoElement -> Data.UserToUser.PduStructure);
  297. if (Status != ERROR_SUCCESS) {
  298. if (InfoElement -> Data.UserToUser.PduStructure) {
  299. // return value was a warning, not error
  300. H225FreePdu_H323_UserInformation (InfoElement -> Data.UserToUser.PduStructure);
  301. InfoElement -> Data.UserToUser.PduStructure = NULL;
  302. }
  303. InfoElement -> Data.UserToUser.PduStructure = NULL;
  304. DebugError (Status, _T("Q931_MESSAGE::ParseIE_UUIE: failed to decode UUIE / ASN.1\n"));
  305. return E_FAIL;
  306. }
  307. InfoElement -> Data.UserToUser.IsOwner = TRUE;
  308. // Debug (_T("Q931_MESSAGE::ParseIE_UUIE: successfully decoded UUIE\n"));
  309. return S_OK;
  310. }
  311. HRESULT Q931_MESSAGE::ParseIE (
  312. IN Q931_IE * InfoElement)
  313. {
  314. assert (InfoElement);
  315. switch (InfoElement -> Identifier) {
  316. case Q931_IE_USER_TO_USER:
  317. return ParseIE_UUIE (InfoElement);
  318. break;
  319. case Q931_IE_CAUSE:
  320. // Debug (_T("Q931_MESSAGE::ParseInfoElement: Q931_IE_CAUSE\n"));
  321. break;
  322. case Q931_IE_DISPLAY:
  323. // Debug (_T("Q931_MESSAGE::ParseInfoElement: Q931_IE_DISPAY\n"));
  324. break;
  325. case Q931_IE_BEARER_CAPABILITY:
  326. // Debug (_T("Q931_MESSAGE::ParseInfoElement: Q931_IE_BEARER_CAPABILITY\n"));
  327. break;
  328. default:
  329. DebugF (_T("Q931_MESSAGE::ParseInfoElement: unknown IE identifier (%02XH), no interpretation will be imposed\n"),
  330. InfoElement -> Identifier);
  331. break;
  332. }
  333. return S_OK;
  334. }
  335. HRESULT Q931_MESSAGE::AttachDecodePdu (
  336. IN LPBYTE Data,
  337. IN DWORD Length,
  338. IN BOOL IsDataOwner)
  339. {
  340. LPBYTE Pos;
  341. LPBYTE End;
  342. HRESULT Result;
  343. Q931_IE * ArrayEntry;
  344. assert (Data);
  345. Detach();
  346. if (Length < 5) {
  347. DebugF (_T("Q931_MESSAGE::Decode: header is too short (%d)\n"), Length);
  348. return E_INVALIDARG;
  349. }
  350. // octet 0 is the Protocol Discriminator
  351. if (Data [0] != Q931_PROTOCOL_DISCRIMINATOR) {
  352. DebugF (_T("Q931_MESSAGE::Decode: the pdu is not a Q.931 pdu, protocol discriminator = %02XH\n"),
  353. Data [0]);
  354. return E_INVALIDARG;
  355. }
  356. // octet 1: bits 0-3 contain the length, in octets of the Call Reference Value
  357. // octet 1: bits 4-7 should be zero
  358. if (Data [1] & 0xF0) {
  359. DebugF (_T("Q931_MESSAGE::Decode: the pdu has non-zero bits in octet 1: %02XH\n"),
  360. Data [1]);
  361. }
  362. // according to H.225, the Call Reference Value must be two octets in length
  363. if ((Data [1] & 0x0F) != 2) {
  364. DebugF (_T("Q931_MESSAGE::Decode: the call reference value size is invalid (%d), should be 2\n"),
  365. Data [1] & 0x0F);
  366. return E_INVALIDARG;
  367. }
  368. // since the Call Reference Value size is 2 octets, octets 2 and 3 are the CRV
  369. // octets are in network (big-endian) order.
  370. CallReferenceValue = (((WORD) Data [2]) << 8) | Data [3];
  371. // DebugF (_T("Q931_MESSAGE::Decode: crv %04XH\n"), CallReferenceValue);
  372. // Message Type is at octet offset 4
  373. if (Data [4] & 0x80) {
  374. DebugF (_T("Q931_MESSAGE::Decode: message type is invalid (%02XH)\n"), Data [4]);
  375. return E_INVALIDARG;
  376. }
  377. MessageType = (Q931_MESSAGE_TYPE) Data [4];
  378. // enumerate the Information Elements and extract the ones that we will use
  379. Pos = Data + 5;
  380. End = Data + Length;
  381. Result = S_OK;
  382. while (Pos < End) {
  383. ArrayEntry = InfoElementArray.AllocAtEnd();
  384. if (!ArrayEntry) {
  385. Result = E_OUTOFMEMORY;
  386. Debug (_T("Q931_MESSAGE::Decode: allocation failure\n"));
  387. break;
  388. }
  389. Result = DecodeInfoElement (&Pos, End, ArrayEntry);
  390. if (Result != S_OK) {
  391. DebugError (Result, _T("Q931_MESSAGE::Decode: failed to decode IE, packet may be corrupt, terminating (but not failing) decode\n"));
  392. Result = S_OK;
  393. InfoElementArray.DeleteEntry (ArrayEntry);
  394. break;
  395. }
  396. }
  397. if (Result == S_OK) {
  398. assert (!Buffer);
  399. Buffer = Data;
  400. BufferLength = Length;
  401. BufferIsOwner = IsDataOwner;
  402. }
  403. else {
  404. Detach();
  405. }
  406. return ERROR_SUCCESS;
  407. }
  408. HRESULT Q931_MESSAGE::EncodePdu (
  409. IN OUT LPBYTE Data,
  410. IN OUT LPDWORD Length)
  411. {
  412. Q931_ENCODE_CONTEXT Context;
  413. Q931_IE * IePos;
  414. Q931_IE * IeEnd;
  415. HRESULT Result;
  416. DWORD EncodeLength;
  417. assert (Data);
  418. assert (Length);
  419. Context.Pos = Data;
  420. Context.End = Data + *Length;
  421. SortInfoElementArray();
  422. Result = EncodeHeader (&Context);
  423. if (Result != S_OK)
  424. return Result;
  425. // walk IE array
  426. InfoElementArray.GetExtents (&IePos, &IeEnd);
  427. for (; IePos < IeEnd; IePos++) {
  428. Result = EncodeInfoElement (&Context, IePos);
  429. if (Result != S_OK) {
  430. return Result;
  431. }
  432. }
  433. EncodeLength = (DWORD)(Context.Pos - Data);
  434. if (Context.HasOverflowed()) {
  435. Result = HRESULT_FROM_WIN32 (ERROR_MORE_DATA);
  436. }
  437. else {
  438. Result = S_OK;
  439. }
  440. *Length = EncodeLength;
  441. return Result;
  442. }
  443. HRESULT Q931_MESSAGE::EncodeHeader (
  444. IN Q931_ENCODE_CONTEXT * Context)
  445. {
  446. BYTE Header [5];
  447. Header [0] = Q931_PROTOCOL_DISCRIMINATOR;
  448. Header [1] = 2;
  449. Header [2] = (CallReferenceValue >> 8) & 0xFF;
  450. Header [3] = CallReferenceValue & 0xFF;
  451. Header [4] = MessageType;
  452. Context -> StoreData (Header, 5);
  453. return S_OK;
  454. }
  455. HRESULT Q931_MESSAGE::EncodeInfoElement (
  456. IN Q931_ENCODE_CONTEXT * Context,
  457. IN Q931_IE * InfoElement)
  458. {
  459. BYTE Header [0x10];
  460. WORD Length;
  461. DWORD LengthLength; // length of Length, in bytes
  462. LPBYTE LengthInsertionPoint;
  463. LPBYTE IeContents;
  464. DWORD IeContentsLength;
  465. DWORD ShiftCount;
  466. HRESULT Result;
  467. if (InfoElement -> Identifier & 0x80) {
  468. // single-byte IE
  469. switch (InfoElement -> Identifier & 0xF0) {
  470. case Q931_IE_MORE_DATA:
  471. case Q931_IE_SENDING_COMPLETE:
  472. // these IEs have an identifier, but no value
  473. Header [0] = (BYTE) InfoElement -> Identifier;
  474. break;
  475. default:
  476. // these IEs have an identifier and a value, combined in a single byte
  477. Header [0] = (((BYTE) InfoElement -> Identifier) & 0xF0)
  478. | (InfoElement -> Data.UnknownFixed.Value & 0x0F);
  479. break;
  480. }
  481. Context -> StoreData (Header, 1);
  482. Result = S_OK;
  483. }
  484. else {
  485. // variable-length IE
  486. Header [0] = (BYTE) InfoElement -> Identifier;
  487. Context -> StoreData (Header, 1);
  488. // allocate data for the insertion point
  489. Context -> AllocData (2, &LengthInsertionPoint);
  490. // record the current buffer position, for use below in storing the content length
  491. IeContents = Context -> Pos;
  492. switch (InfoElement -> Identifier) {
  493. case Q931_IE_USER_TO_USER:
  494. Result = EncodeIE_UUIE (Context, InfoElement);
  495. break;
  496. default:
  497. Context -> StoreData (
  498. InfoElement -> Data.UnknownVariable.Data,
  499. InfoElement -> Data.UnknownVariable.Length);
  500. if (InfoElement -> Data.UnknownVariable.Length >= 0x10000) {
  501. DebugF (_T("Q931_MESSAGE::EncodeInfoElement: payload is waaaaay too big (%d %08XH)\n"),
  502. InfoElement -> Data.UnknownVariable.Length,
  503. InfoElement -> Data.UnknownVariable.Length);
  504. Result = E_INVALIDARG;
  505. }
  506. else {
  507. Result = S_OK;
  508. }
  509. break;
  510. }
  511. if (Result == S_OK) {
  512. IeContentsLength = (DWORD)(Context -> Pos - IeContents);
  513. // this is such a hack
  514. // with little or no justification for when LengthLength = 1 and when LengthLength = 2
  515. // the octet group extension mechanism is poorly defined in Q.931
  516. if (InfoElement -> Identifier == Q931_IE_USER_TO_USER)
  517. LengthLength = 2;
  518. else
  519. LengthLength = 1;
  520. // if the storage context has not overflowed,
  521. // and if it is necessary to resize the Length parameter (we guessed pessimistically
  522. // that it would be 2), then move the buffer down one byte
  523. ShiftCount = 2 - LengthLength;
  524. if (ShiftCount > 0) {
  525. if (!Context -> HasOverflowed()) {
  526. memmove (
  527. LengthInsertionPoint + LengthLength, // destination, where IE contents should be
  528. IeContents, // source, where IE contents were actually stored
  529. IeContentsLength); // length of the contents
  530. }
  531. // pull back the storage context's position pointer
  532. Context -> Pos -= ShiftCount;
  533. }
  534. // now store the actual count
  535. if ( LengthInsertionPoint != NULL )
  536. {
  537. switch (LengthLength) {
  538. case 1:
  539. assert (IeContentsLength < 0x100);
  540. LengthInsertionPoint [0] = (BYTE) IeContentsLength;
  541. break;
  542. case 2:
  543. assert (IeContentsLength < 0x10000);
  544. LengthInsertionPoint [0] = (BYTE) (IeContentsLength >> 8);
  545. LengthInsertionPoint [1] = (BYTE) (IeContentsLength & 0xFF);
  546. break;
  547. default:
  548. assert (FALSE);
  549. }
  550. }
  551. }
  552. }
  553. return Result;
  554. }
  555. HRESULT Q931_MESSAGE::EncodeIE_UUIE (
  556. IN Q931_ENCODE_CONTEXT * Context,
  557. IN Q931_IE * InfoElement)
  558. {
  559. DWORD Status;
  560. LPBYTE Buffer;
  561. DWORD Length;
  562. BYTE ProtocolDiscriminator;
  563. assert (Context);
  564. assert (InfoElement);
  565. assert (InfoElement -> Data.UserToUser.PduStructure);
  566. // store the UUIE protocol discriminator
  567. ProtocolDiscriminator = InfoElement -> Data.UserToUser.Type;
  568. Context -> StoreData (&ProtocolDiscriminator, 1);
  569. Buffer = NULL;
  570. Length = 0;
  571. Status = H225EncodePdu_H323_UserInformation (
  572. InfoElement -> Data.UserToUser.PduStructure,
  573. &Buffer, &Length);
  574. if (Status == ERROR_SUCCESS) {
  575. Context -> StoreData (Buffer, Length);
  576. H225FreeBuffer (Buffer);
  577. return S_OK;
  578. }
  579. else {
  580. // Status is not a real Win32 error code
  581. // it is an ASN.1 enum (
  582. #if DBG
  583. // we pull this in so source debuggers can show actual symbolic enum name
  584. tagASN1error_e AsnError = (tagASN1error_e) Status;
  585. DebugF (_T("Q931_MESSAGE::EncodeIE_UUIE: failed to encode ASN.1 structure (%d)\n"),
  586. AsnError);
  587. #endif
  588. // -XXX- one day, i'm going to convince Lon to use real Win32 error codes for ASN.1 return values
  589. // -XXX- on that day, the return value should reflect the actual ASN.1 error code
  590. return DIGSIG_E_ENCODE;
  591. }
  592. }
  593. void Q931_MESSAGE::SortInfoElementArray (void)
  594. {
  595. InfoElementArray.QuickSort (CompareInfoElement);
  596. }
  597. // static
  598. INT __cdecl Q931_MESSAGE::CompareInfoElement (
  599. const Q931_IE * ComparandA,
  600. const Q931_IE * ComparandB)
  601. {
  602. if (ComparandA -> Identifier < ComparandB -> Identifier) return -1;
  603. if (ComparandA -> Identifier > ComparandB -> Identifier) return 1;
  604. return 0;
  605. }
  606. HRESULT Q931_MESSAGE::FindInfoElement (
  607. IN Q931_IE_IDENTIFIER Identifier,
  608. OUT Q931_IE ** ReturnInfoElement)
  609. {
  610. DWORD Index;
  611. assert (ReturnInfoElement);
  612. if (InfoElementArray.BinarySearch ((SEARCH_FUNC_Q931_IE)InfoElementSearchFunc, &Identifier, &Index)) {
  613. *ReturnInfoElement = InfoElementArray.m_Array + Index;
  614. return S_OK;
  615. }
  616. else {
  617. *ReturnInfoElement = NULL;
  618. return E_FAIL;
  619. }
  620. }
  621. // static
  622. INT Q931_MESSAGE::InfoElementSearchFunc (
  623. IN const Q931_IE_IDENTIFIER * SearchKey,
  624. IN const Q931_IE * Comparand)
  625. {
  626. Q931_IE_IDENTIFIER Identifier;
  627. assert (SearchKey);
  628. assert (Comparand);
  629. Identifier = * (Q931_IE_IDENTIFIER *) SearchKey;
  630. if (Identifier < Comparand -> Identifier) return -1;
  631. if (Identifier > Comparand -> Identifier) return 1;
  632. return 0;
  633. }