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:
Francois Gouget 2004-08-20 19:33:17 +00:00 committed by Alexandre Julliard
parent 4133ed17d9
commit 09747e50e7
5 changed files with 141 additions and 94 deletions

View File

@ -760,13 +760,13 @@ static void test_pack_SHNAMEMAPPINGW(void)
static void test_pack_AUTO_SCROLL_DATA(void) static void test_pack_AUTO_SCROLL_DATA(void)
{ {
/* AUTO_SCROLL_DATA (pack 4) */ /* AUTO_SCROLL_DATA (pack 1) */
TEST_TYPE(AUTO_SCROLL_DATA, 48, 4); TEST_TYPE(AUTO_SCROLL_DATA, 48, 1);
TEST_FIELD(AUTO_SCROLL_DATA, int, iNextSample, 0, 4, 4); TEST_FIELD(AUTO_SCROLL_DATA, int, iNextSample, 0, 4, 1);
TEST_FIELD(AUTO_SCROLL_DATA, DWORD, dwLastScroll, 4, 4, 4); TEST_FIELD(AUTO_SCROLL_DATA, DWORD, dwLastScroll, 4, 4, 1);
TEST_FIELD(AUTO_SCROLL_DATA, BOOL, bFull, 8, 4, 4); TEST_FIELD(AUTO_SCROLL_DATA, BOOL, bFull, 8, 4, 1);
TEST_FIELD(AUTO_SCROLL_DATA, POINT[NUM_POINTS], pts, 12, 24, 4); TEST_FIELD(AUTO_SCROLL_DATA, POINT[NUM_POINTS], pts, 12, 24, 1);
TEST_FIELD(AUTO_SCROLL_DATA, DWORD[NUM_POINTS], dwTimes, 36, 12, 4); TEST_FIELD(AUTO_SCROLL_DATA, DWORD[NUM_POINTS], dwTimes, 36, 12, 1);
} }
static void test_pack_BFFCALLBACK(void) static void test_pack_BFFCALLBACK(void)
@ -778,10 +778,10 @@ static void test_pack_BFFCALLBACK(void)
static void test_pack_CABINETSTATE(void) static void test_pack_CABINETSTATE(void)
{ {
/* CABINETSTATE (pack 1) */ /* 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, cLength, 0, 2, 1);
TEST_FIELD(CABINETSTATE, WORD, nVersion, 2, 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) static void test_pack_CIDA(void)
@ -876,7 +876,7 @@ static void test_pack_LPCABINETSTATE(void)
{ {
/* LPCABINETSTATE */ /* LPCABINETSTATE */
TEST_TYPE(LPCABINETSTATE, 4, 4); TEST_TYPE(LPCABINETSTATE, 4, 4);
TEST_TYPE_POINTER(LPCABINETSTATE, 10, 1); TEST_TYPE_POINTER(LPCABINETSTATE, 12, 1);
} }
static void test_pack_LPDROPFILES(void) static void test_pack_LPDROPFILES(void)
@ -939,21 +939,21 @@ static void test_pack_LPSHDESCRIPTIONID(void)
{ {
/* LPSHDESCRIPTIONID */ /* LPSHDESCRIPTIONID */
TEST_TYPE(LPSHDESCRIPTIONID, 4, 4); TEST_TYPE(LPSHDESCRIPTIONID, 4, 4);
TEST_TYPE_POINTER(LPSHDESCRIPTIONID, 20, 1); TEST_TYPE_POINTER(LPSHDESCRIPTIONID, 20, 4);
} }
static void test_pack_LPSHELLFLAGSTATE(void) static void test_pack_LPSHELLFLAGSTATE(void)
{ {
/* LPSHELLFLAGSTATE */ /* LPSHELLFLAGSTATE */
TEST_TYPE(LPSHELLFLAGSTATE, 4, 4); TEST_TYPE(LPSHELLFLAGSTATE, 4, 4);
TEST_TYPE_POINTER(LPSHELLFLAGSTATE, 2, 1); TEST_TYPE_POINTER(LPSHELLFLAGSTATE, 4, 1);
} }
static void test_pack_LPSHELLSTATE(void) static void test_pack_LPSHELLSTATE(void)
{ {
/* LPSHELLSTATE */ /* LPSHELLSTATE */
TEST_TYPE(LPSHELLSTATE, 4, 4); TEST_TYPE(LPSHELLSTATE, 4, 4);
TEST_TYPE_POINTER(LPSHELLSTATE, 29, 1); TEST_TYPE_POINTER(LPSHELLSTATE, 32, 1);
} }
static void test_pack_SHChangeDWORDAsIDList(void) static void test_pack_SHChangeDWORDAsIDList(void)
@ -983,27 +983,27 @@ static void test_pack_SHChangeProductKeyAsIDList(void)
static void test_pack_SHDESCRIPTIONID(void) static void test_pack_SHDESCRIPTIONID(void)
{ {
/* SHDESCRIPTIONID (pack 1) */ /* SHDESCRIPTIONID (pack 1) */
TEST_TYPE(SHDESCRIPTIONID, 20, 1); TEST_TYPE(SHDESCRIPTIONID, 20, 4);
TEST_FIELD(SHDESCRIPTIONID, DWORD, dwDescriptionId, 0, 4, 1); TEST_FIELD(SHDESCRIPTIONID, DWORD, dwDescriptionId, 0, 4, 4);
TEST_FIELD(SHDESCRIPTIONID, CLSID, clsid, 4, 16, 1); TEST_FIELD(SHDESCRIPTIONID, CLSID, clsid, 4, 16, 4);
} }
static void test_pack_SHELLFLAGSTATE(void) static void test_pack_SHELLFLAGSTATE(void)
{ {
/* SHELLFLAGSTATE (pack 1) */ /* SHELLFLAGSTATE (pack 1) */
TEST_TYPE(SHELLFLAGSTATE, 2, 1); TEST_TYPE(SHELLFLAGSTATE, 4, 1);
} }
static void test_pack_SHELLSTATE(void) static void test_pack_SHELLSTATE(void)
{ {
/* SHELLSTATE (pack 1) */ /* SHELLSTATE (pack 1) */
TEST_TYPE(SHELLSTATE, 29, 1); TEST_TYPE(SHELLSTATE, 32, 1);
TEST_FIELD(SHELLSTATE, DWORD, dwWin95Unused, 3, 4, 1); TEST_FIELD(SHELLSTATE, DWORD, dwWin95Unused, 4, 4, 1);
TEST_FIELD(SHELLSTATE, UINT, uWin95Unused, 7, 4, 1); TEST_FIELD(SHELLSTATE, UINT, uWin95Unused, 8, 4, 1);
TEST_FIELD(SHELLSTATE, LONG, lParamSort, 11, 4, 1); TEST_FIELD(SHELLSTATE, LONG, lParamSort, 12, 4, 1);
TEST_FIELD(SHELLSTATE, int, iSortDirection, 15, 4, 1); TEST_FIELD(SHELLSTATE, int, iSortDirection, 16, 4, 1);
TEST_FIELD(SHELLSTATE, UINT, version, 19, 4, 1); TEST_FIELD(SHELLSTATE, UINT, version, 20, 4, 1);
TEST_FIELD(SHELLSTATE, UINT, uNotUsed, 23, 4, 1); TEST_FIELD(SHELLSTATE, UINT, uNotUsed, 24, 4, 1);
} }
static void test_pack_SHELLVIEWID(void) static void test_pack_SHELLVIEWID(void)

