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.

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