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.

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