Windows NT 4.0 source code leak
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.

1270 lines
28 KiB

4 years ago
  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. ptrndr.hxx
  5. Abstract:
  6. Contains routines for the generation of the new NDR format strings for
  7. pointer types, and the new NDR marshalling and unmarshalling calls.
  8. Notes:
  9. History:
  10. DKays Oct-1993 Created.
  11. ----------------------------------------------------------------------------*/
  12. #include "becls.hxx"
  13. #pragma hdrstop
  14. static long StringToHex( char * str );
  15. extern CMD_ARG * pCommand;
  16. BOOL
  17. CG_POINTER::IsPointerToBaseType()
  18. {
  19. BOOL fIsPointerToBaseType = FALSE;
  20. CG_NDR * pChild;
  21. if(GetCGID() == ID_CG_PTR)
  22. {
  23. pChild = (CG_NDR *)GetChild();
  24. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  25. pChild = (CG_NDR *)pChild->GetChild();
  26. if(pChild->IsSimpleType())
  27. fIsPointerToBaseType = TRUE;
  28. }
  29. return fIsPointerToBaseType;
  30. }
  31. BOOL
  32. CG_POINTER::IsPointerToPointer()
  33. {
  34. BOOL fIsPointerToPointer = FALSE;
  35. CG_NDR * pChild;
  36. if(GetCGID() == ID_CG_PTR)
  37. {
  38. pChild = (CG_NDR *)GetChild();
  39. if ( pChild->GetCGID() == ID_CG_GENERIC_HDL )
  40. pChild = (CG_NDR *)pChild->GetChild();
  41. if (pChild->IsPointer())
  42. fIsPointerToPointer = TRUE;
  43. }
  44. return fIsPointerToPointer;
  45. }
  46. BOOL
  47. CG_POINTER::IsBasicRefPointer()
  48. {
  49. short Attributes;
  50. if ( (GetCGID() == ID_CG_INTERFACE_PTR) ||
  51. (GetCGID() == ID_CG_BC_PTR) ||
  52. (GetCGID() == ID_CG_STRUCT_STRING_PTR) ||
  53. (GetPtrType() != PTR_REF) ||
  54. IsPointerToBaseType() )
  55. return FALSE;
  56. if ( ((GetCGID() == ID_CG_STRING_PTR) ||
  57. (GetCGID() == ID_CG_SIZE_STRING_PTR)) &&
  58. ((CG_STRING_POINTER *)this)->IsStringableStruct() )
  59. return FALSE;
  60. Attributes = GetAllocateDetails();
  61. if ( IsPointerToPointer() ||
  62. IS_ALLOCATE(Attributes, ALLOCATE_ALL_NODES) ||
  63. IS_ALLOCATE(Attributes, ALLOCATE_DONT_FREE) )
  64. return FALSE;
  65. return TRUE;
  66. }
  67. BOOL
  68. CG_POINTER::IsMultiSize()
  69. {
  70. if ( (GetCGID() != ID_CG_SIZE_PTR) &&
  71. (GetCGID() != ID_CG_SIZE_LENGTH_PTR) )
  72. return FALSE;
  73. CG_NDR * pChild = (CG_NDR *) GetChild();
  74. if ( (pChild->GetCGID() == ID_CG_SIZE_PTR) ||
  75. (pChild->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
  76. (pChild->GetCGID() == ID_CG_SIZE_STRING_PTR) )
  77. return TRUE;
  78. return FALSE;
  79. }
  80. long
  81. CG_POINTER::SizedDimensions()
  82. {
  83. CG_NDR * pNdr;
  84. long Dim;
  85. Dim = 0;
  86. pNdr = this;
  87. for ( ; ; pNdr = (CG_NDR *) pNdr->GetChild(), Dim++ )
  88. {
  89. if ( (pNdr->GetCGID() != ID_CG_SIZE_PTR) &&
  90. (pNdr->GetCGID() != ID_CG_SIZE_LENGTH_PTR) &&
  91. (pNdr->GetCGID() != ID_CG_SIZE_STRING_PTR) )
  92. break;
  93. }
  94. return Dim;
  95. }
  96. long
  97. CG_POINTER::FixedBufferSize( CCB * pCCB )
  98. {
  99. long BufSize;
  100. //
  101. // Must give up on string or sized pointers.
  102. //
  103. if ( GetCGID() != ID_CG_PTR )
  104. return -1;
  105. BufSize = ((CG_NDR *)GetChild())->FixedBufferSize( pCCB );
  106. if ( BufSize == -1 )
  107. return -1;
  108. if ( GetPtrType() != PTR_REF )
  109. BufSize += 8;
  110. return BufSize;
  111. }
  112. BOOL
  113. CG_POINTER::InterpreterAllocatesOnStack(
  114. CCB * pCCB,
  115. CG_PARAM * pMyParam,
  116. long * pAllocationSize )
  117. {
  118. CG_NDR * pNdr;
  119. long OutSize;
  120. if ( ! pMyParam )
  121. return FALSE;
  122. pNdr = (CG_NDR *) GetChild();
  123. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
  124. pNdr = (CG_NDR *) pNdr->GetChild();
  125. if ( pNdr->GetCGID() == ID_CG_CONTEXT_HDL )
  126. {
  127. //
  128. // These get the "allocated on stack" attribute but a size of 0 since
  129. // they are allocated by calling NDRSContextUnmarshall.
  130. //
  131. *pAllocationSize = 0;
  132. return TRUE;
  133. }
  134. //
  135. // Make sure this pointer is a top level parameter and doesn't have
  136. // any allocate attributes.
  137. //
  138. if ( (pMyParam->GetCGID() == ID_CG_RETURN) ||
  139. (pMyParam->GetChild() != this) ||
  140. IS_ALLOCATE( GetAllocateDetails(), ALLOCATE_ALL_NODES ) ||
  141. IS_ALLOCATE( GetAllocateDetails(), ALLOCATE_DONT_FREE ) )
  142. return FALSE;
  143. OutSize = pCCB->GetInterpreterOutSize();
  144. //
  145. // Watch for [out] only ref to ref pointers as they should be
  146. // handled by NdrOutInit in the new interpreter, not on stack.
  147. //
  148. if ( ! pMyParam->IsParamIn() && IsRef() &&
  149. IsPointerToPointer() && ((CG_POINTER *)pNdr)->IsRef() )
  150. return FALSE;
  151. //
  152. // Look for pointer to pointer, [out] only pointer to base type, or
  153. // pointer to enum16 of any direction.
  154. //
  155. if ( IsPointerToPointer() ||
  156. (IsPointerToBaseType() && ! pMyParam->IsParamIn()) ||
  157. (IsPointerToBaseType() &&
  158. (((CG_BASETYPE *)pNdr)->GetFormatChar() == FC_ENUM16) &&
  159. pMyParam->IsParamIn()) )
  160. {
  161. if ( (OutSize + 8) <= MAX_INTERPRETER_OUT_SIZE )
  162. {
  163. *pAllocationSize = 8;
  164. pCCB->SetInterpreterOutSize( pCCB->GetInterpreterOutSize() + 8 );
  165. return TRUE;
  166. }
  167. }
  168. //
  169. // Finished with [in], [in,out] cases now.
  170. //
  171. if ( pMyParam->IsParamIn() )
  172. return FALSE;
  173. //
  174. // This covers [out] pointers to structs and unions. We don't allow
  175. // any one parameter to eat up too much of the total stack space
  176. // the interpreter has set aside for this optimization.
  177. //
  178. if ( pNdr->GetMemorySize() <= MAX_INTERPRETER_PARAM_OUT_SIZE )
  179. {
  180. OutSize += (pNdr->GetMemorySize() + 7) & ~0x7;
  181. if ( OutSize <= MAX_INTERPRETER_OUT_SIZE )
  182. {
  183. *pAllocationSize = (pNdr->GetMemorySize() + 7) & ~0x7;
  184. pCCB->SetInterpreterOutSize(
  185. pCCB->GetInterpreterOutSize() + *pAllocationSize );
  186. return TRUE;
  187. }
  188. }
  189. return FALSE;
  190. }
  191. void
  192. CG_POINTER::GenNdrPointerType( CCB * pCCB )
  193. /*++
  194. Routine Description :
  195. Generates the first two bytes of a pointer's format string description.
  196. Arguments :
  197. pCCB - pointer to the code control block.
  198. Return:
  199. Returns FALSE if the format string for the pointer type has already been
  200. generated, otherwise returns TRUE.
  201. --*/
  202. {
  203. FORMAT_STRING * pFormatString;
  204. CG_PARAM * pParam;
  205. short Attributes;
  206. unsigned char FormatAttr;
  207. pFormatString = pCCB->GetFormatString();
  208. pParam = pCCB->GetCurrentParam();
  209. //
  210. // Set the pointer type.
  211. //
  212. switch ( GetPtrType() )
  213. {
  214. case PTR_REF :
  215. pFormatString->PushPointerFormatChar(FC_RP);
  216. break;
  217. case PTR_UNIQUE :
  218. //
  219. // Check if this is a unique pointer in an OLE interface, but
  220. // is not the top most pointer.
  221. //
  222. if ( pCCB->IsInObjectInterface() &&
  223. pParam->IsParamOut() &&
  224. pParam->GetChild() != this )
  225. pFormatString->PushPointerFormatChar(FC_OP);
  226. else
  227. pFormatString->PushPointerFormatChar(FC_UP);
  228. break;
  229. case PTR_FULL :
  230. pFormatString->PushPointerFormatChar(FC_FP);
  231. break;
  232. }
  233. //
  234. // Now the attributes.
  235. //
  236. FormatAttr = 0;
  237. Attributes = GetAllocateDetails();
  238. if ( IS_ALLOCATE(Attributes, ALLOCATE_ALL_NODES) )
  239. FormatAttr |= FC_ALLOCATE_ALL_NODES;
  240. if ( IS_ALLOCATE(Attributes, ALLOCATE_DONT_FREE) )
  241. FormatAttr |= FC_DONT_FREE;
  242. if ( GetCGID() == ID_CG_PTR )
  243. {
  244. //
  245. // Check if we are allocated on the stack by the stub. Currently this
  246. // only works for top level pointers.
  247. //
  248. if ( ! ShouldPointerFree() &&
  249. ! (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER) )
  250. FormatAttr |= FC_ALLOCED_ON_STACK;
  251. //
  252. // For the interpreter we set the alloced on stack attribute for
  253. // those [out] pointers which we will be able to "allocate" on the
  254. // server interpreter's stack. We also do this for [in,out] double
  255. // pointers.
  256. // The version 1 interpreter simply looks for pointers to context
  257. // handles.
  258. //
  259. if ( pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER )
  260. {
  261. if ( ! (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER_V2) )
  262. {
  263. if ( ((CG_NDR *)GetChild())->GetCGID() == ID_CG_CONTEXT_HDL )
  264. FormatAttr |= FC_ALLOCED_ON_STACK;
  265. }
  266. else
  267. {
  268. long OutSize;
  269. if ( InterpreterAllocatesOnStack( pCCB, pParam, &OutSize ) )
  270. FormatAttr |= FC_ALLOCED_ON_STACK;
  271. }
  272. }
  273. }
  274. //
  275. // Check for a pointer to simple type, non-sized string, or pointer to
  276. // pointer.
  277. //
  278. if ( IsPointerToBaseType() || (GetCGID() == ID_CG_STRING_PTR) )
  279. FormatAttr |= FC_SIMPLE_POINTER;
  280. if ( IsPointerToPointer() )
  281. FormatAttr |= FC_POINTER_DEREF;
  282. pFormatString->PushByte( FormatAttr );
  283. SetFormatAttr( FormatAttr );
  284. }
  285. void
  286. CG_POINTER::GenNdrFormat( CCB * pCCB )
  287. /*++
  288. Routine Description :
  289. Generates the format string description for a pointer to anything.
  290. Arguments :
  291. pCCB - pointer to the code control block.
  292. --*/
  293. {
  294. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  295. unsigned short StartOffset = pFormatString->GetCurrentOffset();
  296. if ( GetFormatStringOffset() != -1 )
  297. return;
  298. SetFormatStringOffset( StartOffset );
  299. SetFormatStringEndOffset( StartOffset + 4 );
  300. GenNdrFormatAlways( pCCB );
  301. // here, we assume all pointers generate 4 bytes
  302. SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
  303. }
  304. void
  305. CG_POINTER::GenNdrFormatAlways( CCB * pCCB )
  306. /*++
  307. Routine Description :
  308. Generates the format string description for a pointer to anything.
  309. Arguments :
  310. pCCB - pointer to the code control block.
  311. --*/
  312. {
  313. FORMAT_STRING * pFormatString;
  314. long Offset;
  315. pFormatString = pCCB->GetFormatString();
  316. GenNdrPointerType( pCCB );
  317. //
  318. // If it's an unattributed pointer to a simple type then the format
  319. // string is optimized.
  320. //
  321. if ( IsPointerToBaseType() )
  322. {
  323. GenNdrFormatPointee( pCCB );
  324. pFormatString->PushFormatChar( FC_PAD );
  325. return;
  326. }
  327. // Get the current offset.
  328. Offset = pFormatString->GetCurrentOffset();
  329. // Push a short for the offset to be filled in later.
  330. pFormatString->PushShortOffset( 0 );
  331. // Generate the pointee's format string.
  332. GenNdrFormatPointee( pCCB );
  333. // Now fill in the offset field correctly.
  334. pFormatString->PushShort( GetPointeeFormatStringOffset() - Offset,
  335. Offset );
  336. }
  337. void
  338. CG_POINTER::GenNdrParamOffline( CCB * pCCB )
  339. {
  340. GenNdrFormat( pCCB );
  341. }
  342. void
  343. CG_POINTER::GenNdrFormatPointee( CCB * pCCB )
  344. /*++
  345. Routine Description :
  346. Generates the format string description for the pointee of an
  347. unattributed pointer to anything.
  348. Arguments :
  349. pCCB - pointer to the code control block.
  350. --*/
  351. {
  352. CG_NDR * pChild;
  353. pChild = (CG_NDR *)GetChild();
  354. if (pChild->IsProc())
  355. {
  356. assert(pCommand->IsHookOleEnabled());
  357. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  358. SetPointeeFormatStringOffset(pFormatString->GetCurrentOffset());
  359. pFormatString->PushFormatChar(FC_BLKHOLE);
  360. pFormatString->PushByte( BLKHOLE_FUNCTION ); // flags
  361. pFormatString->PushShort( (short) -1 ); // Reserved
  362. }
  363. else
  364. {
  365. //
  366. // For unattributed pointers (no size or length), this is simply a
  367. // call to the child's GenNdrFormat method.
  368. //
  369. pChild->GenNdrFormat( pCCB );
  370. SetPointeeFormatStringOffset( pChild->GetFormatStringOffset() );
  371. }
  372. }
  373. BOOL
  374. CG_POINTER::ShouldFreeOffline()
  375. {
  376. CG_NDR * pNdr;
  377. //
  378. // The order here is very, very important.
  379. //
  380. if ( IsAllocateDontFree() )
  381. return FALSE;
  382. pNdr = (CG_NDR *) GetChild();
  383. //
  384. // Skip past generic handle nodes.
  385. //
  386. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
  387. pNdr = (CG_NDR *) pNdr->GetChild();
  388. //
  389. // Check for handles.
  390. //
  391. if ( (pNdr->GetCGID() == ID_CG_CONTEXT_HDL) ||
  392. (pNdr->GetCGID() == ID_CG_PRIMITIVE_HDL) )
  393. return FALSE;
  394. //
  395. // Offline full pointers.
  396. //
  397. if ( GetPtrType() == PTR_FULL )
  398. return TRUE;
  399. switch ( GetCGID() )
  400. {
  401. case ID_CG_PTR :
  402. case ID_CG_SIZE_PTR :
  403. break;
  404. case ID_CG_STRING_PTR :
  405. case ID_CG_STRUCT_STRING_PTR :
  406. return FALSE;
  407. case ID_CG_SIZE_LENGTH_PTR :
  408. case ID_CG_LENGTH_PTR :
  409. case ID_CG_SIZE_STRING_PTR :
  410. case ID_CG_BC_PTR :
  411. return TRUE;
  412. default :
  413. assert(0);
  414. }
  415. if ( pNdr->IsSimpleType() )
  416. return FALSE;
  417. if ( pNdr->IsStruct() )
  418. return ((CG_STRUCT *)pNdr)->ShouldFreeOffline();
  419. return TRUE;
  420. }
  421. void
  422. CG_POINTER::GenFreeInline( CCB * pCCB )
  423. {
  424. CG_PARAM * pParam;
  425. CG_NDR * pNdr;
  426. BOOL fFree;
  427. if ( ShouldFreeOffline() || IsAllocateDontFree() )
  428. return;
  429. //
  430. // We use the buffer for these since they have to be [in] or [in,out].
  431. //
  432. if ( GetCGID() == ID_CG_STRING_PTR )
  433. return;
  434. fFree = FALSE;
  435. pParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
  436. pNdr = (CG_NDR *) GetChild();
  437. //
  438. // Skip past generic handle nodes.
  439. //
  440. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
  441. pNdr = (CG_NDR *) pNdr->GetChild();
  442. //
  443. // Check for handles.
  444. //
  445. if ( (pNdr->GetCGID() == ID_CG_CONTEXT_HDL) ||
  446. (pNdr->GetCGID() == ID_CG_PRIMITIVE_HDL) )
  447. return;
  448. //
  449. // Free a pointer to simple type only if it's a pointer to enum16.
  450. //
  451. if ( pNdr->IsSimpleType() )
  452. fFree = ( (pNdr->GetCGID() == ID_CG_ENUM) &&
  453. ! ((CG_ENUM *)pNdr)->IsEnumLong() );
  454. //
  455. // Out only pointer is freed if it wasn't allocated on the server's stack.
  456. // We overwrite any previous freeing descision.
  457. //
  458. if ( ! pParam->IsParamIn() )
  459. fFree = ShouldPointerFree();
  460. if ( fFree )
  461. {
  462. //
  463. // Always check if the pointer is not null before freeing.
  464. //
  465. Out_FreeParamInline( pCCB );
  466. }
  467. }
  468. void CG_SIZE_POINTER::GenNdrFormatPointee( CCB * pCCB )
  469. /*++
  470. Routine Description :
  471. Generates the format string description for the pointee of an
  472. sized pointer to anything.
  473. Since a sized pointer is really the same as a pointer to a conformant
  474. array in Ndr terms, we just create a CG_CONFORMANT_ARRAY class on the
  475. fly and tell it to generate it's code.
  476. Arguments :
  477. pCCB - pointer to the code control block.
  478. --*/
  479. {
  480. CG_CONFORMANT_ARRAY * pConformantArray;
  481. CG_QUALIFIED_POINTER * pOldSizePtr;
  482. if ( GetPointeeFormatStringOffset() != -1 )
  483. return;
  484. if ( IsMultiSize() )
  485. {
  486. CG_NDR * pChild = (CG_NDR *) GetChild();
  487. SetIsInMultiSized( TRUE );
  488. if ( (pChild->GetCGID() == ID_CG_SIZE_PTR) ||
  489. (pChild->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
  490. (pChild->GetCGID() == ID_CG_SIZE_STRING_PTR) )
  491. {
  492. ((CG_QUALIFIED_POINTER *)pChild)->SetIsInMultiSized( TRUE );
  493. ((CG_QUALIFIED_POINTER *)pChild)->SetDimension(GetDimension() + 1);
  494. }
  495. }
  496. pOldSizePtr = pCCB->GetCurrentSizePointer();
  497. pCCB->SetCurrentSizePointer( this );
  498. CG_NDR * pChild = (CG_NDR *) GetChild();
  499. pConformantArray = new CG_CONFORMANT_ARRAY( this );
  500. SetPointee( pConformantArray );
  501. pConformantArray->SetPtrType( PTR_REF );
  502. pConformantArray->SetChild( GetChild() );
  503. pConformantArray->SetIsInMultiDim( IsInMultiSized() );
  504. pConformantArray->SetFormatStringOffset( -1 );
  505. pConformantArray->GenNdrFormat( pCCB );
  506. SetPointeeFormatStringOffset( pConformantArray->GetFormatStringOffset() );
  507. pCCB->SetCurrentSizePointer( pOldSizePtr );
  508. }
  509. void CG_SIZE_LENGTH_POINTER::GenNdrFormatPointee( CCB * pCCB )
  510. /*++
  511. Routine Description :
  512. Generates the format string description for the pointee of a
  513. size-length pointer to anything.
  514. Since a size-length pointer is really the same as a pointer to a conformant
  515. varying array in Ndr terms, we just create a CG_CONFORMANT_VARYING_ARRAY
  516. class on the fly and tell it to generate it's code.
  517. Arguments :
  518. pCCB - pointer to the code control block.
  519. --*/
  520. {
  521. CG_CONFORMANT_VARYING_ARRAY * pConfVaryArray;
  522. CG_QUALIFIED_POINTER * pOldSizePtr;
  523. if ( GetPointeeFormatStringOffset() != -1 )
  524. return;
  525. if ( IsMultiSize() )
  526. {
  527. CG_NDR * pChild = (CG_NDR *) GetChild();
  528. SetIsInMultiSized( TRUE );
  529. if ( (pChild->GetCGID() == ID_CG_SIZE_PTR) ||
  530. (pChild->GetCGID() == ID_CG_SIZE_LENGTH_PTR) ||
  531. (pChild->GetCGID() == ID_CG_SIZE_STRING_PTR) )
  532. {
  533. ((CG_QUALIFIED_POINTER *)pChild)->SetIsInMultiSized( TRUE );
  534. ((CG_QUALIFIED_POINTER *)pChild)->SetDimension(GetDimension() + 1);
  535. }
  536. }
  537. pOldSizePtr = pCCB->GetCurrentSizePointer();
  538. pCCB->SetCurrentSizePointer( this );
  539. pConfVaryArray = new CG_CONFORMANT_VARYING_ARRAY( this );
  540. SetPointee( pConfVaryArray );
  541. pConfVaryArray->SetPtrType( PTR_REF );
  542. pConfVaryArray->SetChild( GetChild() );
  543. pConfVaryArray->SetIsInMultiDim( IsInMultiSized() );
  544. pConfVaryArray->SetFormatStringOffset( -1 );
  545. pConfVaryArray->GenNdrFormat( pCCB );
  546. SetPointeeFormatStringOffset( pConfVaryArray->GetFormatStringOffset() );
  547. pCCB->SetCurrentSizePointer( pOldSizePtr );
  548. }
  549. // --------------------------------------------------------------------------
  550. // Strings
  551. // --------------------------------------------------------------------------
  552. void
  553. CG_STRING_POINTER::GenNdrFormat( CCB * pCCB )
  554. /*++
  555. Routine Description :
  556. Generates the format string description for a string pointer.
  557. Arguments :
  558. pCCB - pointer to the code control block.
  559. --*/
  560. {
  561. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  562. unsigned short StartOffset = pFormatString->GetCurrentOffset();
  563. if ( GetFormatStringOffset() != -1 )
  564. return;
  565. SetFormatStringOffset( StartOffset );
  566. SetFormatStringEndOffset( StartOffset + 4 );
  567. GenNdrFormatAlways( pCCB );
  568. // here, we assume all pointers generate 4 bytes
  569. SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
  570. }
  571. void
  572. CG_STRING_POINTER::GenNdrFormatAlways( CCB * pCCB )
  573. /*++
  574. Routine Description :
  575. Generates the format string description for a string pointer.
  576. Arguments :
  577. pCCB - pointer to the code control block.
  578. --*/
  579. {
  580. GenNdrPointerType( pCCB );
  581. if ( IsStringableStruct() )
  582. {
  583. FORMAT_STRING * pFormatString;
  584. long Offset;
  585. pFormatString = pCCB->GetFormatString();
  586. //
  587. // For stringable struct's we must emit the offset to the pointee
  588. // description. Regular string pointers have the actual description
  589. // immediately following.
  590. //
  591. Offset = pFormatString->GetCurrentOffset();
  592. pFormatString->PushShortOffset( 0 );
  593. GenNdrFormatPointee( pCCB );
  594. pFormatString->PushShort( GetPointeeFormatStringOffset() - Offset,
  595. Offset );
  596. return;
  597. }
  598. GenNdrFormatPointee( pCCB );
  599. pCCB->GetFormatString()->PushFormatChar( FC_PAD );
  600. }
  601. void
  602. CG_STRING_POINTER::GenNdrFormatPointee( CCB * pCCB )
  603. /*++
  604. Routine Description :
  605. Generate the format string of the actual string type without the
  606. pointer attributes.
  607. Arguments :
  608. pCCB - pointer to the code control block.
  609. --*/
  610. {
  611. FORMAT_STRING * pFormatString;
  612. pFormatString = pCCB->GetFormatString();
  613. //
  614. // Check for stringable struct.
  615. //
  616. if ( IsStringableStruct() )
  617. {
  618. if ( GetPointeeFormatStringOffset() != -1 )
  619. return;
  620. SetPointeeFormatStringOffset( pFormatString->GetCurrentOffset() );
  621. pFormatString->PushFormatChar( FC_C_SSTRING );
  622. pFormatString->PushByte( ((CG_NDR *)GetChild())->GetWireSize() );
  623. return;
  624. }
  625. //
  626. // Always generate the format string. The description of a non-sized
  627. // string pointer is not shared.
  628. //
  629. switch ( ((CG_BASETYPE *)GetChild())->GetFormatChar() )
  630. {
  631. case FC_CHAR :
  632. case FC_BYTE :
  633. pFormatString->PushFormatChar( FC_C_CSTRING );
  634. break;
  635. case FC_WCHAR :
  636. pFormatString->PushFormatChar( FC_C_WSTRING );
  637. break;
  638. default :
  639. assert(0);
  640. }
  641. }
  642. void
  643. CG_SIZE_STRING_POINTER::GenNdrFormat( CCB * pCCB )
  644. /*++
  645. Routine Description :
  646. Generates the format string description for a sized string pointer.
  647. Arguments :
  648. pCCB - pointer to the code control block.
  649. --*/
  650. {
  651. FORMAT_STRING * pFormatString = pCCB->GetFormatString();
  652. unsigned short StartOffset = pFormatString->GetCurrentOffset();
  653. if ( GetFormatStringOffset() != -1 )
  654. return;
  655. SetFormatStringOffset( StartOffset );
  656. SetFormatStringEndOffset( StartOffset + 4 );
  657. GenNdrFormatAlways( pCCB );
  658. // here, we assume all pointers generate 4 bytes
  659. SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
  660. }
  661. void
  662. CG_SIZE_STRING_POINTER::GenNdrFormatAlways( CCB * pCCB )
  663. /*++
  664. Routine Description :
  665. Generates the format string description for a sized string pointer.
  666. Arguments :
  667. pCCB - pointer to the code control block.
  668. --*/
  669. {
  670. FORMAT_STRING * pFormatString;
  671. long Offset;
  672. pFormatString = pCCB->GetFormatString();
  673. GenNdrPointerType( pCCB );
  674. // Get the current offset.
  675. Offset = pFormatString->GetCurrentOffset();
  676. // Push a short for the offset to be filled in later.
  677. pFormatString->PushShortOffset( 0 );
  678. // Generate the pointee's format string.
  679. GenNdrFormatPointee( pCCB );
  680. // Now fill in the offset field correctly.
  681. pFormatString->PushShort( GetPointeeFormatStringOffset() - Offset,
  682. Offset );
  683. }
  684. void
  685. CG_SIZE_STRING_POINTER::GenNdrFormatPointee( CCB * pCCB )
  686. /*++
  687. Routine Description :
  688. Generate the format string of the actual string type without the
  689. pointer attributes.
  690. Arguments :
  691. pCCB - pointer to the code control block.
  692. --*/
  693. {
  694. FORMAT_STRING * pFormatString;
  695. CG_QUALIFIED_POINTER * pOldSizePtr;
  696. if ( GetPointeeFormatStringOffset() != -1 )
  697. return;
  698. pFormatString = pCCB->GetFormatString();
  699. SetPointeeFormatStringOffset( pFormatString->GetCurrentOffset() );
  700. pOldSizePtr = pCCB->GetCurrentSizePointer();
  701. pCCB->SetCurrentSizePointer( this );
  702. //
  703. // Check for stringable struct.
  704. //
  705. if ( IsStringableStruct() )
  706. {
  707. pFormatString->PushFormatChar( FC_C_SSTRING );
  708. pFormatString->PushByte( ((CG_NDR *)GetChild())->GetWireSize() );
  709. pFormatString->PushFormatChar( FC_STRING_SIZED );
  710. pFormatString->PushFormatChar( FC_PAD );
  711. GenFormatStringConformanceDescription( pCCB, TRUE, IsInMultiSized() );
  712. pCCB->SetCurrentSizePointer( pOldSizePtr );
  713. return;
  714. }
  715. switch ( ((CG_BASETYPE *)GetChild())->GetFormatChar() )
  716. {
  717. case FC_CHAR :
  718. case FC_BYTE :
  719. pFormatString->PushFormatChar( FC_C_CSTRING );
  720. break;
  721. case FC_WCHAR :
  722. pFormatString->PushFormatChar( FC_C_WSTRING );
  723. break;
  724. default :
  725. assert(0);
  726. }
  727. pFormatString->PushFormatChar( FC_STRING_SIZED );
  728. //
  729. // Set the IsPointer parameter to TRUE.
  730. //
  731. GenFormatStringConformanceDescription( pCCB, TRUE, IsInMultiSized() );
  732. pCCB->SetCurrentSizePointer( pOldSizePtr );
  733. }
  734. void
  735. CG_BYTE_COUNT_POINTER::GenNdrFormat( CCB * pCCB )
  736. /*++
  737. Routine Description :
  738. Generates the format string description for a byte count pointer.
  739. Arguments :
  740. pCCB - pointer to the code control block.
  741. --*/
  742. {
  743. CG_ITERATOR Iterator;
  744. FORMAT_STRING * pFormatString;
  745. CG_PROC * pProc;
  746. CG_PARAM * pParam;
  747. CG_NDR * pChild;
  748. if ( GetFormatStringOffset() != -1 )
  749. return;
  750. pFormatString = pCCB->GetFormatString();
  751. pChild = (CG_NDR *) GetChild();
  752. if ( ! pChild->IsSimpleType() )
  753. pChild->GenNdrFormat( pCCB );
  754. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  755. pFormatString->PushFormatChar( FC_BYTE_COUNT_POINTER );
  756. if ( pChild->IsSimpleType() )
  757. pChild->GenNdrFormat( pCCB );
  758. else
  759. pFormatString->PushFormatChar( FC_PAD );
  760. pProc = (CG_PROC *) pCCB->GetCGNodeContext();
  761. pProc->GetMembers( Iterator );
  762. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  763. if ( GetByteCountParam() == pParam->GetType() )
  764. break;
  765. assert( ((CG_NDR *)pParam->GetChild())->IsSimpleType() );
  766. CG_BASETYPE * pCount = (CG_BASETYPE *) pParam->GetChild();
  767. unsigned char Type;
  768. Type = (unsigned char) pCount->GetFormatChar();
  769. Type |= FC_TOP_LEVEL_CONFORMANCE;
  770. // Byte count description, just do it here.
  771. pFormatString->PushByte( Type );
  772. pFormatString->PushByte( 0 );
  773. pFormatString->PushShortStackOffset(
  774. (short) pParam->GetStackOffset( pCCB, I386_STACK_SIZING ),
  775. (short) pParam->GetStackOffset( pCCB, ALPHA_STACK_SIZING ),
  776. (short) pParam->GetStackOffset( pCCB, MIPS_STACK_SIZING ),
  777. (short) pParam->GetStackOffset( pCCB, PPC_STACK_SIZING ),
  778. (short) pParam->GetStackOffset( pCCB, MAC_STACK_SIZING ) );
  779. if ( ! pChild->IsSimpleType() )
  780. {
  781. pFormatString->PushShortOffset( pChild->GetFormatStringOffset() -
  782. pFormatString->GetCurrentOffset() );
  783. }
  784. }
  785. void
  786. CG_INTERFACE_POINTER::GenNdrFormat( CCB * pCCB )
  787. /*++
  788. Routine Description :
  789. Generates the format string description for an interface pointer.
  790. Arguments :
  791. pCCB - pointer to the code control block.
  792. --*/
  793. {
  794. FORMAT_STRING * pFormatString;
  795. node_interface * pInterface;
  796. node_guid * pGuid;
  797. char * p1;
  798. char * p2;
  799. char * p3;
  800. char * p4;
  801. char * p5;
  802. if ( GetFormatStringOffset() != -1 )
  803. return;
  804. pFormatString = pCCB->GetFormatString();
  805. SetFormatStringOffset( pFormatString->GetCurrentOffset() );
  806. //
  807. // There are two cases, the constant UUID and the [iid_is] expression.
  808. //
  809. // In the normal case, we will get the 16 byte UUID from the [uuid]
  810. // attribute on the interface node. The 16 byte UUID is written to the
  811. // format string. Note that the UUID in the format string is not aligned
  812. // in memory. The UUID must be copied to a local structure before being
  813. // used.
  814. //
  815. // Get the interface node.
  816. pFormatString->PushFormatChar( FC_IP );
  817. if ( GetIIDExpr() )
  818. {
  819. //
  820. // Interface pointer has [iid_is] applied to it.
  821. //
  822. pFormatString->PushFormatChar( FC_PAD );
  823. GenNdrFormatAttributeDescription( pCCB,
  824. 0,
  825. GetIIDExpr(),
  826. TRUE,
  827. FALSE,
  828. FALSE,
  829. FALSE );
  830. return;
  831. }
  832. //
  833. // Else handle a constant iid interface pointer.
  834. //
  835. pInterface = GetTheInterface();
  836. assert( pInterface->NodeKind() == NODE_INTERFACE );
  837. pFormatString->PushFormatChar( FC_CONSTANT_IID );
  838. // Get the [uuid] from the interface node.
  839. pGuid = (node_guid *)pInterface->GetAttribute( ATTR_GUID );
  840. assert( pGuid && "No UUID for interface pointer" );
  841. pGuid->GetStrs( &p1, &p2, &p3, &p4, &p5 );
  842. pFormatString->PushLong( StringToHex( p1 ) );
  843. pFormatString->PushShort( StringToHex( p2 ) );
  844. pFormatString->PushShort( StringToHex( p3 ) );
  845. char Buffer[20];
  846. char String[4];
  847. int i;
  848. strcpy( Buffer, p4 );
  849. strcat( Buffer, p5 );
  850. for ( i = 0; i < 16; i += 2 )
  851. {
  852. String[0] = Buffer[i];
  853. String[1] = Buffer[i+1];
  854. String[2] = '\0';
  855. pFormatString->PushByte( StringToHex( String ) );
  856. }
  857. SetFormatStringEndOffset( pFormatString->GetCurrentOffset() );
  858. SetFormatStringOffset( pFormatString->OptimizeFragment( this ) );
  859. }
  860. void
  861. CG_INTERFACE_POINTER::GenNdrFormatAlways( CCB * pCCB )
  862. {
  863. long OldOffset;
  864. OldOffset = GetFormatStringOffset();
  865. SetFormatStringOffset( -1 );
  866. GenNdrFormat( pCCB );
  867. SetFormatStringOffset( OldOffset );
  868. }
  869. void
  870. CG_POINTER::SetNextNdrAlignment( CCB * pCCB )
  871. {
  872. if ( GetPtrType() != PTR_REF )
  873. {
  874. pCCB->SetNdrAlignment( NDR_ALWC1 );
  875. return;
  876. }
  877. switch ( GetCGID() )
  878. {
  879. case ID_CG_PTR :
  880. pCCB->NdrAlignmentAction(
  881. ((CG_NDR *)GetChild())->GetWireAlignment() );
  882. ((CG_NDR *)GetChild())->SetNextNdrAlignment( pCCB );
  883. break;
  884. case ID_CG_SIZE_PTR :
  885. case ID_CG_LENGTH_PTR :
  886. case ID_CG_SIZE_LENGTH_PTR :
  887. pCCB->SetNdrAlignment( NDR_ALWC4 );
  888. pCCB->NdrAlignmentAction(
  889. ((CG_NDR *)GetChild())->GetWireAlignment() );
  890. ((CG_NDR *)GetChild())->SetNextNdrAlignment( pCCB );
  891. break;
  892. default :
  893. pCCB->SetNdrAlignment( NDR_ALWC1 );
  894. break;
  895. }
  896. }
  897. void
  898. CG_STRING_POINTER::SetNextNdrAlignment( CCB * pCCB )
  899. {
  900. CG_BASETYPE * pChild;
  901. if ( GetPtrType() != PTR_REF )
  902. {
  903. pCCB->SetNdrAlignment( NDR_ALWC1 );
  904. return;
  905. }
  906. if ( ((CG_NDR *)GetChild())->IsSimpleType() )
  907. {
  908. pChild = (CG_BASETYPE *) GetChild();
  909. pCCB->SetNdrAlignment( pChild->GetFormatChar( pCCB ) == FC_WCHAR ?
  910. NDR_ALWC2 : NDR_ALWC1 );
  911. }
  912. else
  913. {
  914. // Stringable struct - just give up.
  915. pCCB->SetNdrAlignment( NDR_ALWC1 );
  916. }
  917. }
  918. static long
  919. StringToHex( char * str )
  920. {
  921. long l;
  922. l = 0;
  923. for ( ; *str ; str++ )
  924. {
  925. l *= 16;
  926. if ( ('0' <= *str) && (*str <= '9') )
  927. {
  928. l += *str - '0';
  929. continue;
  930. }
  931. if ( ('a' <= *str) && (*str <= 'f') )
  932. {
  933. l += 10 + *str - 'a';
  934. continue;
  935. }
  936. if ( ('A' <= *str) && (*str <= 'F') )
  937. {
  938. l += 10 + *str - 'A';
  939. continue;
  940. }
  941. assert(0);
  942. }
  943. return l;
  944. }