Fix packing bug in shlobj.h.
Fix the declaration of bitfields so their layout matches what MSVC generates. Modify winapi_test to compute the bitfields size/alignment like MSVC does. Update the impacted generated.c files.
This commit is contained in:
parent
4133ed17d9
commit
09747e50e7
|
@ -760,13 +760,13 @@ static void test_pack_SHNAMEMAPPINGW(void)
|
|||
|
||||
static void test_pack_AUTO_SCROLL_DATA(void)
|
||||
{
|
||||
/* AUTO_SCROLL_DATA (pack 4) */
|
||||
TEST_TYPE(AUTO_SCROLL_DATA, 48, 4);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, int, iNextSample, 0, 4, 4);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, DWORD, dwLastScroll, 4, 4, 4);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, BOOL, bFull, 8, 4, 4);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, POINT[NUM_POINTS], pts, 12, 24, 4);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, DWORD[NUM_POINTS], dwTimes, 36, 12, 4);
|
||||
/* AUTO_SCROLL_DATA (pack 1) */
|
||||
TEST_TYPE(AUTO_SCROLL_DATA, 48, 1);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, int, iNextSample, 0, 4, 1);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, DWORD, dwLastScroll, 4, 4, 1);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, BOOL, bFull, 8, 4, 1);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, POINT[NUM_POINTS], pts, 12, 24, 1);
|
||||
TEST_FIELD(AUTO_SCROLL_DATA, DWORD[NUM_POINTS], dwTimes, 36, 12, 1);
|
||||
}
|
||||
|
||||
static void test_pack_BFFCALLBACK(void)
|
||||
|
@ -778,10 +778,10 @@ static void test_pack_BFFCALLBACK(void)
|
|||
static void test_pack_CABINETSTATE(void)
|
||||
{
|
||||
/* CABINETSTATE (pack 1) */
|
||||
TEST_TYPE(CABINETSTATE, 10, 1);
|
||||
TEST_TYPE(CABINETSTATE, 12, 1);
|
||||
TEST_FIELD(CABINETSTATE, WORD, cLength, 0, 2, 1);
|
||||
TEST_FIELD(CABINETSTATE, WORD, nVersion, 2, 2, 1);
|
||||
TEST_FIELD(CABINETSTATE, UINT, fMenuEnumFilter, 6, 4, 1);
|
||||
TEST_FIELD(CABINETSTATE, UINT, fMenuEnumFilter, 8, 4, 1);
|
||||
}
|
||||
|
||||
static void test_pack_CIDA(void)
|
||||
|
@ -876,7 +876,7 @@ static void test_pack_LPCABINETSTATE(void)
|
|||
{
|
||||
/* LPCABINETSTATE */
|
||||
TEST_TYPE(LPCABINETSTATE, 4, 4);
|
||||
TEST_TYPE_POINTER(LPCABINETSTATE, 10, 1);
|
||||
TEST_TYPE_POINTER(LPCABINETSTATE, 12, 1);
|
||||
}
|
||||
|
||||
static void test_pack_LPDROPFILES(void)
|
||||
|
@ -939,21 +939,21 @@ static void test_pack_LPSHDESCRIPTIONID(void)
|
|||
{
|
||||
/* LPSHDESCRIPTIONID */
|
||||
TEST_TYPE(LPSHDESCRIPTIONID, 4, 4);
|
||||
TEST_TYPE_POINTER(LPSHDESCRIPTIONID, 20, 1);
|
||||
TEST_TYPE_POINTER(LPSHDESCRIPTIONID, 20, 4);
|
||||
}
|
||||
|
||||
static void test_pack_LPSHELLFLAGSTATE(void)
|
||||
{
|
||||
/* LPSHELLFLAGSTATE */
|
||||
TEST_TYPE(LPSHELLFLAGSTATE, 4, 4);
|
||||
TEST_TYPE_POINTER(LPSHELLFLAGSTATE, 2, 1);
|
||||
TEST_TYPE_POINTER(LPSHELLFLAGSTATE, 4, 1);
|
||||
}
|
||||
|
||||
static void test_pack_LPSHELLSTATE(void)
|
||||
{
|
||||
/* LPSHELLSTATE */
|
||||
TEST_TYPE(LPSHELLSTATE, 4, 4);
|
||||
TEST_TYPE_POINTER(LPSHELLSTATE, 29, 1);
|
||||
TEST_TYPE_POINTER(LPSHELLSTATE, 32, 1);
|
||||
}
|
||||
|
||||
static void test_pack_SHChangeDWORDAsIDList(void)
|
||||
|
@ -983,27 +983,27 @@ static void test_pack_SHChangeProductKeyAsIDList(void)
|
|||
static void test_pack_SHDESCRIPTIONID(void)
|
||||
{
|
||||
/* SHDESCRIPTIONID (pack 1) */
|
||||
TEST_TYPE(SHDESCRIPTIONID, 20, 1);
|
||||
TEST_FIELD(SHDESCRIPTIONID, DWORD, dwDescriptionId, 0, 4, 1);
|
||||
TEST_FIELD(SHDESCRIPTIONID, CLSID, clsid, 4, 16, 1);
|
||||
TEST_TYPE(SHDESCRIPTIONID, 20, 4);
|
||||
TEST_FIELD(SHDESCRIPTIONID, DWORD, dwDescriptionId, 0, 4, 4);
|
||||
TEST_FIELD(SHDESCRIPTIONID, CLSID, clsid, 4, 16, 4);
|
||||
}
|
||||
|
||||
static void test_pack_SHELLFLAGSTATE(void)
|
||||
{
|
||||
/* SHELLFLAGSTATE (pack 1) */
|
||||
TEST_TYPE(SHELLFLAGSTATE, 2, 1);
|
||||
TEST_TYPE(SHELLFLAGSTATE, 4, 1);
|
||||
}
|
||||
|
||||
static void test_pack_SHELLSTATE(void)
|
||||
{
|
||||
/* SHELLSTATE (pack 1) */
|
||||
TEST_TYPE(SHELLSTATE, 29, 1);
|
||||
TEST_FIELD(SHELLSTATE, DWORD, dwWin95Unused, 3, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, UINT, uWin95Unused, 7, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, LONG, lParamSort, 11, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, int, iSortDirection, 15, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, UINT, version, 19, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, UINT, uNotUsed, 23, 4, 1);
|
||||
TEST_TYPE(SHELLSTATE, 32, 1);
|
||||
TEST_FIELD(SHELLSTATE, DWORD, dwWin95Unused, 4, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, UINT, uWin95Unused, 8, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, LONG, lParamSort, 12, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, int, iSortDirection, 16, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, UINT, version, 20, 4, 1);
|
||||
TEST_FIELD(SHELLSTATE, UINT, uNotUsed, 24, 4, 1);
|
||||
}
|
||||
|
||||
static void test_pack_SHELLVIEWID(void)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
extern "C" {
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
||||
/* Except for specific structs, this header is byte packed */
|
||||
#include <pshpack1.h>
|
||||
|
||||
#include <shtypes.h>
|
||||
|
@ -210,6 +211,8 @@ void WINAPI SHAddToRecentDocs(UINT uFlags, LPCVOID pv);
|
|||
*/
|
||||
typedef INT (CALLBACK *BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
|
||||
|
||||
#include <pshpack8.h>
|
||||
|
||||
typedef struct tagBROWSEINFOA {
|
||||
HWND hwndOwner;
|
||||
LPCITEMIDLIST pidlRoot;
|
||||
|
@ -236,6 +239,8 @@ typedef struct tagBROWSEINFOW {
|
|||
#define PBROWSEINFO WINELIB_NAME_AW(PBROWSEINFO)
|
||||
#define LPBROWSEINFO WINELIB_NAME_AW(LPBROWSEINFO)
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
/* Browsing for directory. */
|
||||
#define BIF_RETURNONLYFSDIRS 0x0001
|
||||
#define BIF_DONTGOBELOWDOMAIN 0x0002
|
||||
|
@ -299,11 +304,15 @@ LPITEMIDLIST WINAPI SHBrowseForFolderW(LPBROWSEINFOW lpbi);
|
|||
#define SHDID_COMPUTER_AUDIO 19
|
||||
#define SHDID_COMPUTER_SHAREDDOCS 20
|
||||
|
||||
#include <pshpack8.h>
|
||||
|
||||
typedef struct _SHDESCRIPTIONID
|
||||
{ DWORD dwDescriptionId;
|
||||
CLSID clsid;
|
||||
} SHDESCRIPTIONID, *LPSHDESCRIPTIONID;
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID pv, int cb);
|
||||
HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID pv, int cb);
|
||||
#define SHGetDataFromIDList WINELIB_NAME_AW(SHGetDataFromIDList)
|
||||
|
@ -375,6 +384,7 @@ typedef struct
|
|||
BOOL fShowSuperHidden : 1;
|
||||
BOOL fNoNetCrawling : 1;
|
||||
|
||||
DWORD :0; /* Required for proper binary layout with gcc */
|
||||
DWORD dwWin95Unused;
|
||||
UINT uWin95Unused;
|
||||
LONG lParamSort;
|
||||
|
@ -385,6 +395,7 @@ typedef struct
|
|||
BOOL fStartPanelOn: 1;
|
||||
BOOL fShowStartPage: 1;
|
||||
UINT fSpareFlags : 13;
|
||||
UINT :0; /* Required for proper binary layout with gcc */
|
||||
} SHELLSTATE, *LPSHELLSTATE;
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -408,6 +419,7 @@ typedef struct
|
|||
|
||||
BOOL fHideIcons : 1;
|
||||
UINT fRestFlags : 3;
|
||||
UINT :0; /* Required for proper binary layout with gcc */
|
||||
} SHELLFLAGSTATE, * LPSHELLFLAGSTATE;
|
||||
|
||||
VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
|
||||
|
@ -888,6 +900,7 @@ typedef struct {
|
|||
BOOL fDontPrettyNames:1;
|
||||
BOOL fAdminsCreateCommonGroups:1;
|
||||
UINT fUnusedFlags:7;
|
||||
UINT :0; /* Required for proper binary layout with gcc */
|
||||
UINT fMenuEnumFilter;
|
||||
} CABINETSTATE, *LPCABINETSTATE;
|
||||
|
||||
|
@ -901,8 +914,6 @@ BOOL WINAPI WriteCabinetState(CABINETSTATE *);
|
|||
*/
|
||||
VOID WINAPI PathGetShortPath(LPWSTR pszPath);
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Drag And Drop Routines
|
||||
*/
|
||||
|
@ -1017,6 +1028,8 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST,LPCITEMIDLIST);
|
|||
BOOL WINAPI ILIsParent(LPCITEMIDLIST,LPCITEMIDLIST,BOOL);
|
||||
BOOL WINAPI ILRemoveLastID(LPITEMIDLIST);
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
|
|
@ -1979,7 +1979,7 @@ sub parse_c_variable {
|
|||
}
|
||||
|
||||
$finished = 1;
|
||||
} elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+\b(?:\s*\*)*)\s*(\w+)\s*(\[.*?\]$|:\s*(\d+)$|\{)?//s) {
|
||||
} elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+\b(?:\s+DECLSPEC_ALIGN\(.*?\)|\s*\*)*)\s*(\w+)\s*(\[.*?\]$|:\s*(\d+)$|\{)?//s) {
|
||||
$type = "$sign$1";
|
||||
$name = $2;
|
||||
|
||||
|
@ -1997,6 +1997,12 @@ sub parse_c_variable {
|
|||
|
||||
$type = $self->_format_c_type($type);
|
||||
|
||||
$finished = 1;
|
||||
} elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+\b(?:\s*\*)*)\s*:\s*(\d+)$//s) {
|
||||
$type = "$sign$1:$2";
|
||||
$name = "";
|
||||
$type = $self->_format_c_type($type);
|
||||
|
||||
$finished = 1;
|
||||
} elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+\b(?:\s*\*)*\s*\((?:\s*CALLBACK|\s*NTAPI|\s*WINAPI)?(?:\s*\*)*)\s*(\w+)\s*(\)\s*\(.*?\))$//s) {
|
||||
$type = $self->_format_c_type("$sign$1$3");
|
||||
|
|
|
@ -64,6 +64,17 @@ sub set_find_size_callback {
|
|||
$$find_size = shift;
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# set_find_count_callback
|
||||
#
|
||||
sub set_find_count_callback {
|
||||
my $self = shift;
|
||||
|
||||
my $find_count = \${$self->{FIND_COUNT}};
|
||||
|
||||
$$find_count = shift;
|
||||
}
|
||||
|
||||
sub kind {
|
||||
my $self = shift;
|
||||
my $kind = \${$self->{KIND}};
|
||||
|
@ -236,6 +247,7 @@ sub _refresh {
|
|||
my $find_align = \${$self->{FIND_ALIGN}};
|
||||
my $find_kind = \${$self->{FIND_KIND}};
|
||||
my $find_size = \${$self->{FIND_SIZE}};
|
||||
my $find_count = \${$self->{FIND_COUNT}};
|
||||
|
||||
my $align = \${$self->{ALIGN}};
|
||||
my $kind = \${$self->{KIND}};
|
||||
|
@ -251,70 +263,100 @@ sub _refresh {
|
|||
my $max_field_align = 0;
|
||||
|
||||
my $offset = 0;
|
||||
my $offset_bits = 0;
|
||||
my $bitfield_size = 0;
|
||||
my $bitfield_bits = 0;
|
||||
|
||||
my $n = 0;
|
||||
foreach my $field ($self->fields) {
|
||||
my $type_name = $field->type_name;
|
||||
my $type_size = &$$find_size($type_name);
|
||||
|
||||
my $base_type_name = $type_name;
|
||||
if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) {
|
||||
my $count = $2;
|
||||
my $bits = $3;
|
||||
my $bits;
|
||||
my $count;
|
||||
if ($type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/)
|
||||
{
|
||||
$count = $2;
|
||||
$bits = $3;
|
||||
}
|
||||
my $base_size = &$$find_size($base_type_name);
|
||||
$$align = &$$find_align($base_type_name);
|
||||
my $declspec_align;
|
||||
if ($type_name =~ s/\s+DECLSPEC_ALIGN\((\d+)\)//)
|
||||
{
|
||||
$declspec_align=$1;
|
||||
}
|
||||
my $base_size = &$$find_size($type_name);
|
||||
my $type_size=$base_size;
|
||||
if (defined $count)
|
||||
{
|
||||
$count=&$$find_count($count) if ($count !~ /^\d+$/);
|
||||
if (!defined $count)
|
||||
{
|
||||
$type_size=undef;
|
||||
}
|
||||
else
|
||||
{
|
||||
$type_size *= int($count);
|
||||
}
|
||||
}
|
||||
if ($bitfield_size != 0)
|
||||
{
|
||||
if (($type_name eq "" and defined $bits and $bits == 0) or
|
||||
(defined $type_size and $bitfield_size != $type_size) or
|
||||
!defined $bits or
|
||||
$bitfield_bits + $bits > 8 * $bitfield_size)
|
||||
{
|
||||
# This marks the end of the previous bitfield
|
||||
$bitfield_size=0;
|
||||
$bitfield_bits=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$bitfield_bits+=$bits;
|
||||
$n++;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($$align)) {
|
||||
$$align = $pack if $$align > $pack;
|
||||
$max_field_align = $$align if $$align > $max_field_align;
|
||||
$$align = &$$find_align($type_name);
|
||||
$$align=$declspec_align if (defined $declspec_align);
|
||||
|
||||
if ($offset % $$align != 0) {
|
||||
$offset = (int($offset / $$align) + 1) * $$align;
|
||||
}
|
||||
}
|
||||
if (defined $$align)
|
||||
{
|
||||
$$align = $pack if $$align > $pack;
|
||||
$max_field_align = $$align if $$align > $max_field_align;
|
||||
|
||||
if ($$kind !~ /^(?:struct|union)$/) {
|
||||
$$kind = &$$find_kind($type_name) || "";
|
||||
}
|
||||
if ($offset % $$align != 0) {
|
||||
$offset = (int($offset / $$align) + 1) * $$align;
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined($type_size)) {
|
||||
$$align = undef;
|
||||
$$size = undef;
|
||||
return;
|
||||
} elsif ($type_size >= 0) {
|
||||
if ($offset_bits) {
|
||||
$offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack));
|
||||
$offset_bits = 0;
|
||||
}
|
||||
if ($$kind !~ /^(?:struct|union)$/)
|
||||
{
|
||||
$$kind = &$$find_kind($type_name) || "";
|
||||
}
|
||||
|
||||
$$$field_aligns[$n] = $$align;
|
||||
$$$field_base_sizes[$n] = $base_size;
|
||||
$$$field_offsets[$n] = $offset;
|
||||
$$$field_sizes[$n] = $type_size;
|
||||
if (!$type_size)
|
||||
{
|
||||
$$align = undef;
|
||||
$$size = undef;
|
||||
return;
|
||||
}
|
||||
|
||||
$offset += $type_size;
|
||||
} else {
|
||||
$$$field_aligns[$n] = $$align;
|
||||
$$$field_base_sizes[$n] = $base_size;
|
||||
$$$field_offsets[$n] = $offset;
|
||||
$$$field_sizes[$n] = $type_size;
|
||||
|
||||
$offset_bits += -$type_size;
|
||||
}
|
||||
$$$field_aligns[$n] = $$align;
|
||||
$$$field_base_sizes[$n] = $base_size;
|
||||
$$$field_offsets[$n] = $offset;
|
||||
$$$field_sizes[$n] = $type_size;
|
||||
$offset += $type_size;
|
||||
|
||||
if ($bits)
|
||||
{
|
||||
$bitfield_size=$type_size;
|
||||
$bitfield_bits=$bits;
|
||||
}
|
||||
$n++;
|
||||
}
|
||||
|
||||
$$align = $pack;
|
||||
$$align = $max_field_align if $max_field_align < $pack;
|
||||
|
||||
if ($offset_bits) {
|
||||
$offset += $pack * int(($offset_bits + 8 * $pack - 1 ) / (8 * $pack));
|
||||
$offset_bits = 0;
|
||||
}
|
||||
|
||||
$$size = $offset;
|
||||
if ($$kind =~ /^(?:struct|union)$/) {
|
||||
if ($$size % $$align != 0) {
|
||||
|
|
|
@ -177,13 +177,6 @@ sub _find_align_kind_size {
|
|||
|
||||
local $_ = $type_name;
|
||||
|
||||
my $count;
|
||||
my $bits;
|
||||
if (s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) {
|
||||
$count = $2;
|
||||
$bits = $3;
|
||||
}
|
||||
|
||||
my $align;
|
||||
my $kind;
|
||||
my $size;
|
||||
|
@ -313,21 +306,6 @@ sub _find_align_kind_size {
|
|||
$output->write("$type_name: type needn't be kludged\n");
|
||||
}
|
||||
|
||||
if (!defined($size)) {
|
||||
# $output->write("$type_name: can't find type\n");
|
||||
} elsif (defined($count)) {
|
||||
if ($count =~ /^\d+$/) {
|
||||
$size *= int($count);
|
||||
} elsif (defined(my $count2 = $defines{$count})) {
|
||||
$size *= int($count2);
|
||||
} else {
|
||||
$output->write("$type_name: can't parse type ('$_') ('$count')\n");
|
||||
$size = undef;
|
||||
}
|
||||
} elsif (defined($bits)) {
|
||||
$size = -$bits;
|
||||
}
|
||||
|
||||
return ($align, $kind, $size);
|
||||
}
|
||||
|
||||
|
@ -350,6 +328,11 @@ sub find_size {
|
|||
return $size;
|
||||
}
|
||||
|
||||
sub find_count {
|
||||
my $count = shift;
|
||||
return $defines{$count};
|
||||
}
|
||||
|
||||
foreach my $file (@files) {
|
||||
$progress_current++;
|
||||
|
||||
|
@ -426,6 +409,7 @@ foreach my $file (@files) {
|
|||
$type->set_find_align_callback(\&find_align);
|
||||
$type->set_find_kind_callback(\&find_kind);
|
||||
$type->set_find_size_callback(\&find_size);
|
||||
$type->set_find_count_callback(\&find_count);
|
||||
|
||||
my $pack = $packs[$#packs];
|
||||
if (!defined($type->pack) && $type->kind =~ /^(?:struct|union)$/) {
|
||||
|
@ -728,6 +712,8 @@ sub output_test_pack_fields {
|
|||
my $field_align = $field->align;
|
||||
|
||||
next if $field_name eq "" || (defined($field_size) && $field_size < 0);
|
||||
# We cannot take the address of a bitfield with MSVC
|
||||
next if ($field_type_name =~ /:/);
|
||||
|
||||
if ($$optional_fields{$field_name}) {
|
||||
# Nothing
|
||||
|
|
Loading…
Reference in New Issue