View File

@ -28,6 +28,7 @@
extern "C" { extern "C" {
#endif /* defined(__cplusplus) */ #endif /* defined(__cplusplus) */
/* Except for specific structs, this header is byte packed */
#include <pshpack1.h> #include <pshpack1.h>
#include <shtypes.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); typedef INT (CALLBACK *BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
#include <pshpack8.h>
typedef struct tagBROWSEINFOA { typedef struct tagBROWSEINFOA {
HWND hwndOwner; HWND hwndOwner;
LPCITEMIDLIST pidlRoot; LPCITEMIDLIST pidlRoot;
@ -236,6 +239,8 @@ typedef struct tagBROWSEINFOW {
#define PBROWSEINFO WINELIB_NAME_AW(PBROWSEINFO) #define PBROWSEINFO WINELIB_NAME_AW(PBROWSEINFO)
#define LPBROWSEINFO WINELIB_NAME_AW(LPBROWSEINFO) #define LPBROWSEINFO WINELIB_NAME_AW(LPBROWSEINFO)
#include <poppack.h>
/* Browsing for directory. */ /* Browsing for directory. */
#define BIF_RETURNONLYFSDIRS 0x0001 #define BIF_RETURNONLYFSDIRS 0x0001
#define BIF_DONTGOBELOWDOMAIN 0x0002 #define BIF_DONTGOBELOWDOMAIN 0x0002
@ -299,11 +304,15 @@ LPITEMIDLIST WINAPI SHBrowseForFolderW(LPBROWSEINFOW lpbi);
#define SHDID_COMPUTER_AUDIO 19 #define SHDID_COMPUTER_AUDIO 19
#define SHDID_COMPUTER_SHAREDDOCS 20 #define SHDID_COMPUTER_SHAREDDOCS 20
#include <pshpack8.h>
typedef struct _SHDESCRIPTIONID typedef struct _SHDESCRIPTIONID
{ DWORD dwDescriptionId; { DWORD dwDescriptionId;
CLSID clsid; CLSID clsid;
} SHDESCRIPTIONID, *LPSHDESCRIPTIONID; } SHDESCRIPTIONID, *LPSHDESCRIPTIONID;
#include <poppack.h>
HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID pv, int cb); 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); HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID pv, int cb);
#define SHGetDataFromIDList WINELIB_NAME_AW(SHGetDataFromIDList) #define SHGetDataFromIDList WINELIB_NAME_AW(SHGetDataFromIDList)
@ -375,6 +384,7 @@ typedef struct
BOOL fShowSuperHidden : 1; BOOL fShowSuperHidden : 1;
BOOL fNoNetCrawling : 1; BOOL fNoNetCrawling : 1;
DWORD :0; /* Required for proper binary layout with gcc */
DWORD dwWin95Unused; DWORD dwWin95Unused;
UINT uWin95Unused; UINT uWin95Unused;
LONG lParamSort; LONG lParamSort;
@ -385,6 +395,7 @@ typedef struct
BOOL fStartPanelOn: 1; BOOL fStartPanelOn: 1;
BOOL fShowStartPage: 1; BOOL fShowStartPage: 1;
UINT fSpareFlags : 13; UINT fSpareFlags : 13;
UINT :0; /* Required for proper binary layout with gcc */
} SHELLSTATE, *LPSHELLSTATE; } SHELLSTATE, *LPSHELLSTATE;
/********************************************************************** /**********************************************************************
@ -408,6 +419,7 @@ typedef struct
BOOL fHideIcons : 1; BOOL fHideIcons : 1;
UINT fRestFlags : 3; UINT fRestFlags : 3;
UINT :0; /* Required for proper binary layout with gcc */
} SHELLFLAGSTATE, * LPSHELLFLAGSTATE; } SHELLFLAGSTATE, * LPSHELLFLAGSTATE;
VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask); VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
@ -888,6 +900,7 @@ typedef struct {
BOOL fDontPrettyNames:1; BOOL fDontPrettyNames:1;
BOOL fAdminsCreateCommonGroups:1; BOOL fAdminsCreateCommonGroups:1;
UINT fUnusedFlags:7; UINT fUnusedFlags:7;
UINT :0; /* Required for proper binary layout with gcc */
UINT fMenuEnumFilter; UINT fMenuEnumFilter;
} CABINETSTATE, *LPCABINETSTATE; } CABINETSTATE, *LPCABINETSTATE;
@ -901,8 +914,6 @@ BOOL WINAPI WriteCabinetState(CABINETSTATE *);
*/ */
VOID WINAPI PathGetShortPath(LPWSTR pszPath); VOID WINAPI PathGetShortPath(LPWSTR pszPath);
#include <poppack.h>
/**************************************************************************** /****************************************************************************
* Drag And Drop Routines * Drag And Drop Routines
*/ */
@ -1017,6 +1028,8 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST,LPCITEMIDLIST);
BOOL WINAPI ILIsParent(LPCITEMIDLIST,LPCITEMIDLIST,BOOL); BOOL WINAPI ILIsParent(LPCITEMIDLIST,LPCITEMIDLIST,BOOL);
BOOL WINAPI ILRemoveLastID(LPITEMIDLIST); BOOL WINAPI ILRemoveLastID(LPITEMIDLIST);
#include <poppack.h>
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif /* defined(__cplusplus) */ #endif /* defined(__cplusplus) */

