The recent problems with -noname in shell32.spec got be to dig up an old script I had which reads spec and dumpbin files and processes them. I then retrofitted it so it could do some hopefully useful checks for this kind of issues.
So this script works by comparing the output of winedump or dumpbin on the Windows dlls for as many platforms as are available (I have 7 so far) with the contents of Wine's spec files. It then applies a number of rules to try to detect problems. However the information we can extract from the Windows dlls is incomplete so this script uses heuristics. This means the problems it reports should be treated with a grain of salt.
Running the check script
To download and run the check script, see the instructions are on my web site: http://fgouget.free.fr/wine/checkspec-en.shtml
Then you can run it as follows:
./check_spec --verbose ~/wine/dlls/shell32.spec
And here is a description of the checks it performs so far, illustrated with the output for shell32.dll. Comments and suggestions for more checks or improvements are welcome. I'll wait a bit (and then start sending some patches unless someone else wants to tackle this (could be a nice janitorial project).
Notes: * It would be nice if winedump could dump the Platform SDK's .lib files. These files must have an explicit mention of which entry points have the -noname property so this would give us a more reliable source of information than the heuristics in this script. * dumpbin will something special when an API is being forwarded: 40 [NONAME] (forwarded to shlwapi.PathIsRelativeW) But winedump prints nothing special. It would be nice to add this functionality to winedump.
-noname vs. ordinal internal consistency -----------------------------------------
This check verifies that all APIs which have the '-noname' property, also have an explicit ordinal. This is the only check which does not depend on dumps of the Windows dlls.
No problem found here.
APIs which should not have an explicit ordinal ----------------------------------------------
The script scans the Wine spec file for APIs which have both a name and an explicit ordinal. For each of these, the script looks up the API by name on the Windows platforms and collates a list of the corresponding ordinals. If it finds more than one ordinal then it considers the API should not be given an explicit ordinal.
In that case it reports how many times the API was found with the right ordinal on Windows, and how many different values were found. If the former is 0 or 1 then it's clear the API should not be given an explicit ordinal. If the latter is 2 then things are maybe not so clear.
These 64 APIs should not have an ordinal: SHGetDataFromIDListA (correct 0 times, found 5 values) StrChrIW (correct 0 times, found 3 values) SheGetCurDrive (correct 0 times, found 5 values) ShellAboutW (correct 0 times, found 5 values) SheFullPathA (correct 0 times, found 5 values) DllGetClassObject (correct 0 times, found 5 values) SheGetDirA (correct 0 times, found 5 values) SheGetPathOffsetW (correct 0 times, found 5 values) SheGetDirW (correct 0 times, found 5 values) DragFinish (correct 0 times, found 5 values) StrCmpNW (correct 0 times, found 3 values) StrNCmpA (correct 0 times, found 3 values) StrCmpNIA (correct 0 times, found 3 values) ShellExecuteW (correct 0 times, found 5 values) SheChangeDirW (correct 0 times, found 5 values) Shell_NotifyIconW (correct 0 times, found 5 values) StrCpyNA (correct 0 times, found 3 values) SheRemoveQuotesW (correct 0 times, found 5 values) StrCmpNA (correct 0 times, found 3 values) ShellExecuteExA (correct 0 times, found 5 values) StrRStrIA (correct 0 times, found 3 values) StrStrA (correct 0 times, found 3 values) StrStrW (correct 0 times, found 3 values) StrChrA (correct 0 times, found 3 values) SheShortenPathA (correct 0 times, found 5 values) StrNCmpIW (correct 0 times, found 3 values) StrRChrIA (correct 0 times, found 3 values) StrChrIA (correct 0 times, found 3 values) SheConvertPathW (correct 0 times, found 5 values) StrNCpyW (correct 0 times, found 3 values) DragAcceptFiles (correct 0 times, found 5 values) StrRStrIW (correct 0 times, found 3 values) StrNCmpIA (correct 0 times, found 3 values) Shell_NotifyIconA (correct 0 times, found 5 values) ShellExecuteA (correct 0 times, found 5 values) ShellExecuteEx (correct 0 times, found 5 values) SheChangeDirA (correct 0 times, found 5 values) StrStrIA (correct 0 times, found 3 values) SheChangeDirExA (correct 0 times, found 5 values) ShellAboutA (correct 0 times, found 5 values) SheChangeDirExW (correct 0 times, found 5 values) ShellExecuteExW (correct 0 times, found 5 values) StrNCmpW (correct 0 times, found 3 values) StrChrW (correct 0 times, found 3 values) DragQueryFile (correct 0 times, found 5 values) StrRStrW (correct 0 times, found 3 values) StrCpyNW (correct 0 times, found 3 values) DragQueryFileA (correct 0 times, found 5 values) StrNCpyA (correct 0 times, found 3 values) DragQueryFileW (correct 0 times, found 5 values) Shell_NotifyIcon (correct 0 times, found 5 values) StrStrIW (correct 0 times, found 3 values) SHGetDataFromIDListW (correct 0 times, found 5 values) SheGetDirExW (correct 0 times, found 5 values) SheFullPathW (correct 0 times, found 5 values) SheRemoveQuotesA (correct 0 times, found 5 values) SheShortenPathW (correct 0 times, found 5 values) StrRStrA (correct 0 times, found 3 values) StrCmpNIW (correct 0 times, found 3 values) StrRChrW (correct 0 times, found 3 values) SheSetCurDrive (correct 0 times, found 5 values) StrRChrIW (correct 0 times, found 3 values) DragQueryPoint (correct 0 times, found 5 values) StrRChrA (correct 0 times, found 3 values)
APIs which have the wrong ordinal ---------------------------------
This check collates a list of Windows ordinals for the API exactly as above. But it emits a warning about the API only if it found a single ordinal value on Windows and that ordinal does not match Wine's ordinal.
These 1 APIs have the wrong ordinal: ReadCabinetState (is 654 on api2003es)
(may be best to ignore this one)
APIs which should have the -noname property --------------------------------------------
Again this check concerns APIs which have both an explicit ordinal and a name. This time it counts the number of Windows platforms where the API is not exported by name but which still have an entry point with the right ordinal and no name.
If more than one such platforms were found, the script considers the API should have the '-noname' property.
These 28 APIs should have the -noname property: SHRegOpenKeyW (507 has no name on api95 api98 apint4) SHGetNetResource (69 has no name on all) DAD_SetDragImageFromListView (177 has no name on all) ReceiveAddToRecentDocs (647 has no name on api95 api98 apime apint4 api2000) SHRegQueryValueExW (511 has no name on api95 api98 apint4) PifMgr_GetProperties (10 has no name on api95 api98 apime apint4 api2000 apixp) SHChangeRegistrationReceive (646 has no name on all) RestartDialogEx (730 has no name on apixp) SHRegQueryValueA (508 has no name on api95 api98 apint4) SHWaitOp_Operate (648 has no name on all) SHNetConnectionDialog (160 has no name on all) InvalidateDriveType (65 has no name on all) SHRegCloseKey (505 has no name on api95 api98 apint4) SHHandleDiskFull (185 has no name on all) SHFindComputer (91 has no name on all) SHRegQueryValueW (510 has no name on api95 api98 apint4) SHGlobalDefect (197 has no name on all) PifMgr_OpenProperties (9 has no name on api95 api98 apime apint4 api2000 apixp) SHRegQueryValueExA (509 has no name on api95 api98 apint4) PifMgr_SetProperties (11 has no name on api95 api98 apime apint4 api2000 apixp) SHCreatePropSheetExtArrayEx (194 has no name on all) RealDriveTypeFlags (525 has no name on all) SHChangeNotifyReceive (643 has no name on all) SHRegOpenKeyA (506 has no name on api95 api98 apint4) SHIsBadInterfacePtr (84 has no name on all) SHRegDeleteKeyW (512 has no name on apint4) PifMgr_CloseProperties (13 has no name on api95 api98 apime apint4 api2000 apixp) DragQueryInfo (76 has no name on all)
APIs which should not have the -noname property ------------------------------------------------
This the same check as above but with a different analysis of the results. Namely, the script considers the API should not have the -noname property if one of the following two conditions is met: * the API is exported by name on all platforms * the API's ordinal corresponds to another API on one of the platforms.
These 33 APIs should not have the -noname property: FileMenu_AppendItem (115 has other names on apixp api2003es) FileMenu_Create (114 has other names on apixp api2003es) DragFinish FileMenu_DeleteItemByFirstID (141 has other names on apixp api2003es) FileMenu_DrawItem (105 has other names on apixp api2003es) FileMenu_DeleteAllItems (104 has other names on apixp api2003es) FileMenu_DeleteItemByCmd (117 has other names on apixp api2003es) FileMenu_DeleteItemByIndex (140 has other names on apixp api2003es) FileMenu_DeleteSeparator (142 has other names on apixp api2003es) FileMenu_ReplaceUsingPidl (113 has other names on apixp api2003es) FileMenu_MeasureItem (112 has other names on apixp api2003es) ILAppend (154 has other names on api2003es) FileMenu_AppendFilesForPidl (124 has other names on apixp api2003es) DragAcceptFiles FileMenu_InitMenuPopup (109 has other names on apixp api2003es) FileMenu_AbortInitMenu (120 has other names on apixp api2003es) FileMenu_GetLastSelectedItemPidls (107 has other names on apixp api2003es) FileMenu_EnableItemByCmd (143 has other names on apixp api2003es) FileMenu_HandleMenuChar (108 has other names on apixp api2003es) Shell_GetImageList (71 has other names on api2003es) FileMenu_GetItemExtent (144 has other names on apixp api2003es) FileMenu_TrackPopupMenuEx (116 has other names on apixp api2003es) DragQueryFile FileMenu_FindSubMenuByPidl (106 has other names on apixp api2003es) FileMenu_Invalidate (111 has other names on apixp api2003es) DragQueryFileA DragQueryFileW FileMenu_AddFilesForPidl (125 has other names on api95 api98 apime apint4 api2000 apixp api2003es) FileMenu_Destroy (118 has other names on apixp api2003es) ShellDDEInit (188 has other names on api95 api98 apint4) DragQueryPoint FileMenu_InsertUsingPidl (110 has other names on apixp api2003es) IsUserAdmin (680 has other names on api2003es)
Missing APIs ------------
The script only reports an API as missing if it is present on all platforms but missing from Wine's spec file. That's per Wine's policy to not add APIs that are only present on newer platforms unless we have a good reason to.
These 2 APIs are missing: SHInvokePrinterCommandW SHInvokePrinterCommandA
Francois Gouget fgouget@free.fr writes:
-noname vs. ordinal internal consistency
This check verifies that all APIs which have the '-noname' property, also have an explicit ordinal. This is the only check which does not depend on dumps of the Windows dlls.
Actually this is enforced by winebuild, so you will never find a problem here.
On Mon, 21 Feb 2005, Alexandre Julliard wrote:
Francois Gouget fgouget@free.fr writes:
-noname vs. ordinal internal consistency
This check verifies that all APIs which have the '-noname' property, also have an explicit ordinal. This is the only check which does not depend on dumps of the Windows dlls.
Actually this is enforced by winebuild, so you will never find a problem here.
Ok. I've removed it. Do the other checks make sense to you? Are they useful? Any other useful tests to perform?
Francois Gouget fgouget@free.fr writes:
On Mon, 21 Feb 2005, Alexandre Julliard wrote:
Francois Gouget fgouget@free.fr writes:
-noname vs. ordinal internal consistency
This check verifies that all APIs which have the '-noname' property, also have an explicit ordinal. This is the only check which does not depend on dumps of the Windows dlls.
Actually this is enforced by winebuild, so you will never find a problem here.
Ok. I've removed it. Do the other checks make sense to you? Are they useful? Any other useful tests to perform?
Yes I think they are very useful, though I wouldn't suggest blindly fixing things based on the reports since I suspect that at least in some cases we have wrong ordinals and this will cause complaints about the wrong functions. We should definitely strive to make the checks pass as much as possible, but doing that will require a careful analysis of each case.
Another very useful test would be the ability that you mentioned to correlate with the MS import libs too, but that's not trivial to do.
On Mon, 21 Feb 2005, Alexandre Julliard wrote: [...]
Yes I think they are very useful, though I wouldn't suggest blindly fixing things based on the reports since I suspect that at least in some cases we have wrong ordinals and this will cause complaints about the wrong functions.
It turns out that a lot of the functions my script complains should have the -noname or not have the -noname property should: * really not have a name at all * or be marked as -private
Is this something we want to do?
This is shown by this small program which fails to link using the SDK's shell32.lib file:
__declspec(dllimport) int __stdcall DoEnvironmentSubst(int, int); __declspec(dllimport) int __stdcall FileMenu_AbortInitMenu(); __declspec(dllimport) int __stdcall Shell_GetImageList(int, int); __declspec(dllimport) int __stdcall SHRegCloseKey(int);
int main() { DoEnvironmentSubst(0,0); FileMenu_AbortInitMenu(); Shell_GetImageList(0,0); SHRegCloseKey(0); return 0; }
Similarly in kernel32.spec we have a bunch of entry-points for Windows 9x APIs which Windows exports by ordinal only. However these APIs are given names:
1 stdcall -register -i386 VxDCall0(long) VxDCall 24 stdcall GlobalAlloc16(long long)
That seems wrong since none of the kernel32 dlls ever exports a VxDCall0 or GlobalAlloc16 function. Shouldn't this be written as follows instead?
1 stdcall -register -i386 @(long) VxDCall 24 stdcall @(long long) GlobalAlloc16
The drawback is that this is going to make it harder to use these APIs from other dlls (as in one would have to use GetProcAddress())... Is this something we want to do anyway? Maybe just for the functions which are not called from other dlls?
Francois Gouget fgouget@free.fr writes:
It turns out that a lot of the functions my script complains should have the -noname or not have the -noname property should:
- really not have a name at all
- or be marked as -private
Is this something we want to do?
No, I don't think there's any harm in exporting all the functions we know about.
Similarly in kernel32.spec we have a bunch of entry-points for Windows 9x APIs which Windows exports by ordinal only. However these APIs are given names:
1 stdcall -register -i386 VxDCall0(long) VxDCall 24 stdcall GlobalAlloc16(long long)
That seems wrong since none of the kernel32 dlls ever exports a VxDCall0 or GlobalAlloc16 function. Shouldn't this be written as follows instead?
1 stdcall -register -i386 @(long) VxDCall 24 stdcall @(long long) GlobalAlloc16
Using -noname would be preferable.