Commit 09747e50 authored by Francois Gouget's avatar Francois Gouget Committed by Alexandre Julliard

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.
parent 4133ed17
......@@ -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;
......@@ -1998,6 +1998,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");
$name = $2;
......
......@@ -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);
if (defined($$align)) {
$$align = $pack if $$align > $pack;
$max_field_align = $$align if $$align > $max_field_align;
if ($offset % $$align != 0) {
$offset = (int($offset / $$align) + 1) * $$align;
}
}
if ($$kind !~ /^(?:struct|union)$/) {
$$kind = &$$find_kind($type_name) || "";
}
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;
}
$$$field_aligns[$n] = $$align;
$$$field_base_sizes[$n] = $base_size;
$$$field_offsets[$n] = $offset;
$$$field_sizes[$n] = $type_size;
$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;
}
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;
}
}
$$align = &$$find_align($type_name);
$$align=$declspec_align if (defined $declspec_align);
if (defined $$align)
{
$$align = $pack if $$align > $pack;
$max_field_align = $$align if $$align > $max_field_align;
if ($offset % $$align != 0) {
$offset = (int($offset / $$align) + 1) * $$align;
}
}
if ($$kind !~ /^(?:struct|union)$/)
{
$$kind = &$$find_kind($type_name) || "";
}
if (!$type_size)
{
$$align = undef;
$$size = undef;
return;
}
$$$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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment