CE 5.0: unresolved external symbol __imp__CeGetVolumeInfoW referenced in function WinMain

It turns out that we shipped Windows CE 5.0 with a mistake in the coredll .def file: the CeGetVolumeInfo API should have been exported as CeGetVolumeInfoW instead of CeGetVolumeInfo. This mistake causes link errors when building executables that statically import this API due to an inconsistency with the function definition in storemgr.h.

The link errors will look something like this:

BUILD: [01:0000000047:ERRORE] test.obj : error LNK2019: unresolved external symbol __imp__CeGetVolumeInfoW referenced in function WinMain

If you find that you're encountering this problem, here are a couple of simple ways to work-around the problem locally in your application.

Solution 1: Import the API at Run-Time

This is the cleaner of the two solutions, but involves a bit of code. Basically, you need to remove your static references to CeGetVolumeInfo and instead reference the API indirectly through a function pointer. You'll want to import the funciton by ordinal (1978) if you want your app to run on all post-5.0 version of CE because the fix required changing the name of the export (the ordinal will never change).

Example:

// Funciton pointer type for the CeGetVolumeInfo API.

typedef BOOL (*PCE_GET_VOLUME_INFO) (LPCWSTR, CE_VOLUME_INFO_LEVEL, LPCE_VOLUME_INFO);

BOOL MyCeGetVolumeInfoWrapper (LPCWSTR pszRootPath, CE_VOLUME_INFO_LEVEL InfoLevel, LPCE_VOLUME_INFO lpVolumeInfo)

{

static PCE_GET_VOLUME_INFO s_pfnCeGetVolumeInfo = NULL;

if (!s_pfnCeGetVolumeInfo)

{

// COREDLL is always loaded, so use GetModuleHandle instead of LoadLibrary

HMODULE hCoreDll = GetModuleHandleW (L"COREDLL.DLL");

if (hCoreDll)

{

// Get a pointer to the CeGetVolumeInfo function using its ordinal.

s_pfnCeGetVolumeInfo = (PCE_GET_VOLUME_INFO) GetProcAddressW (hCoreDll, (LPCWSTR)1978);

}

}

if (s_pfnCeGetVolumeInfo)

{

return s_pfnCeGetVolumeInfo (pszRootPath, InfoLevel, lpVolumeInfo);

}

else

{

// Unable to get the export from COREDLL, check SYSGEN variables.

return FALSE;

}

}

If the above funciton is implemented locally, your application can simply invoke it instead of CeGetVolumeInfo and achieve the same result.

Solution 2: Locally Redefine the API

This is the easier of the two solutions. Just undefine and redefine the API in a local header file:

#include <bldver.h>

#if (CE_MAJOR_VER == 0x5) && (CE_MINOR_VER == 0x0)

#undef CeGetVolumeInfo

WINBASEAPI BOOL CeGetVolumeInfo(IN LPCWSTR pszRootPath, IN CE_VOLUME_INFO_LEVEL InfoLevel, OUT LPCE_VOLUME_INFO lpVolumeInfo);

#endif

Note that in Windows Mobile 5 and Windows CE 6, this problem is fixed and the API is properly exported from COREDLL as CeGetVolumeInfoW. So you will only need this work-around when building for CE 5.0 (hence the version checks).

Questions/comments?