NT4/private/windows/base/advapi/group32.c
2020-09-30 17:12:29 +02:00

1180 lines
36 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
group32.c
Abstract:
This module contains routines for reading/writing 32-bit Windows/NT
groups that are stored in the registry.
Author:
Steve Wood (stevewo) 22-Feb-1993
Revision History:
--*/
#include "advapi.h"
#include <stdio.h>
#include <winbasep.h>
#include "win31io.h"
#define BMR_ICON 1
#define BMR_DEVDEP 0
#define ROUND_UP( X, A ) (((DWORD)(X) + (A) - 1) & ~((A) - 1))
#define PAGE_SIZE 4096
#define PAGE_NUMBER( A ) ((DWORD)(A) / PAGE_SIZE)
typedef int (WINAPI *PGETSYSTEMMETRICS)(
int nIndex
);
PGETSYSTEMMETRICS lpGetSystemMetrics;
ULONG
QueryNumberOfPersonalGroupNames(
HANDLE CurrentUser,
PHANDLE GroupNamesKey,
PHANDLE SettingsKey
)
{
NTSTATUS Status;
UNICODE_STRING KeyName, ValueName;
OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR ValueNameBuffer[ 16 ];
KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
ULONG ResultLength, NumberOfPersonalGroups;
RtlInitUnicodeString( &KeyName, L"SoftWare\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\UNICODE Groups" );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
CurrentUser,
NULL
);
Status = NtOpenKey( GroupNamesKey,
STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&ObjectAttributes
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return 0;
}
RtlInitUnicodeString( &KeyName, L"SoftWare\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\Settings" );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
CurrentUser,
NULL
);
Status = NtOpenKey( SettingsKey,
STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&ObjectAttributes
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
NtClose( *GroupNamesKey );
return 0;
}
for (NumberOfPersonalGroups=1; ; NumberOfPersonalGroups++) {
swprintf( ValueNameBuffer, L"Group%d", NumberOfPersonalGroups );
RtlInitUnicodeString( &ValueName, ValueNameBuffer );
Status = NtQueryValueKey( *GroupNamesKey,
&ValueName,
KeyValuePartialInformation,
(PVOID)&KeyValueInformation,
sizeof( KeyValueInformation ),
&ResultLength
);
if (Status == STATUS_BUFFER_OVERFLOW) {
Status = STATUS_SUCCESS;
}
if (!NT_SUCCESS( Status ) ||
KeyValueInformation.Type != REG_SZ
) {
break;
}
}
return NumberOfPersonalGroups - 1;
}
BOOL
NewPersonalGroupName(
HANDLE GroupNamesKey,
PWSTR GroupName,
ULONG GroupNumber
)
{
NTSTATUS Status;
UNICODE_STRING ValueName;
WCHAR ValueNameBuffer[ 16 ];
if (GroupNumber >= CGROUPSMAX) {
SetLastError( ERROR_TOO_MANY_NAMES );
return FALSE;
}
swprintf( ValueNameBuffer, L"Group%d", GroupNumber );
RtlInitUnicodeString( &ValueName, ValueNameBuffer );
Status = NtSetValueKey( GroupNamesKey,
&ValueName,
0,
REG_SZ,
GroupName,
(wcslen( GroupName ) + 1) * sizeof( WCHAR )
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return FALSE;
}
else {
return TRUE;
}
}
BOOL
DoesExistGroup(
HANDLE GroupsKey,
PWSTR GroupName
)
{
NTSTATUS Status;
UNICODE_STRING KeyName, ValueName;
HANDLE Key;
OBJECT_ATTRIBUTES ObjectAttributes;
KEY_VALUE_FULL_INFORMATION KeyValueInformation;
ULONG ResultLength;
RtlInitUnicodeString( &KeyName, GroupName );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
GroupsKey,
NULL
);
Status = NtOpenKey( &Key,
GENERIC_READ,
&ObjectAttributes
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return FALSE;
}
RtlInitUnicodeString( &ValueName, L"" );
Status = NtQueryValueKey( Key,
&ValueName,
KeyValueFullInformation,
&KeyValueInformation,
sizeof( KeyValueInformation ),
&ResultLength
);
NtClose( Key );
if (!NT_SUCCESS( Status ) && Status != STATUS_BUFFER_OVERFLOW) {
BaseSetLastNTError( Status );
return FALSE;
}
else
if (KeyValueInformation.Type != REG_BINARY ||
KeyValueInformation.DataLength > 0xFFFF
) {
return FALSE;
}
else {
return TRUE;
}
}
PGROUP_DEF
LoadGroup(
HANDLE GroupsKey,
PWSTR GroupName
)
{
PGROUP_DEF Group;
NTSTATUS Status;
UNICODE_STRING KeyName, ValueName;
HANDLE Key;
OBJECT_ATTRIBUTES ObjectAttributes;
PVOID Base;
KEY_VALUE_FULL_INFORMATION KeyValueInformation;
ULONG ResultLength;
RtlInitUnicodeString( &KeyName, GroupName );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
GroupsKey,
NULL
);
Status = NtOpenKey( &Key,
GENERIC_READ,
&ObjectAttributes
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return NULL;
}
RtlInitUnicodeString( &ValueName, L"" );
Status = NtQueryValueKey( Key,
&ValueName,
KeyValueFullInformation,
&KeyValueInformation,
sizeof( KeyValueInformation ),
&ResultLength
);
if (!NT_SUCCESS( Status )) {
if (Status == STATUS_BUFFER_OVERFLOW) {
Status = STATUS_SUCCESS;
}
else {
NtClose( Key );
BaseSetLastNTError( Status );
return NULL;
}
}
if (KeyValueInformation.Type != REG_BINARY ||
KeyValueInformation.DataLength > 0xFFFF
) {
NtClose( Key );
return NULL;
}
Base = VirtualAlloc( NULL, 0xFFFF, MEM_RESERVE, PAGE_READWRITE );
if (Base == NULL ||
!VirtualAlloc( Base, KeyValueInformation.DataLength, MEM_COMMIT, PAGE_READWRITE )
) {
if (Base != NULL) {
VirtualFree( Base, 0, MEM_RELEASE );
}
NtClose( Key );
return NULL;
}
Status = NtQueryValueKey( Key,
&ValueName,
KeyValueFullInformation,
&KeyValueInformation,
KeyValueInformation.DataLength,
&ResultLength
);
NtClose( Key );
if (!NT_SUCCESS( Status )) {
VirtualFree( Base, 0, MEM_RELEASE );
return NULL;
}
else {
Group = (PGROUP_DEF)((PCHAR)Base + KeyValueInformation.DataOffset);
//
// Set total size of group
//
Group->wReserved = (WORD)(ResultLength - KeyValueInformation.DataOffset);
RtlMoveMemory( Base, Group, Group->wReserved );
return (PGROUP_DEF)Base;
}
}
BOOL
SaveGroup(
HANDLE GroupsKey,
PWSTR GroupName,
PGROUP_DEF Group
)
{
NTSTATUS Status;
UNICODE_STRING KeyName, ValueName;
HANDLE Key;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG CreateDisposition;
LONG ValueLength;
RtlInitUnicodeString( &KeyName, GroupName );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
GroupsKey,
NULL
);
Status = NtCreateKey( &Key,
STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&ObjectAttributes,
0,
NULL,
0,
&CreateDisposition
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return FALSE;
}
ValueLength = (LONG)((ULONG)Group->wReserved);
Group->wReserved = 0;
Group->wCheckSum = (WORD)-ValueLength;
RtlInitUnicodeString( &ValueName, L"" );
Status = NtSetValueKey( Key,
&ValueName,
0,
REG_BINARY,
Group,
ValueLength
);
Group->wReserved = (WORD)ValueLength;
Group->wCheckSum = 0;
NtClose( Key );
if (!NT_SUCCESS( Status )) {
return FALSE;
}
else {
return TRUE;
}
}
BOOL
DeleteGroup(
HANDLE GroupsKey,
PWSTR GroupName
)
{
NTSTATUS Status;
UNICODE_STRING KeyName;
HANDLE Key;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString( &KeyName, GroupName );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
GroupsKey,
NULL
);
Status = NtOpenKey( &Key,
STANDARD_RIGHTS_WRITE |
DELETE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&ObjectAttributes
);
if (!NT_SUCCESS( Status )) {
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
return TRUE;
}
else {
BaseSetLastNTError( Status );
return FALSE;
}
}
Status = NtDeleteKey( Key );
NtClose( Key );
if (!NT_SUCCESS( Status )) {
return FALSE;
}
else {
return TRUE;
}
}
BOOL
UnloadGroup(
PGROUP_DEF Group
)
{
return VirtualFree( Group, 0, MEM_RELEASE );
}
BOOL
ExtendGroup(
PGROUP_DEF Group,
BOOL AppendToGroup,
DWORD cb
)
{
PBYTE Start, Commit, End;
if (((DWORD)Group->wReserved + cb) > 0xFFFF) {
return FALSE;
}
Start = (PBYTE)Group + Group->cbGroup;
End = Start + cb;
if (PAGE_NUMBER( Group->wReserved ) != PAGE_NUMBER( Group->wReserved + cb )) {
Commit = (PBYTE)ROUND_UP( (PBYTE)Group + Group->wReserved, PAGE_SIZE );
if (!VirtualAlloc( Commit, ROUND_UP( cb, PAGE_SIZE ), MEM_COMMIT, PAGE_READWRITE )) {
return FALSE;
}
}
if (!AppendToGroup) {
memmove( End, Start, Group->wReserved - Group->cbGroup );
}
Group->wReserved += (WORD)cb;
return TRUE;
}
WORD
AddDataToGroup(
PGROUP_DEF Group,
PBYTE Data,
DWORD cb
)
{
WORD Offset;
if (cb == 0) {
cb = strlen( Data ) + 1;
}
cb = ROUND_UP( cb, sizeof( DWORD ) );
if (!ExtendGroup( Group, FALSE, cb )) {
return 0;
}
if (((DWORD)Group->cbGroup + cb) > 0xFFFF) {
return 0;
}
Offset = Group->cbGroup;
Group->cbGroup += (WORD)cb;
if (Data != NULL) {
memmove( (PBYTE)Group + Offset, Data, cb );
}
else {
memset( (PBYTE)Group + Offset, 0, cb );
}
return Offset;
}
BOOL
AddTagToGroup(
PGROUP_DEF Group,
WORD wID,
WORD wItem,
WORD cb,
PBYTE rgb
)
{
WORD Offset;
PTAG_DEF Tag;
cb = (WORD)(ROUND_UP( cb, sizeof( DWORD ) ));
Offset = Group->wReserved;
if (!ExtendGroup( Group, TRUE, FIELD_OFFSET( TAG_DEF, rgb[ 0 ] ) + cb )) {
return FALSE;
}
Tag = (PTAG_DEF)PTR( Group, Offset );
Tag->wID = wID;
Tag->dummy1 = 0;
Tag->wItem = (int)wItem;
Tag->dummy2 = 0;
if (cb != 0 || rgb != NULL) {
Tag->cb = (WORD)(cb + FIELD_OFFSET( TAG_DEF, rgb[ 0 ] ));
memmove( &Tag->rgb[ 0 ], rgb, cb );
}
else {
Tag->cb = 0;
}
return TRUE;
}
ULONG MonoChromePalette[] = {
0x00000000, 0x00ffffff
};
BITMAPINFOHEADER DefaultQuestionIconBIH = {
0x00000028,
0x00000020,
0x00000040,
0x0001,
0x0004,
0x00000000,
0x00000280,
0x00000000,
0x00000000,
0xFFFFFFFF,
0x00000000
};
ULONG DefaultQuestionIconBits[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000
, 0x00000000, 0x33000000, 0x00000030, 0x00000000
, 0x00000000, 0xbb080000, 0x00000083, 0x00000000
, 0x00000000, 0xff0b0000, 0x000000b3, 0x00000000
, 0x00000000, 0xff0b0000, 0x000000b3, 0x00000000
, 0x00000000, 0xbb000000, 0x00000080, 0x00000000
, 0x00000000, 0x00000000, 0x00000000, 0x00000000
, 0x00000000, 0x00000000, 0x00000000, 0x00000000
, 0x00000000, 0x00000000, 0x00000000, 0x00000000
, 0x00000000, 0x33000000, 0x00000030, 0x00000000
, 0x00000000, 0xbb080000, 0x00000083, 0x00000000
, 0x00000000, 0xbb0b0000, 0x000000b3, 0x00000000
, 0x00000000, 0xff0b0000, 0x000000b3, 0x00000000
, 0x00000000, 0xff0b0000, 0x000030b8, 0x00000000
, 0x00000000, 0xbf000000, 0x000083bb, 0x00000000
, 0x00000000, 0xbf000000, 0x0033b8fb, 0x00000000
, 0x00000000, 0x0b000000, 0x33b8bbbf, 0x00000000
, 0x00000000, 0x00000000, 0xb3bbfbbb, 0x00000030
, 0x00000000, 0x00000000, 0xbbbbbb00, 0x00000030
, 0x00000000, 0x00000000, 0xbbbb0000, 0x00000083
, 0x00000000, 0x00000000, 0xbb0b0000, 0x000000b3
, 0x00000000, 0x00003033, 0xbb0b0000, 0x000000b3
, 0x08000000, 0x000083bb, 0xbb0b0000, 0x000000b3
, 0x0b000000, 0x0000b3bb, 0xbb0b0000, 0x000000b3
, 0x0b000000, 0x0030b8ff, 0xbb3b0000, 0x000000b3
, 0x0b000000, 0x0083bbff, 0xbb8b0300, 0x000000b3
, 0x00000000, 0x33b8fbbf, 0xbbbb3833, 0x00000080
, 0x00000000, 0xbbbbffbb, 0xb8bbbbbb, 0x00000030
, 0x00000000, 0xbbffbf0b, 0x83bbbbbb, 0x00000000
, 0x00000000, 0xffbf0b00, 0x00b8bbff, 0x00000000
, 0x00000000, 0xbb0b0000, 0x0000b8bb, 0x00000000
, 0x00000000, 0x00000000, 0x00000000, 0x00000000
, 0xff7ffcff, 0xff3ff8ff, 0xff1ff0ff, 0xff1ff0ff
, 0xff1ff0ff, 0xff3ff8ff, 0xff7ffcff, 0xffffffff
, 0xff7ffcff, 0xff3ff8ff, 0xff1ff0ff, 0xff1ff0ff
, 0xff1ff0ff, 0xff0ff0ff, 0xff03f8ff, 0xff00f8ff
, 0x7f00fcff, 0x3f00feff, 0x3f00ffff, 0x1fc0ffff
, 0x1ff01fff, 0x1ff00ffe, 0x1ff007fc, 0x1ff007fc
, 0x1fe003fc, 0x1f0000fc, 0x3f0000fe, 0x3f0000fe
, 0x7f0000ff, 0xff0080ff, 0xff03e0ff, 0xff0ff8ff
};
BOOL
ConvertIconBits(
PCURSORSHAPE_16 pIconHeader
);
BOOL
ConvertIconBits(
PCURSORSHAPE_16 pIconHeader
)
{
PBYTE Src;
UINT cbScanLine;
UINT nScanLine;
UINT i, j, k;
PBYTE Plane0;
PBYTE Plane1;
PBYTE Plane2;
PBYTE Plane3;
PBYTE p;
BYTE Color0, Color1, Color2, Color3, FourColor, FourColorPlane[ 32 * 4 * 4 ];
Src = (PBYTE)(pIconHeader + 1) + (pIconHeader->cbWidth * pIconHeader->cy);
cbScanLine = (((pIconHeader->cx * pIconHeader->BitsPixel + 31) & ~31) / 8);
nScanLine = pIconHeader->cy;
if (pIconHeader->Planes != 4) {
return FALSE;
}
else
if (pIconHeader->BitsPixel != 1) {
return FALSE;
}
else
if (pIconHeader->cx != pIconHeader->cy) {
return FALSE;
}
else
if (nScanLine != 32) {
return FALSE;
}
else
if (cbScanLine != 4) {
return FALSE;
}
Plane0 = (PBYTE)Src;
Plane1 = Plane0 + cbScanLine;
Plane2 = Plane1 + cbScanLine;
Plane3 = Plane2 + cbScanLine;
p = &FourColorPlane[ 0 ];
j = nScanLine;
while (j--) {
k = cbScanLine;
while (k--) {
Color0 = *Plane0++;
Color1 = *Plane1++;
Color2 = *Plane2++;
Color3 = *Plane3++;
i = 4;
while (i--) {
FourColor = 0;
if (Color0 & 0x80) {
FourColor |= 0x10;
}
if (Color1 & 0x80) {
FourColor |= 0x20;
}
if (Color2 & 0x80) {
FourColor |= 0x40;
}
if (Color3 & 0x80) {
FourColor |= 0x80;
}
if (Color0 & 0x40) {
FourColor |= 0x01;
}
if (Color1 & 0x40) {
FourColor |= 0x02;
}
if (Color2 & 0x40) {
FourColor |= 0x04;
}
if (Color3 & 0x40) {
FourColor |= 0x08;
}
Color0 <<= 2;
Color1 <<= 2;
Color2 <<= 2;
Color3 <<= 2;
*p++ = FourColor;
}
}
Plane0 += 3 * cbScanLine;
Plane1 += 3 * cbScanLine;
Plane2 += 3 * cbScanLine;
Plane3 += 3 * cbScanLine;
}
memmove( Src, &FourColorPlane[ 0 ], sizeof( FourColorPlane ) );
pIconHeader->BitsPixel = 4;
pIconHeader->Planes = 1;
pIconHeader->cbWidth = cbScanLine * 4;
return TRUE;
}
VOID
CopyIconBits(
PBYTE Dst,
PBYTE Src,
UINT cbScanLine,
UINT nScanLine
);
VOID
CopyIconBits(
PBYTE Dst,
PBYTE Src,
UINT cbScanLine,
UINT nScanLine
)
{
Src += (cbScanLine * nScanLine);
while (nScanLine--) {
Src -= cbScanLine;
memcpy( Dst, Src, cbScanLine );
Dst += cbScanLine;
}
}
typedef struct _WIN31_GROUP_ITEM_DESC {
LPSTR GroupName;
LPSTR ItemName;
} WIN31_GROUP_ITEM_DESC, *PWIN31_GROUP_ITEM_DESC;
WIN31_GROUP_ITEM_DESC GroupItemsToIgnore[] = {
{"Main", "File Manager"},
{NULL, "Control Panel"},
{NULL, "Print Manager"},
{NULL, "ClipBook Viewer"},
{NULL, "MS-DOS Prompt"},
{NULL, "Windows Setup"},
{NULL, "Read Me"},
{"Accessories", "Paintbrush"},
{NULL, "Write"},
{NULL, "Terminal"},
{NULL, "Notepad"},
{NULL, "Recorder"},
{NULL, "Clock"},
{NULL, "Object Packager"},
{NULL, "Media Player"},
{NULL, "Sound Recorder"},
{"Network", NULL},
{NULL, NULL}
};
PGROUP_DEF
CreateGroupFromGroup16(
LPSTR GroupName,
PGROUP_DEF16 Group16
)
{
PWIN31_GROUP_ITEM_DESC p1, ItemsToIgnore;
PGROUP_DEF Group;
PITEM_DEF Item;
PITEM_DEF16 Item16;
PTAG_DEF16 Tag16;
DWORD cb;
PBYTE p;
LPSTR s;
UINT i;
PCURSORSHAPE_16 pIconHeader;
PBITMAPINFOHEADER pbmi;
BOOL bUserDefaultIcon, bItemConvertedOkay;
int imagesize, colorsize, masksize, bmisize;
ItemsToIgnore = NULL;
p1 = GroupItemsToIgnore;
while (p1->GroupName || p1->ItemName) {
if (p1->GroupName &&
!_stricmp( p1->GroupName, GroupName )
) {
if (p1->ItemName == NULL) {
return (PGROUP_DEF)-1;
}
ItemsToIgnore = p1;
break;
}
p1 += 1;
}
Group = VirtualAlloc( NULL, 0xFFFF, MEM_RESERVE, PAGE_READWRITE );
if (Group == NULL) {
return NULL;
}
if (!VirtualAlloc( Group,
cb = FIELD_OFFSET( GROUP_DEF, rgiItems[ 0 ] ),
MEM_COMMIT,
PAGE_READWRITE
)
) {
VirtualFree( Group, 0, MEM_RELEASE );
return NULL;
}
cb = ROUND_UP( cb, sizeof( DWORD ) );
Group->wReserved = (WORD)cb;
Group->cbGroup = (WORD)cb;
Group->cItems = (Group16->cItems + NSLOTS - 1) & ~(NSLOTS-1);
AddDataToGroup( Group, NULL, (Group->cItems * sizeof( Group->rgiItems[ 0 ] )) );
Group->pName = AddDataToGroup( Group,
GroupName,
0
);
Group->dwMagic = GROUP_MAGIC;
Group->wCheckSum = 0; /* adjusted later... */
Group->nCmdShow = SW_SHOWMINIMIZED; // Group16->nCmdShow;
Group->wIconFormat = Group16->wIconFormat;
if (lpGetSystemMetrics == NULL) {
lpGetSystemMetrics = (PGETSYSTEMMETRICS)GetProcAddress( LoadLibrary( "user32.dll" ),
"GetSystemMetrics"
);
if (lpGetSystemMetrics == NULL) {
lpGetSystemMetrics = (PGETSYSTEMMETRICS)-1;
}
}
if (lpGetSystemMetrics != (PGETSYSTEMMETRICS)-1) {
Group->cxIcon = (WORD)(*lpGetSystemMetrics)(SM_CXICON);
Group->cyIcon = (WORD)(*lpGetSystemMetrics)(SM_CYICON);
}
Group->ptMin.x = (LONG)Group16->ptMin.x;
Group->ptMin.y = (LONG)Group16->ptMin.y;
Group->rcNormal.left = (int)Group16->rcNormal.Left;
Group->rcNormal.top = (int)Group16->rcNormal.Top;
Group->rcNormal.right = (int)Group16->rcNormal.Right;
Group->rcNormal.bottom = (int)Group16->rcNormal.Bottom;
for (i=0; i<Group16->cItems; i++) {
if (Group16->rgiItems[ i ] == 0) {
continue;
}
Item16 = ITEM16( Group16, i );
if (p1 = ItemsToIgnore) {
s = PTR( Group16, Item16->pName );
do {
if (!_stricmp( p1->ItemName, s )) {
s = NULL;
break;
}
p1 += 1;
}
while (p1->GroupName == NULL && p1->ItemName != NULL);
if (s == NULL) {
continue;
}
}
Group->rgiItems[ i ] = AddDataToGroup( Group, NULL, sizeof( ITEM_DEF ) );
if (Group->rgiItems[ i ] == 0) {
break;
}
Item = ITEM( Group, i );
Item->pt.x = (LONG)Item16->pt.x;
Item->pt.y = (LONG)Item16->pt.y;
Item->idIcon = Item16->iIcon;
Item->indexIcon = Item16->iIcon;
Item->wIconVer = 3;
bUserDefaultIcon = FALSE;
pIconHeader = (PCURSORSHAPE_16)PTR( Group16, Item16->pHeader );
if (pIconHeader->Planes != 1) {
if (!ConvertIconBits( pIconHeader )) {
KdPrint(("WIN31IO: Invalid 16-bit item icon at %08x\n", pIconHeader ));
bUserDefaultIcon = TRUE;
}
}
else
if (pIconHeader->BitsPixel != 1 &&
pIconHeader->BitsPixel != 4 &&
pIconHeader->BitsPixel != 8
) {
bUserDefaultIcon = TRUE;
}
if (!bUserDefaultIcon) {
bmisize = sizeof( BITMAPINFOHEADER );
imagesize = Item16->cbXORPlane;
masksize = Item16->cbANDPlane;
if (pIconHeader->BitsPixel == 1) {
colorsize = sizeof( MonoChromePalette );
}
else {
colorsize = 0;
}
Item->cbIconRes = (WORD)(bmisize +
colorsize +
imagesize +
masksize
);
Item->cbIconRes = (WORD)ROUND_UP( Item->cbIconRes, sizeof( DWORD ) );
Item->pIconRes = AddDataToGroup( Group, NULL, Item->cbIconRes );
if (Item->pIconRes != 0) {
p = PTR( Group, Item->pIconRes );
pbmi = (PBITMAPINFOHEADER)p;
pbmi->biSize = bmisize;
pbmi->biWidth = pIconHeader->cx;
pbmi->biHeight = pIconHeader->cy * 2;
pbmi->biPlanes = pIconHeader->Planes;
pbmi->biBitCount = pIconHeader->BitsPixel;
pbmi->biCompression = BI_RGB;
pbmi->biSizeImage = imagesize;
pbmi->biXPelsPerMeter = 0;
pbmi->biYPelsPerMeter = 0;
pbmi->biClrImportant = 0;
if (colorsize != 0) {
memcpy( p + bmisize, MonoChromePalette, colorsize );
pbmi->biClrUsed = 0;
}
else {
pbmi->biClrUsed = (DWORD)-1;
}
CopyIconBits( p + bmisize + colorsize,
(PBYTE)PTR( Group16, Item16->pXORPlane ),
(((pIconHeader->cx * pIconHeader->BitsPixel + 31) & ~31) / 8),
pIconHeader->cy
);
CopyIconBits( p + bmisize + colorsize + imagesize,
(PBYTE)PTR( Group16, Item16->pANDPlane ),
(((pIconHeader->cx + 31) & ~31) / 8),
pIconHeader->cy
);
}
}
else {
bmisize = sizeof( DefaultQuestionIconBIH );
imagesize = sizeof( DefaultQuestionIconBits );
Item->cbIconRes = bmisize + imagesize;
Item->cbIconRes = (WORD)ROUND_UP( Item->cbIconRes, sizeof( DWORD ) );
Item->pIconRes = AddDataToGroup( Group, NULL, Item->cbIconRes );
if (Item->pIconRes != 0) {
p = PTR( Group, Item->pIconRes );
memcpy( p, &DefaultQuestionIconBIH, bmisize );
memcpy( p + bmisize, &DefaultQuestionIconBits, imagesize );
}
}
bItemConvertedOkay = FALSE;
if (Item->pIconRes != 0) {
Item->pName = AddDataToGroup( Group,
PTR( Group16, Item16->pName ),
0
);
if (Item->pName != 0) {
Item->pCommand = AddDataToGroup( Group,
PTR( Group16, Item16->pCommand ),
0
);
if (Item->pCommand != 0) {
Item->pIconPath = AddDataToGroup( Group,
PTR( Group16, Item16->pIconPath ),
0
);
if (Item->pIconPath != 0) {
bItemConvertedOkay = TRUE;
}
}
}
}
if (!bItemConvertedOkay) {
break;
}
}
Tag16 = (PTAG_DEF16)((PBYTE)Group16 + Group16->cbGroup);
if (bItemConvertedOkay &&
Tag16->wID == ID_MAGIC && Tag16->wItem == ID_LASTTAG &&
*(UNALIGNED DWORD *)&Tag16->rgb[ 0 ] == PMTAG_MAGIC
) {
while (Tag16->wID != ID_LASTTAG) {
if (!AddTagToGroup( Group,
Tag16->wID,
Tag16->wItem,
(WORD)(Tag16->cb - FIELD_OFFSET( TAG_DEF16, rgb[ 0 ] )),
&Tag16->rgb[ 0 ]
)
) {
bItemConvertedOkay = FALSE;
break;
}
Tag16 = (PTAG_DEF16)((PBYTE)Tag16 + Tag16->cb);
}
if (bItemConvertedOkay) {
if (!AddTagToGroup( Group,
ID_LASTTAG,
0xFFFF,
0,
NULL
)
) {
bItemConvertedOkay = FALSE;
}
}
}
if (!bItemConvertedOkay) {
UnloadGroup( Group );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
else {
return Group;
}
}
#if DBG
BOOL
DumpGroup(
PWSTR GroupName,
PGROUP_DEF Group
)
{
PBITMAPINFOHEADER Icon;
PICON_HEADER16 Icon16;
PITEM_DEF Item;
PTAG_DEF Tag;
PULONG p;
int cb;
UINT i;
DbgPrint( "%ws - Group at %08x\n", GroupName, Group );
DbgPrint( " dwMagic: %08x\n", Group->dwMagic );
DbgPrint( " wCheckSum: %04x\n", Group->wCheckSum );
DbgPrint( " cbGroup: %04x\n", Group->cbGroup );
DbgPrint( " nCmdShow: %04x\n", Group->nCmdShow );
DbgPrint( " rcNormal: [%08x,%08x,%08x,%08x]\n",
Group->rcNormal.left,
Group->rcNormal.top,
Group->rcNormal.right,
Group->rcNormal.bottom
);
DbgPrint( " ptMin: [%08x,%08x]\n", Group->ptMin.x, Group->ptMin.y );
DbgPrint( " pName: [%04x] %s\n", Group->pName, Group->pName ? (PSZ)PTR( Group, Group->pName ) : "(null)" );
DbgPrint( " cxIcon: %04x\n", Group->cxIcon );
DbgPrint( " cyIcon: %04x\n", Group->cyIcon );
DbgPrint( " wIconFormat: %04x\n", Group->wIconFormat );
DbgPrint( " wReserved: %04x\n", Group->wReserved );
DbgPrint( " cItems: %04x\n", Group->cItems );
for (i=0; i<Group->cItems; i++) {
DbgPrint( " Item[ %02x ] at %04x\n", i, Group->rgiItems[ i ] );
if (Group->rgiItems[ i ] != 0) {
Item = ITEM( Group, i );
DbgPrint( " pt: [%08x, %08x]\n",
Item->pt.x,
Item->pt.y
);
DbgPrint( " idIcon: %04x\n", Item->idIcon );
DbgPrint( " wIconVer: %04x\n", Item->wIconVer );
DbgPrint( " cbIconRes:%04x\n", Item->cbIconRes );
DbgPrint( " indexIcon:%04x\n", Item->indexIcon );
DbgPrint( " dummy2: %04x\n", Item->dummy2 );
DbgPrint( " pIconRes: %04x\n", Item->pIconRes );
if (Item->wIconVer == 2) {
Icon16 = (PICON_HEADER16)PTR( Group, Item->pIconRes );
DbgPrint( " xHot: %04x\n", Icon16->xHotSpot );
DbgPrint( " yHot: %04x\n", Icon16->yHotSpot );
DbgPrint( " cx: %04x\n", Icon16->cx );
DbgPrint( " cy: %04x\n", Icon16->cy );
DbgPrint( " cbWid:%04x\n", Icon16->cbWidth );
DbgPrint( " Plane:%04x\n", Icon16->Planes );
DbgPrint( " BPP: %04x\n", Icon16->BitsPixel );
p = (PULONG)(Icon16+1);
cb = Item->cbIconRes - sizeof( *Icon16 );
}
else {
Icon = (PBITMAPINFOHEADER)PTR( Group, Item->pIconRes );
DbgPrint( " biSize : %08x\n", Icon->biSize );
DbgPrint( " biWidth : %08x\n", Icon->biWidth );
DbgPrint( " biHeight : %08x\n", Icon->biHeight );
DbgPrint( " biPlanes : %04x\n", Icon->biPlanes );
DbgPrint( " biBitCount : %04x\n", Icon->biBitCount );
DbgPrint( " biCompression : %08x\n", Icon->biCompression );
DbgPrint( " biSizeImage : %08x\n", Icon->biSizeImage );
DbgPrint( " biXPelsPerMeter: %08x\n", Icon->biXPelsPerMeter );
DbgPrint( " biYPelsPerMeter: %08x\n", Icon->biYPelsPerMeter );
DbgPrint( " biClrUsed : %08x\n", Icon->biClrUsed );
DbgPrint( " biClrImportant : %08x\n", Icon->biClrImportant );
p = (PULONG)(Icon+1);
cb = Item->cbIconRes - sizeof( *Icon );
}
DbgPrint( " dummy3: %04x\n", Item->dummy3 );
DbgPrint( " pName: [%04x] %s\n", Item->pName, PTR( Group, Item->pName ) );
DbgPrint( " pCommand:[%04x] %s\n", Item->pCommand, PTR( Group, Item->pCommand ) );
DbgPrint( " pIconPth:[%04x] %s\n", Item->pIconPath, PTR( Group, Item->pIconPath ) );
DbgPrint( " IconData: %04x bytes\n", cb );
while (cb > 0) {
DbgPrint( " %08x", *p++ );
cb -= sizeof( *p );
if (cb >= sizeof( *p )) {
cb -= sizeof( *p );
DbgPrint( " %08x", *p++ );
if (cb >= sizeof( *p )) {
cb -= sizeof( *p );
DbgPrint( " %08x", *p++ );
if (cb >= sizeof( *p )) {
cb -= sizeof( *p );
DbgPrint( " %08x", *p++ );
}
}
}
DbgPrint( "\n" );
}
}
}
Tag = (PTAG_DEF)((PBYTE)Group + Group->cbGroup);
if (Tag->wID == ID_MAGIC && Tag->wItem == ID_LASTTAG &&
*(LPDWORD)&Tag->rgb == PMTAG_MAGIC
) {
while (Tag->wID != ID_LASTTAG) {
DbgPrint( " Tag at %04x\n", (PBYTE)Tag - (PBYTE)Group );
DbgPrint( " wID: %04x\n", Tag->wID );
DbgPrint( " dummy1: %04x\n", Tag->dummy1 );
DbgPrint( " wItem: %08x\n", Tag->wItem );
DbgPrint( " cb: %04x\n", Tag->cb );
DbgPrint( " dummy2: %04x\n", Tag->dummy2 );
switch( Tag->wID ) {
case ID_MAGIC:
DbgPrint( " rgb: ID_MAGIC( %.4s )\n", Tag->rgb );
break;
case ID_WRITERVERSION:
DbgPrint( " rgb: ID_WRITERVERSION( %s )\n", Tag->rgb );
break;
case ID_APPLICATIONDIR:
DbgPrint( " rgb: ID_APPLICATIONDIR( %s )\n", Tag->rgb );
break;
case ID_HOTKEY:
DbgPrint( " rgb: ID_HOTKEY( %04x )\n", *(LPWORD)Tag->rgb );
break;
case ID_MINIMIZE:
DbgPrint( " rgb: ID_MINIMIZE()\n" );
break;
case ID_LASTTAG:
DbgPrint( " rgb: ID_LASTTAG()\n" );
break;
default:
DbgPrint( " rgb: unknown data format for this ID\n" );
break;
}
Tag = (PTAG_DEF)((PBYTE)Tag + Tag->cb);
}
}
return TRUE;
}
#endif // DBG