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.

1404 lines
34 KiB

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