/*++ Copyright (c) 1996 Microsoft Corporation Module Name: scheme.c Abstract: Control Panel scheme converters The helper functions in this source file converts an ANSI- based Win95 scheme into a UNICODE-based NT scheme. Also supplied is a logical font converter, closely related to the scheme converter. Author: Jim Schmidt (jimschm) 9-Aug-1996 Revision History: --*/ #include "pch.h" #define COLOR_MAX_V1 25 #define COLOR_MAX_V3 25 #define COLOR_MAX_V4 29 #define COLOR_MAX_NT 29 // this is a modified version 2 format, similar to 4 // // Win95 uses a mix of LOGFONTA and a weird 16-bit LOGFONT // structure that uses SHORTs instead of LONGs. // typedef struct { SHORT lfHeight; SHORT lfWidth; SHORT lfEscapement; SHORT lfOrientation; SHORT lfWeight; BYTE lfItalic; BYTE lfUnderline; BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE lfQuality; BYTE lfPitchAndFamily; char lfFaceName[LF_FACESIZE]; } SHORT_LOGFONT, *PSHORT_LOGFONT; // // NT uses only UNICODE structures, and pads the members // to 32-bit boundaries. // typedef struct { SHORT version; // 2 for NT UNICODE WORD wDummy; // for alignment NONCLIENTMETRICSW ncm; LOGFONTW lfIconTitle; COLORREF rgb[COLOR_MAX_NT]; } SCHEMEDATA_NT, *PSCHEMEDATA_NT; // // Win95 uses NONCLIENTMETRICSA which has LOGFONTA members, // but it uses a 16-bit LOGFONT as well. // #pragma pack(push) #pragma pack(1) typedef struct { SHORT version; // 1 for Win95 ANSI NONCLIENTMETRICSA ncm; SHORT_LOGFONT lfIconTitle; COLORREF rgb[COLOR_MAX_V1]; } SCHEMEDATA_V1, *PSCHEMEDATA_V1; typedef struct { SHORT version; // 1 for Win95 ANSI NONCLIENTMETRICSA ncm; SHORT_LOGFONT lfIconTitle; COLORREF rgb[COLOR_MAX_V4]; } SCHEMEDATA_V1A, *PSCHEMEDATA_V1A; typedef struct { SHORT version; // 3 for Win98 ANSI, 4 for portable format WORD Dummy; NONCLIENTMETRICSA ncm; LOGFONTA lfIconTitle; COLORREF rgb[COLOR_MAX_V3]; } SCHEMEDATA_V3, *PSCHEMEDATA_V3; typedef struct { SHORT version; // 4 for Win32 format (whatever that means) WORD Dummy; NONCLIENTMETRICSA ncm; LOGFONTA lfIconTitle; COLORREF rgb[COLOR_MAX_V4]; } SCHEMEDATA_V4, *PSCHEMEDATA_V4; #pragma pack(pop) // // Some utility functions // void ConvertLF (LOGFONTW *plfDest, const LOGFONTA *plfSrc) { plfDest->lfHeight = plfSrc->lfHeight; plfDest->lfWidth = plfSrc->lfWidth; plfDest->lfEscapement = plfSrc->lfEscapement; plfDest->lfOrientation = plfSrc->lfOrientation; plfDest->lfWeight = plfSrc->lfWeight; plfDest->lfItalic = plfSrc->lfItalic; plfDest->lfUnderline = plfSrc->lfUnderline; plfDest->lfStrikeOut = plfSrc->lfStrikeOut; plfDest->lfCharSet = plfSrc->lfCharSet; plfDest->lfOutPrecision = plfSrc->lfOutPrecision; plfDest->lfClipPrecision = plfSrc->lfClipPrecision; plfDest->lfQuality = plfSrc->lfQuality; plfDest->lfPitchAndFamily = plfSrc->lfPitchAndFamily; MultiByteToWideChar (OurGetACP(), 0, plfSrc->lfFaceName, -1, plfDest->lfFaceName, sizeof (plfDest->lfFaceName) / sizeof (WCHAR)); } void ConvertLFShort (LOGFONTW *plfDest, const SHORT_LOGFONT *plfSrc) { plfDest->lfHeight = plfSrc->lfHeight; plfDest->lfWidth = plfSrc->lfWidth; plfDest->lfEscapement = plfSrc->lfEscapement; plfDest->lfOrientation = plfSrc->lfOrientation; plfDest->lfWeight = plfSrc->lfWeight; plfDest->lfItalic = plfSrc->lfItalic; plfDest->lfUnderline = plfSrc->lfUnderline; plfDest->lfStrikeOut = plfSrc->lfStrikeOut; plfDest->lfCharSet = plfSrc->lfCharSet; plfDest->lfOutPrecision = plfSrc->lfOutPrecision; plfDest->lfClipPrecision = plfSrc->lfClipPrecision; plfDest->lfQuality = plfSrc->lfQuality; plfDest->lfPitchAndFamily = plfSrc->lfPitchAndFamily; MultiByteToWideChar (OurGetACP(), 0, plfSrc->lfFaceName, -1, plfDest->lfFaceName, sizeof (plfDest->lfFaceName) / sizeof (WCHAR)); } VOID ConvertNonClientMetrics ( OUT NONCLIENTMETRICSW *Dest, IN NONCLIENTMETRICSA *Src ) { Dest->cbSize = sizeof (NONCLIENTMETRICSW); Dest->iBorderWidth = Src->iBorderWidth; Dest->iScrollWidth = Src->iScrollWidth; Dest->iScrollHeight = Src->iScrollHeight; Dest->iCaptionWidth = Src->iCaptionWidth; Dest->iCaptionHeight = Src->iCaptionHeight; Dest->iSmCaptionWidth = Src->iSmCaptionWidth; Dest->iSmCaptionHeight = Src->iSmCaptionHeight; Dest->iMenuWidth = Src->iMenuWidth; Dest->iMenuHeight = Src->iMenuHeight; ConvertLF (&Dest->lfCaptionFont, &Src->lfCaptionFont); ConvertLF (&Dest->lfSmCaptionFont, &Src->lfSmCaptionFont); ConvertLF (&Dest->lfMenuFont, &Src->lfMenuFont); ConvertLF (&Dest->lfStatusFont, &Src->lfStatusFont); ConvertLF (&Dest->lfMessageFont, &Src->lfMessageFont); } // // And now the scheme converter // BOOL ValFn_ConvertAppearanceScheme ( IN PDATAOBJECT ObPtr ) { SCHEMEDATA_NT sd_nt; PSCHEMEDATA_V1 psd_v1; PSCHEMEDATA_V3 psd_v3; PSCHEMEDATA_V4 psd_v4; PSCHEMEDATA_V1A psd_v1a; BOOL Copy3dValues = FALSE; psd_v1 = (PSCHEMEDATA_V1) ObPtr->Value.Buffer; // // Validate the size (must be a known size) // if (ObPtr->Value.Size != sizeof (SCHEMEDATA_V1) && ObPtr->Value.Size != sizeof (SCHEMEDATA_V3) && ObPtr->Value.Size != sizeof (SCHEMEDATA_V4) && ObPtr->Value.Size != sizeof (SCHEMEDATA_V1A) ) { DEBUGMSG (( DBG_WARNING, "ValFn_ConvertAppearanceScheme doesn't support scheme size of %u bytes. " "The supported sizes are %u, %u, %u, and %u.", ObPtr->Value.Size, sizeof (SCHEMEDATA_V1), sizeof (SCHEMEDATA_V1A), sizeof (SCHEMEDATA_V3), sizeof (SCHEMEDATA_V4) )); return TRUE; } // // Make sure the structure is a known version // if (psd_v1->version != 1 && psd_v1->version != 3 && psd_v1->version != 4) { DEBUGMSG (( DBG_WARNING, "ValFn_ConvertAppearanceScheme doesn't support version %u", psd_v1->version )); return TRUE; } // // Convert the structure // if (psd_v1->version == 1) { sd_nt.version = 2; ConvertNonClientMetrics (&sd_nt.ncm, &psd_v1->ncm); ConvertLFShort (&sd_nt.lfIconTitle, &psd_v1->lfIconTitle); ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb)); CopyMemory ( &sd_nt.rgb, &psd_v1->rgb, min (sizeof (psd_v1->rgb), sizeof (sd_nt.rgb)) ); Copy3dValues = TRUE; } else if (psd_v1->version == 3 && ObPtr->Value.Size == sizeof (SCHEMEDATA_V1A)) { psd_v1a = (PSCHEMEDATA_V1A) psd_v1; sd_nt.version = 2; ConvertNonClientMetrics (&sd_nt.ncm, &psd_v1a->ncm); ConvertLFShort (&sd_nt.lfIconTitle, &psd_v1a->lfIconTitle); ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb)); CopyMemory ( &sd_nt.rgb, &psd_v1a->rgb, min (sizeof (psd_v1a->rgb), sizeof (sd_nt.rgb)) ); Copy3dValues = TRUE; } else if (psd_v1->version == 3 && ObPtr->Value.Size == sizeof (SCHEMEDATA_V3)) { psd_v3 = (PSCHEMEDATA_V3) psd_v1; sd_nt.version = 2; ConvertNonClientMetrics (&sd_nt.ncm, &psd_v3->ncm); ConvertLF (&sd_nt.lfIconTitle, &psd_v3->lfIconTitle); ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb)); CopyMemory ( &sd_nt.rgb, &psd_v3->rgb, min (sizeof (psd_v3->rgb), sizeof (sd_nt.rgb)) ); Copy3dValues = TRUE; } else if (psd_v1->version == 4) { psd_v4 = (PSCHEMEDATA_V4) psd_v1; sd_nt.version = 2; ConvertNonClientMetrics (&sd_nt.ncm, &psd_v4->ncm); ConvertLF (&sd_nt.lfIconTitle, &psd_v4->lfIconTitle); ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb)); CopyMemory ( &sd_nt.rgb, &psd_v4->rgb, min (sizeof (psd_v4->rgb), sizeof (sd_nt.rgb)) ); } else { // not a possible case MYASSERT (FALSE); } if (Copy3dValues) { // // Make sure the NT structure has values for 3D colors // sd_nt.rgb[COLOR_HOTLIGHT] = sd_nt.rgb[COLOR_ACTIVECAPTION]; sd_nt.rgb[COLOR_GRADIENTACTIVECAPTION] = sd_nt.rgb[COLOR_ACTIVECAPTION]; sd_nt.rgb[COLOR_GRADIENTINACTIVECAPTION] = sd_nt.rgb[COLOR_INACTIVECAPTION]; } return ReplaceValue (ObPtr, (LPBYTE) &sd_nt, sizeof (sd_nt)); } // // And logfont converter // BOOL ValFn_ConvertLogFont ( IN PDATAOBJECT ObPtr ) { LOGFONTW lfNT; PSHORT_LOGFONT plf95; plf95 = (PSHORT_LOGFONT) ObPtr->Value.Buffer; if (ObPtr->Value.Size != sizeof (SHORT_LOGFONT)) { SetLastError (ERROR_SUCCESS); DEBUGMSG (( DBG_NAUSEA, "ValFn_ConvertLogFont skipped because data wasn't the right size. " "%u bytes, should be %u", ObPtr->Value.Size, sizeof (SHORT_LOGFONT) )); return FALSE; } ConvertLFShort (&lfNT, plf95); return ReplaceValue (ObPtr, (LPBYTE) &lfNT, sizeof (lfNT)); }