PRB: Linker Produces Unresolved External ChangeSelector Error

ID Number: Q72019

3.00

WINDOWS

docerr

Summary:

SYMPTOMS

When linking a application or a dynamic-link library (DLL) for the

Microsoft Windows environment, the Microsoft linker produces the

following error message:

error L2029: 'CHANGESELECTOR' : unresolved external

CAUSE

The program calls the ChangeSelector function. This function was

named PrestoChangoSelector in the kernel and in the LIBW.LIB

library. It was named ChangeSelector in the WINDOWS.H header file,

in the Microsoft Windows Software Development Kit (SDK)

documentation, and in the Windows SDK on-line help files.

RESOLUTION

Modify the code to call PrestoChangoSelector instead of

ChangeSelector. Add the following prototype to code compiled using

the WINDOWS.H header file from version 3.0 of the Windows SDK:

WORD PrestoChangoSelector(WORD, WORD);

More Information:

The documentation for ChangeSelector on page 4-24 of the "Microsoft

Windows Software Development Kit Reference--Volume 1" for Windows 3.0

is incorrect. The order of the parameters is reversed. This error has

been corrected in the documentation for PrestoChangoSelector on pages

750 and 751 of the "Microsoft Windows Software Development Kit:

Programmer's Reference, Volume 2: Functions" manual for Windows 3.1.

The following code fragment demonstrates how to change a data selector

into a code selector. The following code should be used only in a DLL

and it should be used only when absolutely necessary as in a Windows-

hosted programming environment. Directly manipulating selectors

violates preferred Windows programming practice.

Note: This code assumes that the WORD variable DATA_SELECTOR is the

selector for a block of data; in other words, an application called

GlobalAlloc to allocate a block of memory and stored the returned

handle (selector) in the DATA_SELECTOR variable.

WORD PrestoChangoSelector(WORD, WORD);

#include "windows.h"

...

WORD wCopyOfDataSelector;

WORD wSelectorToCode;

...

// When the AllocSelector function is called with a valid selector,

// the function copies the information associated with the selector to

// a new location in the descriptor table used by Windows, and returns

// this new location. Therefore, wCopyOfDataSelector is a second entry

// in the descriptor table that points to the globally allocated

// memory block.

if (wCopyOfDataSelector = AllocSelector(DATA_SELECTOR))

{

// PrestoChangoSelector toggles the bit in the descriptor table

// that specifies whether a block of memory is code or data.

// Therefore, wSelectorToCode is a modified version of

// wCopyOfDataSelector.

if (wSelectorToCode = PrestoChangoSelector(DATA_SELECTOR,

wCopyOfDataSelector))

{

... // call code pointed to by wSelectorToCode

if (FreeSelector(wCopyOfDataSelector))

return FALSE; // selector not freed

return TRUE; // everything worked!

}

}

WARNING: A selector created with the AllocSelector function is not

part of the Windows global arena and is not updated if memory movement

occurs. This could invalidate the new selector and terminate the

program with a general protection violation (GP-fault, Unrecoverable

Application Error, or UAE). The application can prevent memory from

moving by calling the GlobalFix function to fix the memory block in

the address space.

Additional reference words: 3.00