Monday, September 17, 2007

How to fix an ordinal error

Most of the time if your are using an SDK to build your application that doesn't match with the current Windows CE binary image you are using to run this application, your application could not be launched and you have an ordinal error :
"Function @ Ordinal 1788 missing in Module 'coredll.dll'"
That's mean that your application is using a Win32 API that was available in the SDK but is definitively not available in your image. So a Component is missing in the OSDesign.

How could I find the missing function ?

To find the missing component you have to find where ordinals are defined for the coredll.dll (the Dll containing the most common Win32 APIs). When you are building a Dynamic Library (DLL) you always have to provide the entry points of the final binary file, as you can have private and public procedures in a DLL, the public functions are definied in a def file using by the linker to export those entry points.
For the Coredll.dll library each function is associated to an ordinal, so in the Coredll.def file you will find all the Win32 entry points.

Where to locate the coredll.def file ?

The Coredll.def file will be proceed during the sysgen phase of the build, so depending on the components you selected in the OSDesign some functions will be disabled by CESYSGEN filtering. That's the main goal of the sysgen. So instead of looking at the resultant file, you have to look at the original one.
This file is located in :
_WINCEROOT\PUBLIC\COMMON\OAK\LIB\_CPUDEPPATH
Depending on the processor family of your target device, you will not have the same content as some functions have aliases depending on the processor for which it is compiled for.

How could I identify the missing component ?

Open the coredll.def file corresponding to the processor family you are using and search for the missing ordinal. In our case we are looking for ordinal 1788.
....
; @CESYSGEN IF SHELLSDK_MODULES_AYGSHELL
; AYGSHELL thunks
SHDoneButtonI=xxx_SHDoneButton @1782
SHGetAppKeyAssocI=xxx_SHGetAppKeyAssoc @1783
SHSetAppKeyWndAssocI=xxx_SHSetAppKeyWndAssoc @1784
SHSetNavBarTextI=xxx_SHSetNavBarText @1785
SHSipPreferenceI=xxx_SHSipPreference @1786
NotSystemParametersInfoI=xxx_NotSystemParametersInfo @1787
SHCloseAppsI=xxx_SHCloseApps @1788
SHNotificationAddI=xxx_SHNotificationAdd @1806
SHNotificationUpdateI=xxx_SHNotificationUpdate @1807
SHNotificationRemoveI=xxx_SHNotificationRemove @1808
SHNotificationGetDataI=xxx_SHNotificationGetData @1809
; @CESYSGEN ENDIF
....

After locating the correct ordinal in the file scroll up to the previous @CESYSGEN IF statement. This one is used to include those APIs only in the case of the IF statement is evaluated to TRUE. In our case the SHELLSDK_MODULES_AYGSHELL variable must be set to have access to those APIs.

Most of the time the name of the variable is explicit enough to identify the component linked to it. In that case we identify the AYGSHELL component name. But some times it more complex to identify the module associated with.
So next time we will look more in details in the deptree mechanism to identify component and sysgen variables naming convention.

Stay connected ...

- Nicolas

1 comment:

Cormac said...

Thanks man this totally saved me time and money. You are the coolest guy I know. You are totally worth the MVP status. I hope some day I will get the chance to meet you and buy you a drink. wait...I already have. Seriously though, it did help me solve an ordinal error.