0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SHFILEOPSTRUCT構造体はx86プラットフォームだと30バイト

Last updated at Posted at 2020-01-03

タイトルだけだとなんのコッチャですが。

P/Invokeでやりがちな誤り

C#などでP/Invokeの定義を記述すると下記のように書いてしまいたくなりますが、__x86プラットフォームでは32バイトになり誤り__です。(こちらから引用)

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SHFILEOPSTRUCT
{
    public IntPtr hwnd;
    [MarshalAs(UnmanagedType.U4)]
    public int wFunc;
    public string pFrom;
    public string pTo;
    public short fFlags;
    [MarshalAs(UnmanagedType.Bool)]
    public bool fAnyOperationsAborted;
    public IntPtr hNameMappings;
    public string lpszProgressTitle;
}

ネイティブの定義

SHFileOperation関数で使用するSHFILEOPSTRUCT構造体は、shellapi.hで下記のように定義されています。

typedef WORD FILEOP_FLAGS;

...

typedef struct _SHFILEOPSTRUCTA
{
    HWND            hwnd;
    UINT            wFunc;
    PCZZSTR         pFrom;
    PCZZSTR         pTo;
    FILEOP_FLAGS    fFlags;
    BOOL            fAnyOperationsAborted;
    LPVOID          hNameMappings;
    PCSTR           lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
} SHFILEOPSTRUCTA, *LPSHFILEOPSTRUCTA;
typedef struct _SHFILEOPSTRUCTW
{
    HWND            hwnd;
    UINT            wFunc;
    PCZZWSTR        pFrom;
    PCZZWSTR        pTo;
    FILEOP_FLAGS    fFlags;
    BOOL            fAnyOperationsAborted;
    LPVOID          hNameMappings;
    PCWSTR          lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
} SHFILEOPSTRUCTW, *LPSHFILEOPSTRUCTW;

fFlags以外は、ポインターかintになっているのがポイントです。

shellapi.hの先頭でpshpack1.hをincludeしているため、パッキングアラインメントが1バイトになりfFlagsより後は4バイト境界には配置されず、x86プラットフォームだと30バイトになります。

# if !defined(_WIN64)
# include <pshpack1.h>
# endif
...

前述のP/Invokeの定義では32バイトになるため、誤りということになります。
(fFlagsより後を使用しなければ、実害はないと思います。)

対応方法

pinvoke.netに記載がある通り、Pack=1を設定したx86用と、Packを設定しないx64用を2つ定義し、プラットフォームを判別して使い分ける必要があります。

実装としてはdotnet/runtimeあたりを見れば参考になるでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?