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.

835 lines
28 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name:
  4. frmtstr.hxx
  5. Abstract:
  6. Notes:
  7. History:
  8. DKays Oct-1993 Created.
  9. ----------------------------------------------------------------------------*/
  10. #ifndef __FRMTSTR_HXX__
  11. #define __FRMTSTR_HXX__
  12. extern "C"
  13. {
  14. #include <memory.h>
  15. }
  16. #include "ndrtypes.h"
  17. #include "stream.hxx"
  18. #include "cgcommon.hxx"
  19. #include "dict.hxx"
  20. // #define RKK_FRAG_OPT 1
  21. class RepAsPadExprDict;
  22. class RepAsSizeDict;
  23. class CG_NDR;
  24. #if defined(_AMD64_) || defined(_IA64_) // winnt
  25. #define UNALIGNED __unaligned // winnt
  26. #else // winnt
  27. #define UNALIGNED // winnt
  28. #endif // winnt
  29. // Global defined in frmtstr.cxx
  30. extern char * pNdrRoutineNames[];
  31. // This has to be an even number.
  32. #define DEFAULT_FORMAT_STRING_SIZE 1024
  33. // Format string entry type
  34. // If you add anything here, be sure that it works not only when outputting,
  35. // but also when optimizing out fragments via FRMTREG::Compare.
  36. //
  37. typedef enum
  38. {
  39. FS_FORMAT_CHARACTER,
  40. FS_POINTER_FORMAT_CHARACTER,
  41. FS_SMALL,
  42. FS_SHORT,
  43. FS_LONG,
  44. FS_SHORT_OFFSET,
  45. FS_SHORT_TYPE_OFFSET,
  46. FS_SHORT_STACK_OFFSET,
  47. FS_SMALL_STACK_SIZE,
  48. FS_PAD_MACRO,
  49. FS_SIZE_MACRO,
  50. FS_UNKNOWN_STACK_SIZE,
  51. FS_OLD_PROC_FLAG_BYTE,
  52. FS_Oi2_PROC_FLAG_BYTE,
  53. FS_EXT_PROC_FLAG_BYTE,
  54. FS_PARAM_FLAG_SHORT,
  55. FS_MAGIC_UNION_SHORT,
  56. FS_CORR_TYPE_BYTE,
  57. FS_CORR_FLAG_SHORT,
  58. FS_CONTEXT_HANDLE_FLAG_BYTE
  59. } FORMAT_STRING_ENTRY_TYPE;
  60. // (Stack) Offset Dictionary
  61. //---------------------------
  62. //
  63. // It keeps track of stack or field offsets for parallel win32 platforms.
  64. // The x86 stack offset is stored both directly in the format string itself (as
  65. // a short for 32b implementation) and in the dictionary as a long.
  66. // The true long value is used when optimizing.
  67. // Other offsets are kept in the dictionary under the key which is the position
  68. // of the x86 stack offset in the format string
  69. //
  70. // Note that field offsets may be negative, as for some objects like open structs,
  71. // the correlation descriptor's offset is relative to the position of the
  72. // array field in the struct.
  73. // The format string offset (the position) on the other hand is always absolute,
  74. // we use long only for convenience in dictionary comparisons.
  75. //
  76. typedef struct
  77. {
  78. long FormatStringOffset; // Note, this is not an x86 offset.
  79. // This is the key for this dictionary.
  80. long X86Offset;
  81. } OffsetDictElem;
  82. class OffsetDictionary : Dictionary
  83. {
  84. public :
  85. OffsetDictionary() : Dictionary()
  86. {
  87. }
  88. OffsetDictElem * LookupOffset( long Position )
  89. {
  90. OffsetDictElem DictElem;
  91. OffsetDictElem * pDictElem;
  92. Dict_Status DictStatus;
  93. DictElem.FormatStringOffset = Position;
  94. DictStatus = Dict_Find( &DictElem );
  95. #if defined(RKK_FRAG_OPT)
  96. if (DictStatus != SUCCESS )
  97. {
  98. printf("LookupOffset Offset=%d\n", Position );
  99. }
  100. #endif
  101. MIDL_ASSERT( DictStatus == SUCCESS );
  102. pDictElem = (OffsetDictElem *) Dict_Item();
  103. return pDictElem;
  104. }
  105. virtual
  106. SSIZE_T Compare( pUserType p1, pUserType p2 )
  107. {
  108. return ((OffsetDictElem *)p1)->FormatStringOffset -
  109. ((OffsetDictElem *)p2)->FormatStringOffset;
  110. }
  111. void Insert( long Position,
  112. long X86Offset)
  113. {
  114. OffsetDictElem * pElem;
  115. OffsetDictElem * pElemSave;
  116. #if defined(RKK_FRAG_OPT)
  117. if ( Position < 0 )
  118. printf("Insert negative offset %d\n", Position );
  119. #endif
  120. pElemSave = pElem = new OffsetDictElem;
  121. pElem->FormatStringOffset = Position;
  122. pElem->X86Offset = X86Offset;
  123. //
  124. // Delete any entries which currently match, that is
  125. // entries with the same FormatStringOffset key. This
  126. // can happen because of format string compression.
  127. //
  128. while ( Dict_Delete( (pUserType *) &pElem ) == SUCCESS )
  129. ;
  130. Dict_Insert( pElemSave );
  131. }
  132. };
  133. // Type Offset Dictionary
  134. //---------------------------
  135. //
  136. // It keeps track of type offsets, both absolute and relative.
  137. // The reason we use a dictionary is to allow proper fragment optimization for
  138. // for 32b implementation where a type offset has to be in short32 range while
  139. // keeping it as a long permits the best optimization possible.
  140. // Note that for 32b there is only one type offset regardless of the platform.
  141. //
  142. // The format string offset (the position) on the other hand is always absolute,
  143. // we use long only for convenience in dictionary comparisons.
  144. //
  145. typedef struct
  146. {
  147. long Position; // FormatStringOffset is the key for this dictionary.
  148. long TypeOffset;
  149. } TypeOffsetDictElem;
  150. class TypeOffsetDictionary : Dictionary
  151. {
  152. public :
  153. TypeOffsetDictionary() : Dictionary()
  154. {
  155. }
  156. TypeOffsetDictElem *LookupOffset( long Position )
  157. {
  158. TypeOffsetDictElem DictElem;
  159. TypeOffsetDictElem * pDictElem;
  160. Dict_Status DictStatus;
  161. DictElem.Position = Position;
  162. DictStatus = Dict_Find( &DictElem );
  163. #if defined(RKK_FRAG_OPT)
  164. if (DictStatus != SUCCESS )
  165. {
  166. printf("LookupOffset Position=%d\n", Position );
  167. }
  168. #endif
  169. MIDL_ASSERT( DictStatus == SUCCESS );
  170. pDictElem = (TypeOffsetDictElem *) Dict_Item();
  171. return pDictElem;
  172. }
  173. virtual
  174. SSIZE_T Compare( pUserType p1, pUserType p2 )
  175. {
  176. return ((TypeOffsetDictElem *)p1)->Position -
  177. ((TypeOffsetDictElem *)p2)->Position;
  178. }
  179. void Insert( long Position, long TypeOffset )
  180. {
  181. TypeOffsetDictElem * pElem;
  182. TypeOffsetDictElem * pElemSave;
  183. #if defined(RKK_FRAG_OPT)
  184. if ( Position < 0 )
  185. printf("Insert negative offset %d\n", Position );
  186. #endif
  187. pElemSave = pElem = new TypeOffsetDictElem;
  188. pElem->Position = Position;
  189. pElem->TypeOffset = TypeOffset;
  190. //
  191. // Delete any entries which currently match, that is
  192. // entries with the same FormatStringOffset key. This
  193. // can happen because of format string compression.
  194. //
  195. while ( Dict_Delete( (pUserType *) &pElem ) == SUCCESS )
  196. ;
  197. Dict_Insert( pElemSave );
  198. }
  199. };
  200. // (Unknown) StackSize Dictionary
  201. //-------------------------------
  202. //
  203. // It keeps track of unknown stack sizes related to unknown represent_as() types.
  204. // At the place where we have to generate the stack size in the output file,
  205. // we use the type name to generate a size_of() expression.
  206. //
  207. // The format string offset (the position) is always absolute,
  208. // we use longs only for convenience in dictionary comparisons.
  209. typedef struct
  210. {
  211. long FormatStringOffset; // used as the key
  212. char * pTypeName;
  213. } StackSizeDictElem;
  214. class StackSizeDictionary : Dictionary
  215. {
  216. public :
  217. StackSizeDictionary() : Dictionary()
  218. {
  219. }
  220. virtual
  221. SSIZE_T Compare( pUserType p1, pUserType p2 )
  222. {
  223. return ((StackSizeDictElem *)p1)->FormatStringOffset -
  224. ((StackSizeDictElem *)p2)->FormatStringOffset;
  225. }
  226. char * LookupTypeName( long Offset )
  227. {
  228. StackSizeDictElem DictElem;
  229. StackSizeDictElem * pDictElem;
  230. Dict_Status DictStatus;
  231. DictElem.FormatStringOffset = Offset;
  232. DictStatus = Dict_Find( &DictElem );
  233. MIDL_ASSERT( DictStatus == SUCCESS );
  234. pDictElem = (StackSizeDictElem *) Dict_Item();
  235. return pDictElem->pTypeName;
  236. }
  237. void Insert( long FormatStringOffset, char * pTypeName )
  238. {
  239. StackSizeDictElem * pElem;
  240. StackSizeDictElem * pElemSave;
  241. pElem = pElemSave = new StackSizeDictElem;
  242. pElem->FormatStringOffset = FormatStringOffset;
  243. pElem->pTypeName = pTypeName;
  244. //
  245. // Delete any entries which currently match, this
  246. // can happen because of format string compression.
  247. //
  248. while ( Dict_Delete( (pUserType *) &pElem ) == SUCCESS )
  249. ;
  250. Dict_Insert( pElemSave );
  251. }
  252. };
  253. // CommentDictionary
  254. //-------------------------------
  255. //
  256. // It keeps track of comments that can be attached to a given format string
  257. // position.
  258. // Note that for any offset position, we may have several comments.
  259. //
  260. // The format string offset (the position) is always absolute,
  261. // we use longs only for convenience in dictionary comparisons.
  262. typedef struct _CommentDictElem
  263. {
  264. struct _CommentDictElem * Next;
  265. long FormatStringOffset; // used as the key
  266. char * Comment;
  267. } CommentDictElem;
  268. class CommentDictionary : Dictionary
  269. {
  270. public :
  271. CommentDictionary() : Dictionary()
  272. {
  273. }
  274. virtual
  275. SSIZE_T Compare( pUserType p1, pUserType p2 )
  276. {
  277. return ((CommentDictElem *)p1)->FormatStringOffset -
  278. ((CommentDictElem *)p2)->FormatStringOffset;
  279. }
  280. char * GetComments( long Offset );
  281. void Insert( long FormatStringOffset, char * Comment );
  282. };
  283. //---------------------------------------
  284. // FormatReg Dictionary is used to keep track of format string fragments
  285. // that can be collapsed (optimized out).
  286. class FRMTREG_DICT;
  287. //---------------------------------------
  288. // Format string
  289. //---------------------------------------
  290. class FORMAT_STRING
  291. {
  292. unsigned char * pBuffer; // Format string buffer.
  293. unsigned char * pBufferType; // Entry type for each position.
  294. // - indicates the meaning
  295. unsigned long BufferSize; // Total current allocated buffer size.
  296. unsigned long CurrentOffset; // Current offset in the format string buffer.
  297. unsigned long LastOffset; // The last valid format string buffer index.
  298. OffsetDictionary OffsetDict; // Stack offsets at a position
  299. TypeOffsetDictionary TypeOffsetDict; // Type offsets at a position
  300. StackSizeDictionary UnknownStackSizeDict; // Unknown type at a position
  301. CommentDictionary CommentDict; // Comments at a position
  302. FRMTREG_DICT * pReuseDict; // Fragment optimization dictionary.
  303. //
  304. // This class is a friend as its Compare method accesses pBuffer, pBufferType
  305. // as well as OffsetDictionary in order to optimize fragments.
  306. //
  307. friend class FRMTREG_DICT;
  308. //
  309. // Increment CurrentOffset and update LastOffset if needed.
  310. //
  311. void
  312. IncrementOffset( long increment )
  313. {
  314. CurrentOffset += increment;
  315. if ( CurrentOffset > LastOffset )
  316. LastOffset = CurrentOffset;
  317. }
  318. public:
  319. FORMAT_STRING();
  320. ~FORMAT_STRING()
  321. {
  322. delete pBuffer;
  323. delete pBufferType;
  324. }
  325. //
  326. // Align the buffer correctly. If the current offset is odd then
  327. // insert a pad format character.
  328. //
  329. void
  330. Align()
  331. {
  332. if ( CurrentOffset % 2 )
  333. PushFormatChar( FC_PAD );
  334. }
  335. void AddComment( long FormatOffset, char * Comment )
  336. {
  337. CommentDict.Insert( FormatOffset, Comment );
  338. }
  339. //
  340. // Add a format char at the current offset.
  341. //
  342. void
  343. PushFormatChar( FORMAT_CHARACTER fc )
  344. {
  345. CheckSize();
  346. pBufferType[CurrentOffset] = FS_FORMAT_CHARACTER;
  347. pBuffer[CurrentOffset] = (unsigned char)fc;
  348. IncrementOffset(1);
  349. }
  350. //
  351. // Add a pointer format char at the current offset.
  352. //
  353. void
  354. PushPointerFormatChar( unsigned char fc )
  355. {
  356. CheckSize();
  357. pBufferType[CurrentOffset] = FS_POINTER_FORMAT_CHARACTER;
  358. pBuffer[CurrentOffset] = fc;
  359. IncrementOffset(1);
  360. }
  361. //
  362. // Push a byte at the current offset.
  363. //
  364. void
  365. PushByte( long b )
  366. {
  367. CheckSize();
  368. pBufferType[CurrentOffset] = FS_SMALL;
  369. pBuffer[CurrentOffset] = (unsigned char) b;
  370. IncrementOffset(1);
  371. }
  372. //
  373. // Push a byte with old proc attributes at the current offset
  374. //
  375. void PushOldProcFlagsByte( long b )
  376. {
  377. CheckSize();
  378. pBufferType[CurrentOffset] = FS_OLD_PROC_FLAG_BYTE;
  379. pBuffer[CurrentOffset] = (unsigned char) b;
  380. IncrementOffset(1);
  381. }
  382. //
  383. // Push a byte with old proc attributes at the current offset
  384. //
  385. void PushOi2ProcFlagsByte( long b )
  386. {
  387. CheckSize();
  388. pBufferType[CurrentOffset] = FS_Oi2_PROC_FLAG_BYTE;
  389. pBuffer[CurrentOffset] = (unsigned char) b;
  390. IncrementOffset(1);
  391. }
  392. //
  393. // Push a byte with NT5 extended proc attributes at the current offset
  394. //
  395. void PushExtProcFlagsByte( long b )
  396. {
  397. CheckSize();
  398. pBufferType[CurrentOffset] = FS_EXT_PROC_FLAG_BYTE;
  399. pBuffer[CurrentOffset] = (unsigned char) b;
  400. IncrementOffset(1);
  401. }
  402. //
  403. // Push a context handle flags byte
  404. //
  405. void PushContextHandleFlagsByte( long b )
  406. {
  407. CheckSize();
  408. pBufferType[CurrentOffset] = FS_CONTEXT_HANDLE_FLAG_BYTE;
  409. pBuffer[CurrentOffset] = (unsigned char) b;
  410. IncrementOffset(1);
  411. }
  412. //
  413. // Push a byte with a correlation type (first byte of a correlation desc).
  414. //
  415. void PushCorrelationTypeByte( long b )
  416. {
  417. CheckSize();
  418. pBufferType[CurrentOffset] = FS_CORR_TYPE_BYTE;
  419. pBuffer[CurrentOffset] = (unsigned char) b;
  420. IncrementOffset(1);
  421. }
  422. //
  423. // Push a short at the current offset.
  424. //
  425. void
  426. PushShort( short s )
  427. {
  428. CheckSize();
  429. pBufferType[CurrentOffset] = FS_SHORT;
  430. pBufferType[CurrentOffset+1] = FS_SMALL;
  431. *((short UNALIGNED *)(pBuffer + CurrentOffset)) = s;
  432. IncrementOffset(2);
  433. }
  434. //
  435. // Push a short with parameter attributes at the current offset.
  436. //
  437. void PushParamFlagsShort( short s )
  438. {
  439. CheckSize();
  440. pBufferType[CurrentOffset] = FS_PARAM_FLAG_SHORT;
  441. pBufferType[CurrentOffset+1] = FS_SMALL;
  442. *((short UNALIGNED *)(pBuffer + CurrentOffset)) = s;
  443. IncrementOffset(2);
  444. }
  445. //
  446. // Push a short with the new, robust related, correlation flags.
  447. //
  448. void PushCorrelationFlagsShort( short s )
  449. {
  450. CheckSize();
  451. pBufferType[CurrentOffset] = FS_CORR_FLAG_SHORT;
  452. pBufferType[CurrentOffset+1] = FS_SMALL;
  453. *((short UNALIGNED *)(pBuffer + CurrentOffset)) = s;
  454. IncrementOffset(2);
  455. }
  456. //
  457. // Push a short at the current offset.
  458. //
  459. void
  460. PushShort( long s )
  461. {
  462. CheckSize();
  463. pBufferType[CurrentOffset] = FS_SHORT;
  464. pBufferType[CurrentOffset+1] = FS_SMALL;
  465. *((short UNALIGNED *)(pBuffer + CurrentOffset)) = (short) s;
  466. IncrementOffset(2);
  467. }
  468. //
  469. // Push a long at the current offset.
  470. //
  471. void
  472. PushLong( long l )
  473. {
  474. CheckSize();
  475. pBufferType[CurrentOffset] = FS_LONG;
  476. pBufferType[CurrentOffset+1] = FS_SMALL;
  477. pBufferType[CurrentOffset+2] = FS_SMALL;
  478. pBufferType[CurrentOffset+3] = FS_SMALL;
  479. *((long UNALIGNED *)(pBuffer + CurrentOffset)) = l;
  480. IncrementOffset(4);
  481. }
  482. //
  483. // Push a pad macro marker at the current offset.
  484. //
  485. void
  486. PushByteWithPadMacro()
  487. {
  488. CheckSize();
  489. pBufferType[ CurrentOffset ] = FS_PAD_MACRO;
  490. pBuffer[ CurrentOffset ] = 0;
  491. IncrementOffset(1);
  492. }
  493. //
  494. // Push a size macro marker at the current offset.
  495. //
  496. void
  497. PushShortWithSizeMacro()
  498. {
  499. CheckSize();
  500. pBufferType[ CurrentOffset ] = FS_SIZE_MACRO;
  501. pBufferType[CurrentOffset+1] = FS_SMALL;
  502. pBuffer[ CurrentOffset ] = 0;
  503. IncrementOffset(2);
  504. }
  505. //
  506. // Push a format char at the specified offset.
  507. //
  508. void
  509. PushFormatChar( FORMAT_CHARACTER fc, long offset )
  510. {
  511. pBufferType[offset] = FS_FORMAT_CHARACTER;
  512. pBuffer[offset] = (unsigned char)fc;
  513. }
  514. //
  515. // Push a short at the specified offset.
  516. // Used only in unions to emit magic byte followed by simple type or
  517. // to emit -1 as a marker for no default arm.
  518. //
  519. void PushMagicUnionShort( short s, long offset )
  520. {
  521. pBufferType[ offset ] = FS_MAGIC_UNION_SHORT;
  522. pBufferType[ offset+1] = FS_SMALL;
  523. *((short UNALIGNED *)(pBuffer + offset)) = s;
  524. }
  525. //
  526. // Push a short at the specified offset.
  527. // Used primarily to push offsets internal to a type descriptor, for example
  528. // an offset to pointer layout. These are treated as plain shorts as they
  529. // never change and should not be mistaken for a relative type offset.
  530. //
  531. void PushShort( long s, long offset )
  532. {
  533. pBufferType[ offset ] = FS_SHORT;
  534. pBufferType[ offset+1] = FS_SMALL;
  535. *((short UNALIGNED *)(pBuffer + offset)) = (short) s;
  536. }
  537. //
  538. // Push a long at the specified offset. Used only for union case values.
  539. //
  540. void PushLong( long l, long offset )
  541. {
  542. pBufferType[ offset ] = FS_LONG;
  543. pBufferType[ offset+1] = FS_SMALL;
  544. pBufferType[ offset+2] = FS_SMALL;
  545. pBufferType[ offset+3] = FS_SMALL;
  546. *((long UNALIGNED *)(pBuffer + offset)) = l;
  547. }
  548. //
  549. // Push a short offset at the current offset.
  550. // This is the relative type offset within the type string.
  551. // For 32b code, this needs to be a value within a signed short.
  552. //
  553. void PushShortOffset( long s );
  554. void PushShortOffset( long s, long offset );
  555. //
  556. // Push a short type-fmt-string offset at the current offset.
  557. // This is used as the offset from a parameter into type format string.
  558. // For 32b code, this needs to be a value within an unsigned short.
  559. //
  560. void PushShortTypeOffset( long s );
  561. //
  562. // Push a stack offset.
  563. // Needs to be relative for non-top level objects.
  564. //
  565. void PushShortStackOffset( long X86Offset );
  566. //
  567. // Push a stack size or an unsigned stack offset. This is absolute value.
  568. // Used for proc stack size and parameter offsets.
  569. //
  570. void PushUShortStackOffsetOrSize( long X86Offset );
  571. //
  572. // Push a parameter stack size expressed as the number of ints required
  573. // for the parameter on the stack.
  574. //
  575. // The old -Oi parameter descriptor is the only place where this is used.
  576. //
  577. void
  578. PushSmallStackSize( char StackSize )
  579. {
  580. CheckSize();
  581. pBufferType[CurrentOffset] = FS_SMALL_STACK_SIZE;
  582. pBuffer[CurrentOffset] = StackSize;
  583. IncrementOffset(1);
  584. }
  585. //
  586. // Push an unknown rep as stack size. We need the type name so we can
  587. // spit out a 'sizeof' in the format string.
  588. //
  589. // The old -Oi parameter descriptor is the only place where this is used.
  590. //
  591. void
  592. PushUnknownStackSize( char * pTypeName )
  593. {
  594. CheckSize();
  595. pBufferType[CurrentOffset] = FS_UNKNOWN_STACK_SIZE;
  596. UnknownStackSizeDict.Insert( (long) CurrentOffset, pTypeName );
  597. IncrementOffset(1);
  598. }
  599. //
  600. // Get a FORMAT_CHARACTER at a specific offset in the format string.
  601. //
  602. FORMAT_CHARACTER
  603. GetFormatChar( long offset )
  604. {
  605. return (FORMAT_CHARACTER) pBuffer[offset];
  606. }
  607. //
  608. // Get a short at a specific offset in the format string.
  609. //
  610. short
  611. GetFormatShort( long offset )
  612. {
  613. return *(short UNALIGNED *)(pBuffer + offset);
  614. }
  615. //
  616. // Get the current format string offset.
  617. //
  618. long
  619. GetCurrentOffset()
  620. {
  621. return (long)CurrentOffset;
  622. }
  623. //
  624. // Set the current format string offset. This discards
  625. // everything after (and including) the new offset from the format string
  626. //
  627. void SetCurrentOffset( long NewOffset )
  628. {
  629. LastOffset = (unsigned long)NewOffset;
  630. CurrentOffset = (unsigned long)NewOffset;
  631. }
  632. //
  633. // Output the format string structure to the given stream.
  634. //
  635. void Output( ISTREAM * pStream,
  636. char * pTypeName,
  637. char * pName,
  638. RepAsPadExprDict * pPadDict,
  639. RepAsSizeDict * pSizeDict );
  640. void OutputExprEvalFormatString(ISTREAM *pStream);
  641. //
  642. // Get the fragment re-use dictionary
  643. //
  644. FRMTREG_DICT * GetReuseDict()
  645. {
  646. return pReuseDict;
  647. }
  648. //
  649. // Optimize a fragment away
  650. //
  651. long OptimizeFragment( CG_NDR * pNode );
  652. //
  653. // Register a fragment, but don't delete it
  654. //
  655. unsigned short RegisterFragment( CG_NDR * pNode );
  656. private :
  657. //
  658. // Check if a bigger buffer needs to be allocated.
  659. //
  660. void CheckSize();
  661. };
  662. #endif