From 09747e50e79167b0e4158b2230fac0af249f5ddd Mon Sep 17 00:00:00 2001 From: Francois Gouget Date: Fri, 20 Aug 2004 19:33:17 +0000 Subject: [PATCH] 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. --- dlls/shell32/tests/generated.c | 48 +++++++------- include/shlobj.h | 17 ++++- tools/winapi/c_parser.pm | 8 ++- tools/winapi/c_type.pm | 146 ++++++++++++++++++++++++++--------------- tools/winapi/winapi_test | 30 +++------ 5 files changed, 148 insertions(+), 101 deletions(-) diff --git a/dlls/shell32/tests/generated.c b/dlls/shell32/tests/generated.c index 3f4f68c288c..9842ddd633f 100644 --- a/dlls/shell32/tests/generated.c +++ b/dlls/shell32/tests/generated.c @@ -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) diff --git a/include/shlobj.h b/include/shlobj.h index 6e6eb7e7b1f..9d621d333c9 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 #include @@ -210,6 +211,8 @@ void WINAPI SHAddToRecentDocs(UINT uFlags, LPCVOID pv); */ typedef INT (CALLBACK *BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); +#include + 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 + /* 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 + typedef struct _SHDESCRIPTIONID { DWORD dwDescriptionId; CLSID clsid; } SHDESCRIPTIONID, *LPSHDESCRIPTIONID; +#include + 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 - /**************************************************************************** * Drag And Drop Routines */ @@ -1017,6 +1028,8 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST,LPCITEMIDLIST); BOOL WINAPI ILIsParent(LPCITEMIDLIST,LPCITEMIDLIST,BOOL); BOOL WINAPI ILRemoveLastID(LPITEMIDLIST); +#include + #ifdef __cplusplus } /* extern "C" */ #endif /* defined(__cplusplus) */ diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm index 4bc2939e1fe..4e4175dae9b 100644 --- a/tools/winapi/c_parser.pm +++ b/tools/winapi/c_parser.pm @@ -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; diff --git a/tools/winapi/c_type.pm b/tools/winapi/c_type.pm index ab056e69187..efe64c68ab8 100644 --- a/tools/winapi/c_type.pm +++ b/tools/winapi/c_type.pm @@ -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) { diff --git a/tools/winapi/winapi_test b/tools/winapi/winapi_test index 008b918932e..42eb3f7a425 100755 --- a/tools/winapi/winapi_test +++ b/tools/winapi/winapi_test @@ -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 -- 2.11.4.GIT