title: Trouble with Marshal.PtrToStructure() and char arrays in structure DEVMODE
body: <p>I'm having an issue with using Marshal.PtrToStructure() to extract data out of a pointer to a structure of type DEVMODE. <a href="http://msdn.microsoft.com/en-us/library/dd183565%28v=vs.85%29.aspx" rel="noreferrer">Here</a> is a link to an MSDN entry on the DEVMODE structure.</p>
  
  <p>My C# implementation for this structure is as follows:</p>
  
  <pre><code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct DEVMODE
  {
      public const int CCHDEVICENAME = 32;
      public const int CCHFORMNAME = 32;
  
      public unsafe fixed char dmDeviceName [CCHDEVICENAME];
      public Int16 dmSpecVersion;
      public Int16 dmDriverVersion;
      public Int16 dmSize;
      public Int16 dmDriverExtra;
      public DM_FIELD_TYPE dmFields;
  
      public Int16 dmOrientation;
      public Int16 dmPaperSize;
      public Int16 dmPaperLength;
      public Int16 dmPaperWidth;
      public Int16 dmScale;
      public Int16 dmCopies;
      public Int16 dmDefaultSource;
      public Int16 dmPrintQuality;
  
      public POINTL dmPosition;
      public Int32 dmDisplayOrientation;
      public Int32 dmDisplayFixedOutput;
  
      public short dmColor;
      public short dmDuplex;
      public short dmYResolution;
      public short dmTTOption;
      public short dmCollate;
  
      public unsafe fixed char dmFormName [CCHFORMNAME];
      public Int16 dmLogPixels;
      public Int32 dmBitsPerPel;
      public Int32 dmPelsWidth;
      public Int32 dmPelsHeight;
      public Int32 dmDisplayFlags;
      public Int32 dmNup;
      public Int32 dmDisplayFrequency;
      public Int32 dmICMMethod;
      public Int32 dmICMIntent;
      public Int32 dmMediaType;
      public Int32 dmDitherType;
      public Int32 dmReserved1;
      public Int32 dmReserved2;
      public Int32 dmPanningWidth;
      public Int32 dmPanningHeight;
  
      public DEVMODE(byte[] data)
      {
          unsafe
          {
              fixed (byte* packet = &amp;data[0])
              {
                  this = *(DEVMODE*)packet;
              }
          }
      }
  
  }
  
  [Flags()]
  public enum DM_FIELD_TYPE : int
  {
      /* field selection bits */
      DM_ORIENTATION          = 0x00000001,
      DM_PAPERSIZE            = 0x00000002,
      DM_PAPERLENGTH          = 0x00000004,
      DM_PAPERWIDTH           = 0x00000008,
      DM_SCALE                = 0x00000010,
      DM_POSITION             = 0x00000020,
      DM_NUP                  = 0x00000040,
      DM_DISPLAYORIENTATION   = 0x00000080,
      DM_COPIES               = 0x00000100,
      DM_DEFAULTSOURCE        = 0x00000200,
      DM_PRINTQUALITY         = 0x00000400,
      DM_COLOR                = 0x00000800,
      DM_DUPLEX               = 0x00001000,
      DM_YRESOLUTION          = 0x00002000,
      DM_TTOPTION             = 0x00004000,
      DM_COLLATE              = 0x00008000,
      DM_FORMNAME             = 0x00010000,
      DM_LOGPIXELS            = 0x00020000,
      DM_BITSPERPEL           = 0x00040000,
      DM_PELSWIDTH            = 0x00080000,
      DM_PELSHEIGHT           = 0x00100000,
      DM_DISPLAYFLAGS         = 0x00200000,
      DM_DISPLAYFREQUENCY     = 0x00400000,
      DM_ICMMETHOD            = 0x00800000,
      DM_ICMINTENT            = 0x01000000,
      DM_MEDIATYPE            = 0x02000000,
      DM_DITHERTYPE           = 0x04000000,
      DM_PANNINGWIDTH         = 0x08000000,
      DM_PANNINGHEIGHT        = 0x10000000,
      DM_DISPLAYFIXEDOUTPUT   = 0x20000000
  }
  
  public struct POINTL
  {
      public Int32 x;
      public Int32 y;
  }
  </code></pre>
  
  <p>In this structure there are 2 character arrays "dmDeviceName" and "dmFormName".  Both are 32 characters long. The problem is, when I attempt to marshal out the structure DEVMODE from a pointer, those character arrays are not being filled properly.  For example, dmDeviceName will only have the first character of the actual device name.  The rest of the array entries will be just '\0'. The line of code I'm that is doing the marshaling is as follows:</p>
  
  <pre><code>DEVMODE devMode = (DEVMODE)Marshal.PtrToStructure(aData[i].NotifyData.Data.pBuf, typeof(DEVMODE));
  </code></pre>
  
  <p>"aData[i].NotifyData.Data.pBuf" is a valid pointer to a structure of type DEVMODE.  I know this for 2 reasons.</p>
  
  <ol>
  <li><p>This structure is a subset of information returned from a printer driver call named FindNextPrinterChangeNotification().  I use this to capture print job information, and when I capture a print job and use the above code to marshal out the DEVMODE object, the "dmCopies" field is always exactly correct with the number of copies that were printed in that job.  So its a bit strange how the 12th member in a structure is getting marshaled correctly when some of the ones before it appear to not be.</p></li>
  <li><p>I used Marshal.ReadByte() to forcibly read the first 100 bytes that aData[i].NotifyData.Data.pBuf was pointing to, and sure enough, the first collection of bytes were the full exact name of the printer device.  So I know the information is there. </p></li>
  </ol>
  
  <p>For whatever reason, when I use Marshal.PtrToStructure() it doesn't seem to be able to correctly fill the character arrays.  I'm pretty sure most of the other variables are correct, but I have my doubts because of the array issue.  Does anyone know whats going on here.</p>
  
  <p>--EDIT --
  As requested, here is the code that populates the aData[] array:</p>
  
  <pre><code>private PRINTER_NOTIFY_INFO_DATA[] MarshalOutPrinterNotifyInfoDataArray(IntPtr ppPrinterNotifyInfo)
  {
      //Dereferencing ppPrinterNotifyInfo and setting NotifyInfoStruct to it.
      PRINTER_NOTIFY_INFO NotifyInfoStruct = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(ppPrinterNotifyInfo, typeof(PRINTER_NOTIFY_INFO));
  
      //Creating a point to point to the PRINTER_NOTIFY_INFO and then moving it to the end of the structure where the
      //aData[] member would begin.
      int paData = (int)ppPrinterNotifyInfo + Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO));
  
      //Creating an array to hold all the elements of our aData array.
      PRINTER_NOTIFY_INFO_DATA[] data = new PRINTER_NOTIFY_INFO_DATA[NotifyInfoStruct.Count];
  
      //looping through all the PRINTER_NOTIFY_INFO_DATA elments in the aData member and adding them to our local array.
      for (uint i = 0; i &lt; NotifyInfoStruct.Count; i++)
      {
          //extracting out a single PRINTER_NOTIFY_INFO_DATA item and storing it in our local array
          data[i] = (PRINTER_NOTIFY_INFO_DATA)Marshal.PtrToStructure((IntPtr)paData, typeof(PRINTER_NOTIFY_INFO_DATA));
  
          //moving our pointer to the next PRINTER_NOTIFY_INFO_DATA item
          paData += Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO_DATA));
      }
  
      return data;
  }
  
  
  
  private void SomeRoutine()
  {
      //////////////////
      /// some code here
      //////////////////
  
      //retrieving information about the most recent change notification for a change notification object associated with the printer
      FindNextPrinterChangeNotification(m_ManualResetEvent.SafeWaitHandle.DangerousGetHandle(), out pdwChangeFlags, null, out ppPrinterNotifyInfo);
  
      //Need to extract our PRINTER_NOTIFY_INFO_DATA array out of the PRINTER_NOTIFY_INFO structure
      PRINTER_NOTIFY_INFO_DATA[] aData = MarshalOutPrinterNotifyInfoDataArray(ppPrinterNotifyInfo);
  
      //////////////////
      /// some code here
      //////////////////
  }
  </code></pre>