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.
diff --git a/dlls/shell32/tests/generated.c b/dlls/shell32/tests/generated.c
index 3f4f68c..9842ddd 100644
--- a/dlls/shell32/tests/generated.c
+++ b/dlls/shell32/tests/generated.c
@@ -760,13 +760,13 @@
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_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 @@
{
/* 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 @@
{
/* 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_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)
diff --git a/include/shlobj.h b/include/shlobj.h
index 6e6eb7e..9d621d3 100644
--- a/include/shlobj.h
+++ b/include/shlobj.h
@@ -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 @@
*/
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 @@
#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 @@
#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 @@
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 @@
BOOL fStartPanelOn: 1;
BOOL fShowStartPage: 1;
UINT fSpareFlags : 13;
+ UINT :0; /* Required for proper binary layout with gcc */
} SHELLSTATE, *LPSHELLSTATE;
/**********************************************************************
@@ -408,6 +419,7 @@
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 @@
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 @@
*/
VOID WINAPI PathGetShortPath(LPWSTR pszPath);
-#include <poppack.h>
-
/****************************************************************************
* Drag And Drop Routines
*/
@@ -1017,6 +1028,8 @@
BOOL WINAPI ILIsParent(LPCITEMIDLIST,LPCITEMIDLIST,BOOL);
BOOL WINAPI ILRemoveLastID(LPITEMIDLIST);
+#include <poppack.h>
+
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */
diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm
index 4bc2939..4e4175d 100644
--- a/tools/winapi/c_parser.pm
+++ b/tools/winapi/c_parser.pm
@@ -1979,7 +1979,7 @@
}
$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;
@@ -1998,6 +1998,12 @@
$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");
$name = $2;
diff --git a/tools/winapi/c_type.pm b/tools/winapi/c_type.pm
index ab056e6..efe64c6 100644
--- a/tools/winapi/c_type.pm
+++ b/tools/winapi/c_type.pm
@@ -64,6 +64,17 @@
$$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 @@
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 @@
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;
+ $$$field_aligns[$n] = $$align;
+ $$$field_base_sizes[$n] = $base_size;
+ $$$field_offsets[$n] = $offset;
+ $$$field_sizes[$n] = $type_size;
+ $offset += $type_size;
- $offset_bits += -$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) {
diff --git a/tools/winapi/winapi_test b/tools/winapi/winapi_test
index 008b918..42eb3f7 100755
--- a/tools/winapi/winapi_test
+++ b/tools/winapi/winapi_test
@@ -177,13 +177,6 @@
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 @@
$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 @@
return $size;
}
+sub find_count {
+ my $count = shift;
+ return $defines{$count};
+}
+
foreach my $file (@files) {
$progress_current++;
@@ -426,6 +409,7 @@
$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 @@
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