ただ、バグかも知れないのですが、そのままでは変なアドレスが返ってきました。これは SHFILEOPSTRUCT 構造体の StructLayout 属性に Pack = 2 を記述することで回避できます。

ということで、私もちょっとハマりましたが、以下のコードで動作させることができましたので、構造体の定義も合わせて載せておきます。(定数の定義は省略してあります)

[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public int wFunc;
[MarshalAs(UnmanagedType.LPWStr)]
public string pFrom;
[MarshalAs(UnmanagedType.LPWStr)]
public string pTo;
public ushort fFlags;
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszProgressTitle;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct SHNAMEMAPPING
{
[MarshalAs(UnmanagedType.LPWStr)]
public string pszOldPath;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszNewPath;
public int cchOldPath;
public int cchNewPath;
}

[StructLayout(LayoutKind.Sequential)]
struct HANDLETOMAPPINGS
{
public uint uNumberOfMappings;
public IntPtr lpSHNameMapping;
}

[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);

[DllImport("shell32.dll")]
static extern void SHFreeNameMappings(IntPtr hNameMappings);

private void Form1_Load(object sender, EventArgs e)
{
}

private void button1_Click(object sender, EventArgs e)
{
SHFILEOPSTRUCT sh;
sh.hwnd = IntPtr.Zero;
sh.wFunc = FO_MOVE;
sh.pFrom = @"D:\aaa" + '\0' + '\0';
sh.fFlags = FOF_ALLOWUNDO | FOF_RENAMEONCOLLISION | FOF_MULTIDESTFILES | FOF_WANTMAPPINGHANDLE;
sh.fAnyOperationsAborted = false;
sh.hNameMappings = IntPtr.Zero;
sh.lpszProgressTitle = null;
sh.pTo = @"D:\bbb\" + '\0' + '\0';

int ret = SHFileOperation(ref sh);

if (!sh.fAnyOperationsAborted)
{
if (sh.hNameMappings != IntPtr.Zero)
{
// sh.hNameMappings から HANDLETOMAPPINGS にコピー
HANDLETOMAPPINGS mappings = (HANDLETOMAPPINGS)Marshal.PtrToStructure(sh.hNameMappings, typeof(HANDLETOMAPPINGS));

// mappings.lpSHNameMapping の位置で読み取り用ポインタを初期化
IntPtr ptr = mappings.lpSHNameMapping;
for (int i = 0; i < (int)mappings.uNumberOfMappings; i++)
{
// 読み取り用ポインタから SHNAMEMAPPING にコピー
SHNAMEMAPPING mapping = (SHNAMEMAPPING)Marshal.PtrToStructure(ptr, typeof(SHNAMEMAPPING));

// FileInfo 作成
FileInfo fileNew = new FileInfo(mapping.pszNewPath);

// ここで必要に応じて処理

// 次の要素を読み込むため、ポインタをSHNAMEMAPPING構造体のサイズ分進める
ptr = new IntPtr(ptr.ToInt32() + Marshal.SizeOf(typeof(SHNAMEMAPPING)));
}

SHFreeNameMappings(sh.hNameMappings);
}
}
}