View File

@ -1979,7 +1979,7 @@ sub parse_c_variable {
} }
$finished = 1; $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"; $type = "$sign$1";
$name = $2; $name = $2;
@ -1997,6 +1997,12 @@ sub parse_c_variable {
$type = $self->_format_c_type($type); $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; $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) { } 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"); $type = $self->_format_c_type("$sign$1$3");

View File

@ -64,6 +64,17 @@ sub set_find_size_callback {
$$find_size = shift; $$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 { sub kind {
my $self = shift; my $self = shift;
my $kind = \${$self->{KIND}}; my $kind = \${$self->{KIND}};
@ -236,6 +247,7 @@ sub _refresh {
my $find_align = \${$self->{FIND_ALIGN}}; my $find_align = \${$self->{FIND_ALIGN}};
my $find_kind = \${$self->{FIND_KIND}}; my $find_kind = \${$self->{FIND_KIND}};
my $find_size = \${$self->{FIND_SIZE}}; my $find_size = \${$self->{FIND_SIZE}};
my $find_count = \${$self->{FIND_COUNT}};
my $align = \${$self->{ALIGN}}; my $align = \${$self->{ALIGN}};
my $kind = \${$self->{KIND}}; my $kind = \${$self->{KIND}};
@ -251,22 +263,63 @@ sub _refresh {
my $max_field_align = 0; my $max_field_align = 0;
my $offset = 0; my $offset = 0;
my $offset_bits = 0; my $bitfield_size = 0;
my $bitfield_bits = 0;
my $n = 0; my $n = 0;
foreach my $field ($self->fields) { foreach my $field ($self->fields) {
my $type_name = $field->type_name; my $type_name = $field->type_name;
my $type_size = &$$find_size($type_name);
my $base_type_name = $type_name; my $bits;
if ($base_type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) { my $count;
my $count = $2; if ($type_name =~ s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/)
my $bits = $3; {
$count = $2;
$bits = $3;
}
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;
}
} }
my $base_size = &$$find_size($base_type_name);
$$align = &$$find_align($base_type_name);
if (defined($$align)) { $$align = &$$find_align($type_name);
$$align=$declspec_align if (defined $declspec_align);
if (defined $$align)
{
$$align = $pack if $$align > $pack; $$align = $pack if $$align > $pack;
$max_field_align = $$align if $$align > $max_field_align; $max_field_align = $$align if $$align > $max_field_align;
@ -275,46 +328,35 @@ sub _refresh {
} }
} }
if ($$kind !~ /^(?:struct|union)$/) { if ($$kind !~ /^(?:struct|union)$/)
{
$$kind = &$$find_kind($type_name) || ""; $$kind = &$$find_kind($type_name) || "";
} }
if (!defined($type_size)) { if (!$type_size)
{
$$align = undef; $$align = undef;
$$size = undef; $$size = undef;
return; 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_aligns[$n] = $$align;
$$$field_base_sizes[$n] = $base_size; $$$field_base_sizes[$n] = $base_size;
$$$field_offsets[$n] = $offset; $$$field_offsets[$n] = $offset;
$$$field_sizes[$n] = $type_size; $$$field_sizes[$n] = $type_size;
$offset += $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; if ($bits)
{
$bitfield_size=$type_size;
$bitfield_bits=$bits;
} }
$n++; $n++;
} }
$$align = $pack; $$align = $pack;
$$align = $max_field_align if $max_field_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; $$size = $offset;
if ($$kind =~ /^(?:struct|union)$/) { if ($$kind =~ /^(?:struct|union)$/) {
if ($$size % $$align != 0) { if ($$size % $$align != 0) {

View File

@ -177,13 +177,6 @@ sub _find_align_kind_size {
local $_ = $type_name; local $_ = $type_name;
my $count;
my $bits;
if (s/^(.*?)\s*(?:\[\s*(.*?)\s*\]|:(\d+))?$/$1/) {
$count = $2;
$bits = $3;
}
my $align; my $align;
my $kind; my $kind;
my $size; my $size;
@ -313,21 +306,6 @@ sub _find_align_kind_size {
$output->write("$type_name: type needn't be kludged\n"); $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); return ($align, $kind, $size);
} }
@ -350,6 +328,11 @@ sub find_size {
return $size; return $size;
} }
sub find_count {
my $count = shift;
return $defines{$count};
}
foreach my $file (@files) { foreach my $file (@files) {
$progress_current++; $progress_current++;
@ -426,6 +409,7 @@ foreach my $file (@files) {
$type->set_find_align_callback(\&find_align); $type->set_find_align_callback(\&find_align);
$type->set_find_kind_callback(\&find_kind); $type->set_find_kind_callback(\&find_kind);
$type->set_find_size_callback(\&find_size); $type->set_find_size_callback(\&find_size);
$type->set_find_count_callback(\&find_count);
my $pack = $packs[$#packs]; my $pack = $packs[$#packs];
if (!defined($type->pack) && $type->kind =~ /^(?:struct|union)$/) { if (!defined($type->pack) && $type->kind =~ /^(?:struct|union)$/) {
@ -728,6 +712,8 @@ sub output_test_pack_fields {
my $field_align = $field->align; my $field_align = $field->align;
next if $field_name eq "" || (defined($field_size) && $field_size < 0); 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}) { if ($$optional_fields{$field_name}) {
# Nothing # Nothing