Nigel Thomas 35 Posted 6 hours ago This is the Delphi 12.1 (and as far back as 10.1 at least, but not in D2007) definition of ShellExecuteInfoW (the A version has the same issue): _SHELLEXECUTEINFOW = record cbSize: DWORD; fMask: ULONG; Wnd: HWND; lpVerb: LPCWSTR; lpFile: LPCWSTR; lpParameters: LPCWSTR; lpDirectory: LPCWSTR; nShow: Integer; hInstApp: HINST; { Optional fields } lpIDList: Pointer; lpClass: LPCWSTR; hkeyClass: HKEY; dwHotKey: DWORD; case Integer of 0: ( hIcon: THandle); 1: ( hMonitor: THandle; hProcess: THandle;); end; According to the definition in MSDN, the hProcess Handle is not part of the union: typedef struct _SHELLEXECUTEINFOW { DWORD cbSize; ULONG fMask; HWND hwnd; LPCWSTR lpVerb; LPCWSTR lpFile; LPCWSTR lpParameters; LPCWSTR lpDirectory; int nShow; HINSTANCE hInstApp; void *lpIDList; LPCWSTR lpClass; HKEY hkeyClass; DWORD dwHotKey; union { HANDLE hIcon; HANDLE hMonitor; } DUMMYUNIONNAME; HANDLE hProcess; } SHELLEXECUTEINFOW, *LPSHELLEXECUTEINFOW; Does that mean that the Delphi translation is faulty? Share this post Link to post
Anders Melander 1748 Posted 6 hours ago (edited) 44 minutes ago, Nigel Thomas said: Does that mean that the Delphi translation is faulty? No. In Delphi the variant part has to be the last in the record and, if you think about it, the hProcess field would have the same offset even if it was possible to declare it after the variant part. https://docwiki.embarcadero.com/RADStudio/Athens/en/Structured_Types_(Delphi)#Variant_Parts_in_Records Quote The variant part must follow the other fields in the record declaration. Edited 6 hours ago by Anders Melander 1 Share this post Link to post
Remy Lebeau 1349 Posted 4 hours ago (edited) 2 hours ago, Nigel Thomas said: Does that mean that the Delphi translation is faulty? Technically, no. The layout is fine. But, if they had done the "politically correct" thing by extracting the union into a separate type, eg: _SHELLEXECUTEINFOW_Union = record case Integer of 0: (hIcon: THandle); 1: (hMonitor: THandle); end; _SHELLEXECUTEINFOW = record cbSize: DWORD; fMask: ULONG; Wnd: HWND; lpVerb: LPCWSTR; lpFile: LPCWSTR; lpParameters: LPCWSTR; lpDirectory: LPCWSTR; nShow: Integer; hInstApp: HINST; { Optional fields } lpIDList: Pointer; lpClass: LPCWSTR; hkeyClass: HKEY; dwHotKey: DWORD; u: _SHELLEXECUTEINFOW_Union; // DUMMYUNIONNAME maps to 'u' for C/C++ hProcess: THandle; // compilers that don't support nameless unions... end; Then referencing the hIcon and hMonitor handles would have to be done as SHELLEXECUTEINFO.u.hIcon instead of as SHELLEXECUTEINFO.hIcon, etc. The variant part keeps the syntax a little cleaner. Edited 4 hours ago by Remy Lebeau 1 Share this post Link to post