/*++ 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 #include #include "win31io.h" #define BMR_ICON 1 #define BMR_DEVDEP 0 #define ROUND_UP( X, A ) (((ULONG_PTR)(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 = (DWORD)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 = (DWORD)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; icItems; 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; icItems; 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