As I understand right shift does sign extension, thus signed negative numbers leave 1s, signed positive and unsigned numbers leave 0s in the upper bits.
Some test code:
For me it seems that there is still no need for a mask, because there is an unsigned cast in the macro definition: (DWORD)(a). So, why the need for the mask '& 0xFFFF' when we already have an unsigned cast?
typedef unsigned long DWORD;
typedef unsigned short WORD;
#define LOWORD(a) ((WORD)(a))
#define HIWORD(a) ((WORD)(((DWORD)(a) >> 16) & 0xFFFF))
int a=-1; // signed numbers are stored in two's complement, so this equals 0xFFFFFFFF
printf("a >> 16 == %X\n",a >> 16); // FFFFFFFF
printf("(DWORD)(a) >> 16 == %X\n",(DWORD)(a) >> 16); //FFFF
//upper bits are sign extended -> int a : signed
printf("a >> 16 == %X\n",a >> 16); // FFFFABCD
//no sign extension -> (DWORD) is an unsigned cast
printf("(DWORD)(a) >> 16 == %X\n",(DWORD)(a) >> 16); //ABCD