AccessViolationException when try to read memory from pointer in C# using Marshal class
<p>I try to create a program that will programatically set Windows Color Management to archive an effect like f.lux as a hobby project.</p>

<p>**The definition of WINAPI <code>WcsGetDefaultColorProfileSize</code>. **</p>

<pre><code>BOOL WINAPI WcsGetDefaultColorProfileSize(
  _In_      WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
  _In_opt_  PCWSTR pDeviceName,
  _In_      COLORPROFILETYPE cptColorProfileType,
  _In_      COLORPROFILESUBTYPE cpstColorProfileSubType,
  _In_      DWORD dwProfileID,
  _Out_     PDWORD pcbProfileName
);
</code></pre>

<p>**This is the signature of managed <code>WcsGetDefaultColorProfileSize</code>. **</p>

<pre><code>[DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfileSize", CharSet = CharSet.Unicode)]
private static extern bool GetDefaultColorProfileSize(
  WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
  [MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName,
  COLORPROFILETYPE cptColorProfileType,
  COLORPROFILESUBTYPE cpstColorProfileSubType,
  Int32 dwProfileID,
  out IntPtr pcbProfileSize
);
</code></pre>

<p><strong>The problem is when I try to get the string which is return as a pointer from WINAPI using Marshal class. Like this</strong></p>

<pre><code>// Need to get the size of ICC profile file first
GetDefaultColorProfileSize(
WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, 
monitor_name.DeviceKey, 
COLORPROFILETYPE.CPT_ICC, 
COLORPROFILESUBTYPE.CPST_RGB_WORKING_SPACE, 
1,
out SizePointer);
System.Diagnostics.Debug.WriteLine("Size is " + Marshal.ReadInt32(SizePointer));
</code></pre>

<p>the <code>GetDefaultColorProfileSize</code> return <code>TRUE</code> but when I try to access the address it return (It return this address 0x0000003e) using <code>Marshal.ReadInt32</code>
It throw this error </p>

<blockquote>
  <p>System.AccessViolationException Attempted to read or write protected memory. This is often an indication that other memory is corrupt.</p>
</blockquote>

<p>How can I able to read the memory at that pointer?</p>

<p>I try to allocate the memory first as suggesting by <strong>nvoigt</strong> </p>

<p>Changing from <code>IntPtr SizePointer</code> to <code>IntPtr SizePointer = Marshal.AllocHGlobal(4);</code></p>

<p>But it  still throw the same exception</p>

<h2>The full code is below here.</h2>

<h3>Enumnerate Display Devices</h3>

<pre><code>    [DllImport("User32.dll")]
    private static extern bool EnumDisplayDevices(
        string lpDevice, int iDevNum,
        ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);

    [StructLayout(LayoutKind.Sequential)]
    public struct DISPLAY_DEVICE
    {
        public int cb;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string DeviceName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceString;
        public int StateFlags;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceID;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string DeviceKey;

        public DISPLAY_DEVICE(int flags) {
            cb = 0;
            StateFlags = flags;
            DeviceName = new string((char)32, 32);
            DeviceString = new string((char)32, 128);
            DeviceID = new string((char)32, 128);
            DeviceKey = new string((char)32, 128);
            cb = Marshal.SizeOf(this);
        }
    }
</code></pre>

<h3>Window Color System</h3>

<pre><code>    enum WCS_PROFILE_MANAGEMENT_SCOPE
    {
        WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE = 0,
        WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER
    }

    enum COLORPROFILETYPE
    {
        CPT_ICC = 0x0001,
        CPT_DMP,
        CPT_CAMP,
        CPT_GMMP
    }

    enum COLORPROFILESUBTYPE
    {
        CPST_NONE = 0x0000,
        CPST_RGB_WORKING_SPACE = 0x0001,
        CPST_PERCEPTUAL = 0x0002,
        CPST_ABSOLUTE_COLORIMETRIC = 0x0004,
        CPST_RELATIVE_COLORIMETRIC = 0x0008,
        CPST_SATURATION = 0x0010,
        CPST_CUSTOM_WORKING_SPACE = 0x0020
    }
    [DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfileSize", CharSet = CharSet.Unicode)]
    private static extern bool GetDefaultColorProfileSize(
      WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
      [MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName,
      COLORPROFILETYPE cptColorProfileType,
      COLORPROFILESUBTYPE cpstColorProfileSubType,
      Int32 dwProfileID,
      out IntPtr pcbProfileSize
    );
    [DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfile" , CharSet =CharSet.Unicode, SetLastError =true)]
    private unsafe static extern bool GetDefaultColorProfile(WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
         [MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName,
          COLORPROFILETYPE cptColorProfileType,
          COLORPROFILESUBTYPE cpstColorProfileSubType,
          Int32 dwProfileID,
          Int32 cbProfileName,
          out IntPtr pProfileName);

    [DllImport("Mscms.dll", EntryPoint = "WcsSetUsePerUserProfiles", CharSet = CharSet.Unicode)]
    private static extern bool SetUsePerUserProfiles([MarshalAs(UnmanagedType.LPWStr), In]string pDeviceName, Int32 dwDeviceClass, bool usePerUserProfiles);
    [DllImport("Mscms.dll", EntryPoint = "WcsGetUsePerUserProfiles", CharSet = CharSet.Unicode)]
    private static extern bool GetUsePerUserProfiles([MarshalAs(UnmanagedType.LPWStr), In]string pDeviceName, Int32 dwDeviceClass, out bool pUsePerUserProfiles);
</code></pre>

<h2>The Actual Code</h2>

<pre><code>    public unsafe static void GetProfile() {
        DISPLAY_DEVICE lpDisplayDevice = new DISPLAY_DEVICE(0);     // OUT
        DISPLAY_DEVICE monitor_name = new DISPLAY_DEVICE(0);        // OUT

        int devNum = 0;
        while (EnumDisplayDevices(null, devNum, ref lpDisplayDevice, 0)) {
            int devNum2 = 0;
            while (EnumDisplayDevices(lpDisplayDevice.DeviceName, devNum2, ref monitor_name, 0)) {
              IntPtr SizePointer;
              // Need to get the size of ICC profile file first
                GetDefaultColorProfileSize(
  WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, 
                    monitor_name.DeviceKey, 
                    COLORPROFILETYPE.CPT_ICC, 
                    COLORPROFILESUBTYPE.CPST_RGB_WORKING_SPACE, 
                    1,
                    out SizePointer);
              System.Diagnostics.Debug.WriteLine("Size is " + Marshal.ReadInt32(SizePointer));
            // Try to get a location of ICC profile file.
             // Not Implement Yet
                break;
            }
            break;
        }
    }
</code></pre>