How to make this project work on x64 OS?

Oct 20, 2008 at 7:57 AM
Hi, I downloaded the project and compiled on my x64 Win 2008, whenever I click "Directory Object Picker", the application crashs, however, it can work well on x86 OS, so this is a compatibility issue, but I don't know to fix it, can you help me?

   // The block of code below always gets crash when running.
            for (int index = 0; index < scopeInitInfo.Length; index++)
            {
                 Marshal.StructureToPtr(scopeInitInfo[index], (IntPtr)((int)refScopeInitInfo + index * Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO))), true);
            }

Feb 5, 2009 at 10:31 PM
Edited Feb 5, 2009 at 10:33 PM
Hello,

In the call to Marshal.StructureToPtr(..., ..., ...) you need to set the last parameter to false, since the call before this alloc'ed the memory.

"If the fDeleteOld parameter is true, the buffer originally pointed to by ptr is deleted with the appropriate delete API on the embedded pointer, but the buffer must contain valid data."

I was seeing this call fail in Windows 2003 Server SP2 randomly because of this.

Heres the link to the MSDN article

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.structuretoptr(VS.80).aspx

Best,

Andrew





Feb 22, 2009 at 3:18 AM
I was getting crashes after the dialog closes.  I think the call to DestroyStructure in the post processing loop is wrong.  The structure in question is a managed object, not something being allocated in the marshaller.  I think the only deletion needed ought to be to free the HGLOBAL at the end after unlocking it.

Anyway I got rid of the destroy and added the hglobal free, now I'm working fine on x64.
Feb 25, 2009 at 12:19 PM
This is now working for me on x64 as well.  Thank you ferrix and starchenzhi..  To get real specific and easy, the changes are:

1.  In Initialize(), change the last parameter to false:
Marshal.StructureToPtr(scopeInitInfo[index],
                    (IntPtr)((int)refScopeInitInfo + index * Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO))),
                    false);

2.  In ProcessSelections():
   a.  Comment out //Marshal.DestroyStructure(current, typeof(DS_SELECTION));
   b.  Add the following as the last line in the finally section:  Marshal.FreeHGlobal(stg.hGlobal);
Aug 10, 2009 at 4:18 PM

Thanks sbailey, following these steps fixed the same issue I was having in a 32 bit Windows 2008 environment.

Sep 4, 2009 at 1:26 PM

Also in the ProcessSelection method you should free the data retrieved by the GetData method.

 

finally
{
PInvoke.GlobalUnlock(pDsSL);
PInvoke.ReleaseStgMedium(ref stg); <
}

 

 

The ReleaseStgMedium metod in Ole32.dll is designed to release the STGMEDIUM returned by the GetData method.

[DllImport("Ole32.dll")]
        public static extern void ReleaseStgMedium(ref STGMEDIUM pMedium);

Mar 6, 2013 at 6:25 AM
When running on 64 bit Windows and receiving memory address beyond the capability of int, then these lines fails:
Marshal.StructureToPtr(scopeInitInfo[index],
                    (IntPtr)((int)refScopeInitInfo + index * Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO))),
                    true);
...
current = (IntPtr)((int)current + (Marshal.SizeOf(typeof(uint))*2));
...
current = (IntPtr)((int)current + Marshal.SizeOf(typeof(DS_SELECTION)));
On .NET 4.0 then one can just do addition to IntPtr without needing to cast to int, but if using .NET 2.0/3.5 then one needs to do this:
Marshal.StructureToPtr(scopeInitInfo[index],
                    new IntPtr(refScopeInitInfo.ToInt64() + index * Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO))),
                    true);
...
current = new IntPtr(current.ToInt64() + Marshal.SizeOf(typeof(uint))*2);
...
current = new IntPtr(current.ToInt64() + Marshal.SizeOf(typeof(DS_SELECTION)));
Mar 9, 2013 at 6:54 PM
Throws error in ProcessSelections at this line:
Marshal.DestroyStructure(current, typeof(DS_SELECTION));
Tried all the changes listed:
  • In Initialize(), change the last parameter to false:
    Marshal.StructureToPtr(scopeInitInfo[index],    
                new IntPtr(refScopeInitInfo.ToInt64() + index * Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO))),  
                true);
  • In ProcessSelections():
    a: Comment out //Marshal.DestroyStructure(current, typeof(DS_SELECTION));
    b: Add the following as the last line in the finally section:
Marshal.FreeHGlobal(stg.hGlobal);
  • The ProcessSelection method you should free the data retrieved by the GetData method:
finally
{
    PInvoke.GlobalUnlock(pDsSL);
    PInvoke.ReleaseStgMedium(ref stg);
}
  • On .NET 4.0 then one can just do addition to IntPtr without needing to cast to int, but if using .NET 2.0/3.5 then one needs to do this:
current = new IntPtr(current.ToInt64() + Marshal.SizeOf(typeof(uint))*2);
current = new IntPtr(current.ToInt64() + Marshal.SizeOf(typeof(DS_SELECTION)));