The Labs \ Source Viewer \ SSCLI \ System \ ArgIterator

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System
  16. {
  17.    
  18.     using System;
  19.     using System.Runtime.InteropServices;
  20.     using System.Runtime.CompilerServices;
  21.    
  22.     // This class will not be marked serializable
  23.    
  24.     [StructLayout(LayoutKind.Auto)]
  25.     public struct ArgIterator
  26.     {
  27.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  28.         private extern ArgIterator(IntPtr arglist);
  29.        
  30.         // create an arg iterator that points at the first argument that
  31.         // is not statically declared (that is the first ... arg)
  32.         // 'arglist' is the value returned by the ARGLIST instruction
  33.        
  34.         public ArgIterator(RuntimeArgumentHandle arglist) : this(arglist.Value)
  35.         {
  36.         }
  37.        
  38.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  39.         unsafe private extern ArgIterator(IntPtr arglist, void* ptr);
  40.        
  41.         // create an arg iterator that points just past 'firstArg'.
  42.         // 'arglist' is the value returned by the ARGLIST instruction
  43.         // This is much like the C va_start macro
  44.        
  45.         [CLSCompliant(false)]
  46.        
  47.        
  48.         unsafe public ArgIterator(RuntimeArgumentHandle arglist, void* ptr) : this(arglist.Value, ptr)
  49.         {
  50.         }
  51.        
  52.         // Fetch an argument as a typed referece, advance the iterator.
  53.         // Throws an exception if past end of argument list
  54.         [CLSCompliant(false)]
  55.         public TypedReference GetNextArg()
  56.         {
  57.             TypedReference result = new TypedReference();
  58.             // reference to TypedReference is banned, so have to pass result as pointer
  59.             unsafe {
  60.                 FCallGetNextArg(&result);
  61.             }
  62.             return result;
  63.         }
  64.        
  65.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  66.         // reference to TypedReference is banned, so have to pass result as void pointer
  67.         unsafe private extern void FCallGetNextArg(void* result);
  68.        
  69.         // Alternate version of GetNextArg() intended primarily for IJW code
  70.         // generated by VC's "va_arg()" construct.
  71.         [CLSCompliant(false)]
  72.         public TypedReference GetNextArg(RuntimeTypeHandle rth)
  73.         {
  74.             if (sigPtr != IntPtr.Zero) {
  75.                 // This is an ordinary ArgIterator capable of determining
  76.                 // types from a signature. Just do a regular GetNextArg.
  77.                 return GetNextArg();
  78.             }
  79.             else {
  80.                 // Prevent abuse of this API with a default ArgIterator (it
  81.                 // doesn't require permission to create a zero-inited value
  82.                 // type). Check that ArgPtr isn't zero or this API will allow a
  83.                 // malicious caller to increment the pointer to an arbitrary
  84.                 // location in memory and read the contents.
  85.                 if (ArgPtr == IntPtr.Zero)
  86.                     throw new ArgumentNullException();
  87.                
  88.                 TypedReference result = new TypedReference();
  89.                 // reference to TypedReference is banned, so have to pass result as pointer
  90.                 unsafe {
  91.                     InternalGetNextArg(&result, rth);
  92.                 }
  93.                 return result;
  94.             }
  95.         }
  96.        
  97.        
  98.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  99.         // reference to TypedReference is banned, so have to pass result as void pointer
  100.         unsafe private extern void InternalGetNextArg(void* result, RuntimeTypeHandle rth);
  101.        
  102.         // This method should invalidate the iterator (va_end). It is not supported yet.
  103.         public void End()
  104.         {
  105.         }
  106.        
  107.         // How many arguments are left in the list
  108.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  109.         public extern int GetRemainingCount();
  110.        
  111.         // Gets the type of the current arg, does NOT advance the iterator
  112.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  113.         unsafe private extern void* _GetNextArgType();
  114.        
  115.         unsafe public RuntimeTypeHandle GetNextArgType()
  116.         {
  117.             return new RuntimeTypeHandle(_GetNextArgType());
  118.         }
  119.        
  120.         public override int GetHashCode()
  121.         {
  122.             return unchecked((int)((long)ArgCookie));
  123.         }
  124.        
  125.         // Inherited from object
  126.         public override bool Equals(object o)
  127.         {
  128.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI"));
  129.         }
  130.        
  131.         private IntPtr ArgCookie;
  132.         // Cookie from the EE.
  133.         // The SigPtr structure consists of the following members
  134.         private IntPtr sigPtr;
  135.         // Pointer to remaining signature.
  136.         private IntPtr sigPtrLen;
  137.         // Remaining length of the pointer
  138.         // Note, sigPtrLen is actually a DWORD, but on 64bit systems this structure becomes
  139.         // 8-byte aligned, which requires us to pad it.
  140.        
  141.         private IntPtr ArgPtr;
  142.         // Pointer to remaining args.
  143.         private int RemainingArgs;
  144.         // # of remaining args.
  145.     }
  146. }

Developer Fusion