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.

646 lines
20 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. persist.c
  5. Abstract:
  6. General structure persistence functions.
  7. Author:
  8. Aghajanyan Souren 27-Mar-2001
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "migutilp.h"
  13. #include "persist.h"
  14. BOOL
  15. MayExtraMemRequire (
  16. IN PFIELD_DESCRIPTION FieldsDescription
  17. )
  18. {
  19. FIELD_DESCRIPTION * FieldPtr;
  20. for(FieldPtr = FieldsDescription; FieldPtr->Offset != END_OF_STRUCT; FieldPtr++){
  21. if(!FieldPtr->FieldDescription && FieldPtr->ArraySizeFieldOffset && FieldPtr->byValue){
  22. return TRUE;
  23. }
  24. }
  25. return FALSE;
  26. }
  27. SIZE_T
  28. GetExtraMemRequirements(
  29. IN BYTE * StructurePtr,
  30. IN PFIELD_DESCRIPTION FieldsDescription
  31. )
  32. /*
  33. This function provide additional memory requirements,
  34. only in case when structure has variable size.
  35. And have to be declared by PERSIST_FIELD_BY_VALUE_NESTED_TYPE_CYCLE
  36. For example:
  37. struct VariableSizeStruct{
  38. ......
  39. UINT uiNumberOfItem;
  40. ITEM items[1];
  41. };
  42. PERSIST_FIELD_BY_VALUE_NESTED_TYPE_CYCLE(VariableSizeStruct, ITEM, items, uiNumberOfItem)
  43. */
  44. {
  45. UINT Len;
  46. FIELD_DESCRIPTION * FieldPtr;
  47. SIZE_T ExtraBytes = 0;
  48. UINT uiItemCount;
  49. MYASSERT(StructurePtr);
  50. for(FieldPtr = FieldsDescription; FieldPtr->Offset != END_OF_STRUCT; FieldPtr++){
  51. if(!FieldPtr->FieldDescription &&
  52. FieldPtr->ArraySizeFieldOffset &&
  53. FieldPtr->byValue &&
  54. FieldPtr->Size){
  55. uiItemCount = *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, StructurePtr, FieldPtr->ArraySizeFieldOffset));
  56. ExtraBytes += uiItemCount? FieldPtr->Size * (uiItemCount - FieldPtr->InitialNumberOfItem): 0;
  57. }
  58. }
  59. return ExtraBytes;
  60. }
  61. BOOL
  62. SerializeStore(
  63. IN OUT BYTE * BufferMain,
  64. IN BYTE * StructurePtr,
  65. IN PFIELD_DESCRIPTION FieldsDescription,
  66. IN OUT SIZE_T * uiHowUsed
  67. )
  68. {
  69. UINT i;
  70. UINT iLen;
  71. SIZE_T Size = 0;
  72. BYTE * SubStruct;
  73. FIELD_DESCRIPTION * FieldPtr;
  74. if(!uiHowUsed){
  75. uiHowUsed = &Size;
  76. }
  77. MYASSERT(StructurePtr);
  78. for(FieldPtr = FieldsDescription; FieldPtr->Offset != END_OF_STRUCT; FieldPtr++){
  79. if(FieldPtr->FieldDescription)
  80. {
  81. iLen = FieldPtr->ArraySizeFieldOffset?
  82. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, StructurePtr, FieldPtr->ArraySizeFieldOffset)):
  83. 1;
  84. if(FieldPtr->byValue){
  85. SubStruct = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset);
  86. MYASSERT(SubStruct);
  87. }
  88. else{
  89. SubStruct = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset);
  90. if(BufferMain){
  91. *(BufferMain + *uiHowUsed) = (SubStruct && iLen);
  92. }
  93. ++*uiHowUsed;
  94. if(!SubStruct || !iLen){
  95. continue;
  96. }
  97. }
  98. for(i = 0; i < iLen;
  99. i++, SubStruct += FieldPtr->Size + GetExtraMemRequirements(SubStruct, FieldPtr->FieldDescription))
  100. {
  101. if(!SerializeStore(BufferMain,
  102. SubStruct,
  103. FieldPtr->FieldDescription,
  104. uiHowUsed)){
  105. MYASSERT(FALSE);
  106. return FALSE;
  107. }
  108. }
  109. }
  110. else{
  111. if(FieldPtr->IsString != NoStr)
  112. {
  113. SubStruct = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset);
  114. if(!SubStruct){
  115. SubStruct = (BYTE*)(FieldPtr->IsString == AnsiStr? "": (char*)L"");
  116. }
  117. if(FieldPtr->IsString == AnsiStr){
  118. iLen = (strlen((PCSTR)SubStruct) + 1) * sizeof(CHAR);
  119. }
  120. else{
  121. iLen = (wcslen((PWSTR)SubStruct) + 1) * sizeof(WCHAR);
  122. }
  123. if(BufferMain){
  124. memcpy((BYTE *)(BufferMain + *uiHowUsed), SubStruct, iLen);
  125. }
  126. *uiHowUsed += iLen;
  127. }
  128. else
  129. {
  130. if(FieldPtr->Size)
  131. {
  132. iLen = FieldPtr->ArraySizeFieldOffset?
  133. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, StructurePtr, FieldPtr->ArraySizeFieldOffset)):
  134. 1;
  135. if(BufferMain){
  136. memcpy((char *)(BufferMain + *uiHowUsed),
  137. GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset),
  138. iLen * FieldPtr->Size);
  139. }
  140. *uiHowUsed += iLen * FieldPtr->Size;
  141. }
  142. }
  143. }
  144. }
  145. return TRUE;
  146. }
  147. UINT
  148. CalcSignature(
  149. IN BYTE * BufferPtr,
  150. IN SIZE_T Length
  151. )
  152. {
  153. UINT i;
  154. SIZE_T iLen = Length >> 2;
  155. SIZE_T iRest = Length & 3;
  156. UINT uiSignature = 0;
  157. for(i = 0; i < iLen; i++){
  158. uiSignature ^= ((PUINT)BufferPtr)[i];
  159. }
  160. if(iRest){
  161. uiSignature ^= (((PUINT)BufferPtr)[iLen]) & (0xffffffff >> ((sizeof(UINT) - iRest) << 3));
  162. }
  163. return uiSignature;
  164. }
  165. PERSISTRESULTSENUM
  166. PersistStore(
  167. OUT BYTE ** BufferPtr,
  168. OUT SIZE_T *Size,
  169. IN BYTE * StructurePtr,
  170. IN PSTRUCT_DEFINITION StructDefinitionPtr
  171. )
  172. {
  173. BYTE * buffer = NULL;
  174. BYTE * memBlock = NULL;
  175. SIZE_T uiBufferSize = 0;
  176. PPERSIST_HEADER pPersistHeader;
  177. PFIELD_DESCRIPTION FieldsDescription;
  178. PERSISTRESULTSENUM result = Persist_Success;
  179. if(!BufferPtr || !Size || !StructurePtr || !StructDefinitionPtr){
  180. SetLastError(ERROR_INVALID_PARAMETER);
  181. MYASSERT(FALSE);
  182. return Persist_BadParameters;
  183. }
  184. FieldsDescription = StructDefinitionPtr->FieldDescriptions;
  185. if(!FieldsDescription){
  186. SetLastError(ERROR_INVALID_PARAMETER);
  187. MYASSERT(FALSE);
  188. return Persist_BadParameters;
  189. }
  190. __try{
  191. uiBufferSize = sizeof(PERSIST_HEADER);
  192. if(!SerializeStore(NULL, StructurePtr, FieldsDescription, &uiBufferSize)){
  193. SetLastError(ERROR_ACCESS_DENIED);
  194. return Persist_Fail;
  195. }
  196. memBlock = (BYTE *)MemAllocUninit(uiBufferSize);
  197. if(!memBlock){
  198. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  199. MYASSERT(FALSE);
  200. return Persist_Fail;
  201. }
  202. buffer = memBlock;
  203. *BufferPtr = memBlock;
  204. *Size = uiBufferSize;
  205. pPersistHeader = (PPERSIST_HEADER)memBlock;
  206. buffer += sizeof(PERSIST_HEADER);
  207. pPersistHeader->dwVersion = StructDefinitionPtr->dwVersion;
  208. pPersistHeader->dwReserved = 0;
  209. uiBufferSize = 0;
  210. if(!SerializeStore(buffer, StructurePtr, FieldsDescription, &uiBufferSize)){
  211. FreeMem(memBlock);
  212. SetLastError(ERROR_ACCESS_DENIED);
  213. return Persist_Fail;
  214. }
  215. pPersistHeader->dwSignature = CalcSignature(buffer, uiBufferSize);
  216. SetLastError(ERROR_SUCCESS);
  217. }
  218. __except(EXCEPTION_EXECUTE_HANDLER){
  219. if(memBlock){
  220. FreeMem(memBlock);
  221. }
  222. result = Persist_Fail;
  223. SetLastError(ERROR_ACCESS_DENIED);
  224. }
  225. return result;
  226. }
  227. BOOL
  228. SerializeLoad(
  229. IN BYTE * BufferMain,
  230. IN OUT BYTE * StructurePtr,
  231. IN PFIELD_DESCRIPTION FieldsDescription,
  232. IN OUT SIZE_T * uiHowUsed,
  233. IN BOOL bRestoreOnlyByValue
  234. )
  235. {
  236. FIELD_DESCRIPTION * FieldPtr;
  237. UINT i;
  238. UINT iLen;
  239. SIZE_T Size = 0;
  240. BYTE * SubStruct;
  241. BYTE * OriginalBuffer;
  242. SIZE_T sizeValue;
  243. SIZE_T uiPrevValue;
  244. if(!uiHowUsed){
  245. uiHowUsed = &Size;
  246. }
  247. MYASSERT(StructurePtr);
  248. for(FieldPtr = FieldsDescription; FieldPtr->Offset != END_OF_STRUCT; FieldPtr++){
  249. if(FieldPtr->FieldDescription)
  250. {
  251. iLen = FieldPtr->ArraySizeFieldOffset?
  252. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, StructurePtr, FieldPtr->ArraySizeFieldOffset)):
  253. 1;
  254. if(FieldPtr->byValue){
  255. SubStruct = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset);
  256. }
  257. else{
  258. if(bRestoreOnlyByValue){
  259. continue;
  260. }
  261. if(!*(BufferMain + (*uiHowUsed)++)){
  262. *GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT_PTR *, StructurePtr, FieldPtr->Offset) =
  263. (UINT_PTR)NULL;
  264. continue;
  265. }
  266. MYASSERT(FieldPtr->Size && iLen);
  267. sizeValue = FieldPtr->Size * iLen;
  268. SubStruct = (BYTE *)MemAllocUninit(sizeValue);
  269. if(!SubStruct){
  270. return FALSE;
  271. }
  272. if(MayExtraMemRequire(FieldPtr->FieldDescription)){
  273. OriginalBuffer = SubStruct;
  274. uiPrevValue = *uiHowUsed;
  275. for(i = 0; i < iLen; i++, SubStruct += FieldPtr->Size)
  276. {
  277. if(!SerializeLoad(BufferMain,
  278. SubStruct,
  279. FieldPtr->FieldDescription,
  280. &uiPrevValue,
  281. TRUE)){
  282. return FALSE;
  283. }
  284. sizeValue += GetExtraMemRequirements(SubStruct, FieldPtr->FieldDescription);
  285. }
  286. FreeMem(OriginalBuffer);
  287. SubStruct = (BYTE *)MemAllocZeroed(sizeValue);
  288. if(!SubStruct){
  289. return FALSE;
  290. }
  291. }
  292. *GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT_PTR *, StructurePtr, FieldPtr->Offset) =
  293. (UINT_PTR)SubStruct;
  294. }
  295. for(i = 0; i < iLen;
  296. i++, SubStruct += FieldPtr->Size + GetExtraMemRequirements(SubStruct, FieldPtr->FieldDescription))
  297. {
  298. if(!SerializeLoad(BufferMain,
  299. SubStruct,
  300. FieldPtr->FieldDescription,
  301. uiHowUsed,
  302. FALSE)){
  303. return FALSE;
  304. }
  305. }
  306. }
  307. else{
  308. if(FieldPtr->IsString != NoStr){
  309. if(bRestoreOnlyByValue){
  310. continue;
  311. }
  312. if(FieldPtr->IsString == AnsiStr){
  313. iLen = strlen((char *)(BufferMain + *uiHowUsed)) + sizeof(CHAR);
  314. }
  315. else{
  316. iLen = (wcslen((WCHAR *)(BufferMain + *uiHowUsed)) + 1) * sizeof(WCHAR);
  317. }
  318. MYASSERT(iLen);
  319. if(iLen != (FieldPtr->IsString == AnsiStr? sizeof(CHAR): sizeof(WCHAR)))
  320. {
  321. SubStruct = (BYTE *)MemAllocUninit(iLen);
  322. if(!SubStruct){
  323. return FALSE;
  324. }
  325. memcpy((BYTE *)SubStruct, (BYTE *)(BufferMain + *uiHowUsed), iLen);
  326. }
  327. else{
  328. SubStruct = NULL;
  329. }
  330. *GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT_PTR *, StructurePtr, FieldPtr->Offset) = (UINT_PTR)SubStruct;
  331. *uiHowUsed += iLen;
  332. }
  333. else
  334. {
  335. if(FieldPtr->Size)
  336. {
  337. iLen = FieldPtr->ArraySizeFieldOffset?
  338. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, StructurePtr, FieldPtr->ArraySizeFieldOffset)):
  339. 1;
  340. sizeValue = iLen * FieldPtr->Size;
  341. if(iLen > 1 && bRestoreOnlyByValue){
  342. continue;
  343. }
  344. memcpy(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset),
  345. (char *)(BufferMain + *uiHowUsed),
  346. sizeValue);
  347. *uiHowUsed += sizeValue;
  348. }
  349. }
  350. }
  351. }
  352. return TRUE;
  353. }
  354. PERSISTRESULTSENUM
  355. PersistLoad(
  356. IN BYTE * BufferPtr,
  357. IN SIZE_T Size,
  358. OUT BYTE * StructurePtr,
  359. IN PSTRUCT_DEFINITION StructDefinitionPtr
  360. )
  361. {
  362. SIZE_T uiBufferSize = 0;
  363. PPERSIST_HEADER pPersistHeader;
  364. PFIELD_DESCRIPTION FieldsDescription;
  365. PERSISTRESULTSENUM result = Persist_Success;
  366. if(!BufferPtr || !Size || !StructurePtr || !StructDefinitionPtr){
  367. SetLastError(ERROR_INVALID_PARAMETER);
  368. MYASSERT(FALSE);
  369. return Persist_BadParameters;
  370. }
  371. FieldsDescription = StructDefinitionPtr->FieldDescriptions;
  372. if(!FieldsDescription){
  373. SetLastError(ERROR_INVALID_PARAMETER);
  374. MYASSERT(FALSE);
  375. return Persist_BadParameters;
  376. }
  377. __try{
  378. pPersistHeader = (PPERSIST_HEADER)BufferPtr;
  379. if(pPersistHeader->dwVersion != StructDefinitionPtr->dwVersion){
  380. SetLastError(ERROR_ACCESS_DENIED);
  381. MYASSERT(FALSE);
  382. return Persist_WrongVersion;
  383. }
  384. BufferPtr += sizeof(PERSIST_HEADER);
  385. Size -= sizeof(PERSIST_HEADER);
  386. if(pPersistHeader->dwSignature != CalcSignature(BufferPtr, Size)){
  387. SetLastError(ERROR_CRC);
  388. return Persist_WrongSignature;
  389. }
  390. uiBufferSize = 0;
  391. //Top structure cannot be variable size
  392. if(!SerializeLoad(BufferPtr, StructurePtr, FieldsDescription, &uiBufferSize, FALSE)){
  393. SetLastError(ERROR_ACCESS_DENIED);
  394. return Persist_Fail;
  395. }
  396. SetLastError(ERROR_SUCCESS);
  397. }
  398. __except(EXCEPTION_EXECUTE_HANDLER){
  399. result = Persist_Fail;
  400. SetLastError(ERROR_ACCESS_DENIED);
  401. }
  402. return result;
  403. }
  404. VOID
  405. PersistReleaseMemory(
  406. IN BYTE * StructurePtr,
  407. IN PFIELD_DESCRIPTION FieldsDescription
  408. )
  409. {
  410. UINT i;
  411. UINT iLen;
  412. FIELD_DESCRIPTION * FieldPtr;
  413. BYTE * SubStruct;
  414. if(!StructurePtr || !FieldsDescription){
  415. return;
  416. }
  417. for(FieldPtr = FieldsDescription; FieldPtr->Offset != END_OF_STRUCT; FieldPtr++){
  418. if(FieldPtr->FieldDescription){
  419. iLen = FieldPtr->ArraySizeFieldOffset?
  420. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, StructurePtr, FieldPtr->ArraySizeFieldOffset)):
  421. 1;
  422. if(!iLen){
  423. continue;
  424. }
  425. if(FieldPtr->byValue){
  426. SubStruct = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset);
  427. }
  428. else{
  429. SubStruct = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset);
  430. }
  431. if(!SubStruct){
  432. continue;
  433. }
  434. for(i = 0; i < iLen; i++, SubStruct += FieldPtr->Size){
  435. PersistReleaseMemory(SubStruct, FieldPtr->FieldDescription);
  436. }
  437. if(!FieldPtr->byValue){
  438. FreeMem(GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, StructurePtr, FieldPtr->Offset));
  439. }
  440. }
  441. else{
  442. if(FieldPtr->IsString != NoStr){
  443. SubStruct = (BYTE *)GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(PCSTR, StructurePtr, FieldPtr->Offset);
  444. if(SubStruct){
  445. FreeMem(SubStruct);
  446. }
  447. }
  448. }
  449. }
  450. }
  451. BOOL
  452. CompareStructures(
  453. IN BYTE * pStructure1,
  454. IN BYTE * pStructure2,
  455. IN PFIELD_DESCRIPTION FieldsDescription
  456. )
  457. {
  458. UINT i;
  459. UINT iLen1;
  460. UINT iLen2;
  461. FIELD_DESCRIPTION * FieldPtr;
  462. BYTE * pSubStruct1;
  463. BYTE * pSubStruct2;
  464. if(!pStructure1 || !pStructure2 || !FieldsDescription){
  465. return FALSE;
  466. }
  467. for(FieldPtr = FieldsDescription; FieldPtr->Offset != END_OF_STRUCT; FieldPtr++){
  468. if(FieldPtr->FieldDescription){
  469. iLen1 = FieldPtr->ArraySizeFieldOffset?
  470. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, pStructure1, FieldPtr->ArraySizeFieldOffset)):
  471. 1;
  472. iLen2 = FieldPtr->ArraySizeFieldOffset?
  473. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, pStructure2, FieldPtr->ArraySizeFieldOffset)):
  474. 1;
  475. if(iLen1 != iLen2){
  476. MYASSERT(FALSE);
  477. return FALSE;
  478. }
  479. if(!iLen1){
  480. continue;
  481. }
  482. if(FieldPtr->byValue){
  483. pSubStruct1 = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, pStructure1, FieldPtr->Offset);
  484. pSubStruct2 = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, pStructure2, FieldPtr->Offset);
  485. }
  486. else{
  487. pSubStruct1 = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, pStructure1, FieldPtr->Offset);
  488. pSubStruct2 = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, pStructure2, FieldPtr->Offset);
  489. }
  490. if(!pSubStruct1 || !pSubStruct2){
  491. if(pSubStruct1 != pSubStruct2){
  492. MYASSERT(FALSE);
  493. return FALSE;
  494. }
  495. continue;
  496. }
  497. for(i = 0; i < iLen1;
  498. i++,
  499. pSubStruct1 += FieldPtr->Size + GetExtraMemRequirements(pSubStruct1, FieldPtr->FieldDescription),
  500. pSubStruct2 += FieldPtr->Size + GetExtraMemRequirements(pSubStruct2, FieldPtr->FieldDescription)){
  501. if(!CompareStructures(pSubStruct1, pSubStruct2, FieldPtr->FieldDescription)){
  502. return FALSE;
  503. }
  504. }
  505. }
  506. else{
  507. if(FieldPtr->IsString != NoStr)
  508. {
  509. pSubStruct1 = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, pStructure1, FieldPtr->Offset);
  510. pSubStruct2 = GET_STRUCT_MEMBER_BYREF_FROM_OFFSET(BYTE*, pStructure2, FieldPtr->Offset);
  511. if(!pSubStruct1 || !pSubStruct2){
  512. if(pSubStruct1 != pSubStruct2){
  513. MYASSERT(FALSE);
  514. return FALSE;
  515. }
  516. continue;
  517. }
  518. if(FieldPtr->IsString == AnsiStr){
  519. if(strcmp((LPCSTR)pSubStruct1, (LPCSTR)pSubStruct1)){
  520. MYASSERT(FALSE);
  521. return FALSE;
  522. }
  523. }
  524. else{
  525. if(wcscmp((LPCWSTR)pSubStruct1, (LPCWSTR)pSubStruct1)){
  526. MYASSERT(FALSE);
  527. return FALSE;
  528. }
  529. }
  530. }
  531. else{
  532. iLen1 = FieldPtr->ArraySizeFieldOffset?
  533. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, pStructure1, FieldPtr->ArraySizeFieldOffset)):
  534. 1;
  535. iLen2 = FieldPtr->ArraySizeFieldOffset?
  536. *(GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(UINT*, pStructure2, FieldPtr->ArraySizeFieldOffset)):
  537. 1;
  538. if(iLen1 != iLen2){
  539. MYASSERT(FALSE);
  540. return FALSE;
  541. }
  542. pSubStruct1 = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, pStructure1, FieldPtr->Offset);
  543. pSubStruct2 = GET_STRUCT_MEMBER_BYVALUE_FROM_OFFSET(BYTE*, pStructure2, FieldPtr->Offset);
  544. if(memcmp(pSubStruct1, pSubStruct2, iLen1 * FieldPtr->Size)){
  545. MYASSERT(FALSE);
  546. return FALSE;
  547. }
  548. }
  549. }
  550. }
  551. return TRUE;
  552. }