Article ID: 326163 - View products that this article applies to.
This article was previously published under Q326163
The module loader for Microsoft Windows CE devices uses an algorithm to load a DLL that is different from the algorithm that loads a DLL on the desktop versions of Windows. This applies to Handheld and Pocket PC devices based on Windows CE versions 2.x through 3.0.
A DLL may not load because of several reasons. This article focuses on what occurs when a lack of process address space (slot) exists for the DLLs that you request to load. You can use this information to help you troubleshoot why a DLL cannot load. Workarounds are described at the end of this article.
A DLL may not load for several reasons:
This article discusses how Windows CE loads a DLL so that you can understand why a DLL may not load because of a lack of address space on the part of the calling application. When an application lacks address space, LoadLibrary returns a NULL value. GetLastError returns error code 14, ERROR_OUTOFMEMORY.
Windows CE loads a DLL differently than Microsoft Windows 98, Microsoft Windows Millennium Edition, Microsoft Windows 2000, or Microsoft Windows XP do. Because of these differences, a DLL may not load although there appears to be enough memory or address space for the DLL.
The following two examples describe how Windows CE loads DLLs.
The process address space for an active Windows CE process begins at 0x00000000 and then ends at 0x02000000, for a total of 32 MB. You must share that address space with ROM-based DLLs, RAM-based DLLs, the EXE module for the process, stacks, heaps, and with any other allocations that you create for the process.
The size of the DLL file does not indicate the actual space that the DLL requires to load. You can determine the initial address space that you require to load a DLL when you run Dumpbin.exe for your DLL. dumpbin is a command-line tool that is included with eMbedded Visual Tools. dumpbin outputs information to the command window. The summary information includes the size of each section. To load the DLL, you must have address space equal to the sum of the section sizes plus 4 KB.
To determine where in a process address space to load a DLL, Windows CE finds the highest address and then seeks down until it finds enough free virtual address space to fit the DLL module. For example, on the Pocket PC 2002 device of one OEM, this address is 0x00AB0000. The address varies between different device makes and models. The device maker build tools of the Windows CE image automatically calculates the value.
Windows CE does not map a RAM-based DLL from anywhere between 0x02000000 and the address where the lowest ROM module is mapped.
The Windows CE loader ignores the image base address for the RAM-based DLL. When a DLL is compiled and linked, the linker writes an address that is labeled the "image base" in the portable executable (PE) header. The image base address tells the module loader the preferred address to load the DLL. Although the image base is present in the DLL file, the Windows CE loader does not use it.
When a DLL is loaded in one process, Windows CE reserves that address space in every process address space. Multiple processes that use the same DLL share it at the same relative address in every process. If your application does not use the same DLL, it cannot use the memory that is reserved for that DLL. In other words, Windows CE does not map a RAM-based DLL at an address where another process maps another DLL. For example, if Process A loads DLL X at address 0x00970000, Windows CE does not map DLL Y in the Process B address space at 0x00970000. Instead, Windows CE seeks the next lower address that is available, depending on the size of DLL Y. So if DLL Y is in the size range of 128 KB, Windows CE selects 0x00950000 if that address is available for Process B. Because of the way that Windows CE allows processes to share a common DLL, Windows CE does not permit two different processes to load two different DLLs at the same relative address of each process.
Before a DLL is mapped in memory the Windows CE loader resolves the implicit links to other DLLs, known as dependent DLLs. If any of those modules is not yet loaded, then Windows CE stops the load of the current DLL and starts the process to load the dependent DLLs. To do this, Windows CE uses the same algorithm recursively. This is one point where Windows CE is similar to desktop versions of Windows. It is mentioned here because a DLL may not load because of factors of the dependent DLLs, not the DLL itself.
If you determine that your application cannot load a DLL because of a lack of address space for the DLL, consider the following workarounds:
For additional information, click the following article numbers to view the articles in the Microsoft Knowledge Base:
(http://support.microsoft.com/kb/259932/EN-US/ )INFO: Process Space Usage by ROM-Based DLLs
(http://support.microsoft.com/kb/303444/EN-US/ )PRB: Using MEM_TOP_DOWN Flag With VirtualAlloc May Cause DLL Loading to Fail
(http://support.microsoft.com/kb/326162/EN-US/ )INFO: Address Space Layout of a Windows CE Process
Article ID: 326163 - Last Review: October 17, 2012 - Revision: 3.0