DATACONV.C

/*++ 

Copyright (c) 1997 Microsoft Corporation

Module Name:

dataconv.c

Abstract:

This source file implements data conversion routines that know
the format of Windows 95 screen saver settings and can convert
them to the Windows NT format.

Author:

Jim Schmidt (jimschm) 14-Apr-1997

Revision History:


--*/

#include "pch.h"

static CHAR g_Data[MAX_PATH];

BOOL
pHasSpecialProcessing (
IN LPCSTR ScreenSaverName
);

BOOL
pTranslateBezier (
IN HKEY RegRoot
);

BOOL
pTranslateMarquee (
IN HKEY RegRoot
);



HKEY
pCreateControlPanelKey (
IN HKEY RootKey,
IN LPCSTR SubKeyName,
IN BOOL CreateEmptyKey
)
{
CHAR FullRegKey[MAX_PATH];

wsprintf (FullRegKey, S_CONTROL_PANEL_MASK, SubKeyName);

if (CreateEmptyKey) {
RegDeleteKey (RootKey, FullRegKey);
}

return CreateRegKey (RootKey, FullRegKey);
}


HKEY
pCreateScreenSaverKey (
IN HKEY RegRoot,
IN LPCSTR ScreenSaverName
)
{
CHAR FullScreenSaverName[MAX_PATH];

wsprintf (FullScreenSaverName, S_SCRNSAVE_MASK, ScreenSaverName);
return pCreateControlPanelKey (RegRoot, FullScreenSaverName, FALSE);
}


BOOL
pCopyValuesFromSettingsFileToRegistry (
IN HKEY RegKeyRoot,
IN LPCSTR RegKeyName,
IN LPCSTR ScreenSaverName,
IN LPCSTR ValueArray[]
)
{
INT i;
CHAR IniKeyName[MAX_PATH];
HKEY RegKey;
BOOL b = TRUE;

//
// This function takes the values stored in our settings file and
// copies them to a brand new key in the NT registry.
//
// In the settings file, we store screen saver parameters in the
// format of <screen saver name len>/<screen saver name>/<parameter>=<value>.
//

//
// Create new registry key
//

RegKey = pCreateControlPanelKey (RegKeyRoot, RegKeyName, TRUE);
if (!RegKey) {
return FALSE;
}

//
// Copy values to reg key
//

for (i = 0 ; ValueArray[i] ; i++) {
if (!CreateScreenSaverParamKey (ScreenSaverName, ValueArray[i], IniKeyName)) {
// fail if screen saver name is huge for some unknown reason
SetupLogError (S_HUGEDATA_ERROR, LogSevWarning);
b = FALSE;
break;
}

GetSettingsFileVal (IniKeyName);
if (!SetRegValueString (RegKey, ValueArray[i], g_Data)) {
b = FALSE;
break;
}
}

CloseRegKey (RegKey);
return b;
}


BOOL
TranslateGeneralSetting (
IN HKEY RegKey,
IN LPCSTR Win9xSetting,
IN LPCSTR WinNTSetting
)
{
BOOL b = TRUE;

if (!WinNTSetting) {
WinNTSetting = Win9xSetting;
} else {
//
// Delete the Win9x setting that was copied to NT, ignore
// any failures.
//
RegDeleteValue (RegKey, Win9xSetting);
}

//
// Obtain setting from data file
//

if (GetSettingsFileVal (Win9xSetting)) {
//
// Save settings to registry
//

b = SetRegValueString (RegKey, WinNTSetting, g_Data);
}

return b;
}


typedef struct {
LPCSTR Win9xName;
LPCSTR WinNtName;
} FILE_TRANS, *PFILE_TRANS;

FILE_TRANS g_FileNameTranslation[] = {
// Win9x name // WinNT name (NULL=no change)
"black16.scr", NULL,
"Blank Screen.scr", "black16.scr",

"ssbezier.scr", NULL,
"Curves and Colors.scr", "ssbezier.scr",

"ssstars.scr", NULL,
"Flying Through Space.scr", "ssstars.scr",

"ssmarque.scr", NULL,
"Scrolling Marquee.scr", "ssmarque.scr",

"ssmyst.scr", NULL,
"Mystify Your Mind.scr", "ssmyst.scr",

NULL, NULL
};


LPCSTR
GetSettingsFileVal (
IN LPCSTR Key
)
{
GetPrivateProfileString (
g_User,
Key,
S_EMPTY,
g_Data,
MAX_PATH,
g_SettingsFile
);

return g_Data[0] ? g_Data : NULL;
}


BOOL
pTranslateScrName (
IN OUT LPSTR KeyName,
OUT LPSTR FullPath OPTIONAL
)
{
int i;

//
// Compare against translation list
//

for (i = 0 ; g_FileNameTranslation[i].Win9xName ; i++) {
if (!_mbsicmp (KeyName, g_FileNameTranslation[i].Win9xName)) {
break;
}
}

//
// Translate filename only if a match was found in our list
//

if (g_FileNameTranslation[i].Win9xName) {

//
// If WinNtName is NULL, there is no renaming necessary. Otherwise,
// use the NT name, which is always a file in system32.
//

if (g_FileNameTranslation[i].WinNtName && FullPath) {
// Rebuild path
GetSystemDirectory (FullPath, MAX_PATH);
_mbscat (FullPath, "\\");
_mbscat (FullPath, g_FileNameTranslation[i].WinNtName);
}

_mbscpy (KeyName, g_FileNameTranslation[i].WinNtName);
}
else if (FullPath) {
FullPath[0] = 0;
}

return TRUE;
}


BOOL
SaveScrName (
IN HKEY RegKey,
IN LPCSTR KeyName
)
{
LPSTR p;
CHAR FullPath[MAX_PATH];
CHAR ShortName[MAX_PATH];

//
// The Windows 95 screen saver names are different than
// Windows NT.
//

if (!GetSettingsFileVal (KeyName)) {
// Unexpected: .SCR name does not exist in our file
return TRUE;
}

//
// Locate the screen saver name within the full path
//

p = _mbsrchr (g_Data, '\\');
if (!p) {
p = g_Data;
} else {
p = _mbsinc (p);
}

//
// Translate it if necessary
//

if (!pTranslateScrName (p, FullPath)) {
return FALSE;
}

if (!FullPath[0]) {
//
// No change was made, so copy original path to FullPath
//

_mbscpy (FullPath, g_Data);
}

//
// Screen savers are always stored in short filename format
//

GetShortPathName (FullPath, ShortName, MAX_PATH);

return SetRegValueString (RegKey, KeyName, ShortName);
}

INT
GetHexDigit (
IN CHAR c
)
{
if (c >= '0' && c <= '9') {
return c - '0';
}

c = tolower (c);
if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
}

return -1;
}

BYTE
GetNextHexByte (
IN LPCSTR HexString,
OUT LPCSTR *HexStringReturn
)
{
INT a, b;

a = GetHexDigit (HexString[0]);
b = GetHexDigit (HexString[1]);

if (a == -1 || b == -1) {
*HexStringReturn = NULL;
return 0;
}

*HexStringReturn = &(HexString[2]);

return a * 16 + b;
}

BOOL
GetNextDword (
IN LPCSTR HexString,
OUT LPCSTR *HexStringReturn,
OUT PDWORD ValuePtr
)
{
INT i;
BYTE NextByte;

*ValuePtr = 0;

for (i = 0 ; i < 4 ; i++) {
NextByte = GetNextHexByte (HexString, &HexString);
if (!HexString) {
return FALSE;
}

*ValuePtr = ((*ValuePtr) << 8) | NextByte;
}

return TRUE;
}

BOOL
VerifyBezierChecksum (
IN LPCSTR HexString
)
{
BYTE Checksum = 0;
INT Len;

Len = _mbslen (HexString);
Len -= 2;

if (Len < 1) {
return FALSE;
}

while (Len > 0) {
Checksum += GetNextHexByte (HexString, &HexString);
if (!HexString) {
return FALSE;
}
}

if (Checksum != GetNextHexByte (HexString, &HexString)) {
return FALSE;
}

return TRUE;
}


BOOL
CopyUntranslatedSettings (
IN HKEY RegRoot
)
{
LPSTR KeyBuffer;
DWORD KeyBufferSize;
LPSTR p;
CHAR ScreenSaverName[MAX_PATH];
CHAR ValueName[MAX_PATH];
HKEY Key;

//
// Enumerate each entry in our private settings file for the user
//

KeyBufferSize = 32768;
KeyBuffer = (LPSTR) HeapAlloc (g_hHeap, 0, KeyBufferSize);
if (!KeyBuffer) {
return FALSE;
}

//
// Get all keys in the user's section
//

GetPrivateProfileString (
g_User,
NULL,
S_DOUBLE_EMPTY,
KeyBuffer,
KeyBufferSize,
g_SettingsFile
);

for (p = KeyBuffer ; *p ; p = _mbschr (p, 0) + 1) {
//
// Process only if key is encoded
//

if (!DecodeScreenSaverParamKey (p, ScreenSaverName, ValueName)) {
continue;
}

//
// Key is encoded, so perform migration!
//

pTranslateScrName (ScreenSaverName, NULL);

//
// Skip screen savers that have special processing
//

if (pHasSpecialProcessing (ScreenSaverName)) {
continue;
}

//
// Save the value to the registry
//

GetSettingsFileVal (p);

Key = pCreateScreenSaverKey (RegRoot, ScreenSaverName);
if (Key) {
if (SetRegValueString (Key, ValueName, g_Data))
{
CHAR DebugMsg[MAX_PATH*2];
wsprintf (DebugMsg, "Saved %s=%s\r\n", ValueName, g_Data);
SetupLogError (DebugMsg, LogSevInformation);
} else {
CHAR DebugMsg[MAX_PATH*2];
wsprintf (DebugMsg, "Could not save %s=%s\r\n", ValueName, g_Data);
SetupLogError (DebugMsg, LogSevError);
}

CloseRegKey (Key);
}
}

HeapFree (g_hHeap, 0, KeyBuffer);

return TRUE;
}


BOOL
pHasSpecialProcessing (
IN LPCSTR ScreenSaverName
)
{
//
// Return TRUE if we are doing something special for the
// named screen saver.
//

if (!_mbsicmp (ScreenSaverName, S_BEZIER) ||
!_mbsicmp (ScreenSaverName, S_MARQUEE)
) {
return TRUE;
}

return FALSE;
}


BOOL
TranslateScreenSavers (
IN HKEY RegRoot
)
{
BOOL b = TRUE;

b &= pTranslateBezier (RegRoot);
b &= pTranslateMarquee (RegRoot);

return b;
}


BOOL
pTranslateBezier (
IN HKEY RegRoot
)
{
DWORD Value;
CHAR StrValue[32];
LPCSTR p;
HKEY RegKey;
BOOL b;

//
// NT's Bezier has three settings:
//
// Length (REG_SZ) = Curve Count on Win9x
// LineSpeed (REG_SZ) = Speed on Win9x
// Width (REG_SZ) = Density on Win9x
//
// Win9x's Bezier has a big string of hex in the following format:
//
// Clear Screen Flag (DWORD)
// Random Colors Flag (DWORD)
// Curve Count (DWORD)
// Line Count (DWORD)
// Density (DWORD)
// Speed (DWORD)
// Current Color (DWORD RGB)
// Checksum (BYTE)
//

//
// Verify structure
//

GetSettingsFileVal (S_BEZIER_SETTINGS);

if (!VerifyBezierChecksum (g_Data)) {
return TRUE;
}

//
// Open reg key
//

RegKey = pCreateControlPanelKey (RegRoot, S_BEZIER_SETTINGS, TRUE);
if (!RegKey) {
return FALSE;
}

p = g_Data;

// Get clear screen flag (but ignore it)
b = GetNextDword (p, &p, &Value);

// Get random colors flag (but ignore it)
if (b) {
b = GetNextDword (p, &p, &Value);
}

//
// Get curve count
//

if (b) {
b = GetNextDword (p, &p, &Value);
}

if (b) {
wsprintf (StrValue, "%u", Value);
b = SetRegValueString (RegKey, S_LENGTH, StrValue);
}

// Get line count (but ignore it)
if (b) {
b = GetNextDword (p, &p, &Value);
}

//
// Get density
//

if (b) {
b = GetNextDword (p, &p, &Value);
}

if (b) {
wsprintf (StrValue, "%u", Value);
b = SetRegValueString (RegKey, S_WIDTH, StrValue);
}

//
// Get speed
//

if (b) {
b = GetNextDword (p, &p, &Value);
}

if (b) {
wsprintf (StrValue, "%u", Value);
b = SetRegValueString (RegKey, S_LINESPEED, StrValue);
}

CloseRegKey (RegKey);

if (!b) {
SetupLogError (S_BEZIER_DATA_ERROR, LogSevError);
}

return TRUE;
}


LPCSTR g_MarqueeValues[] = {
S_BACKGROUND_COLOR,
S_CHARSET,
S_FONT,
S_MODE,
S_SIZE,
S_SPEED,
S_TEXT,
S_TEXTCOLOR,
NULL
};


BOOL
pTranslateMarquee (
IN HKEY RegRoot
)
{
BOOL b;

//
// Marquee has the same settings on Win9x and NT. They just need
// to be copied from the control.ini file to the NT registry.
//

b = pCopyValuesFromSettingsFileToRegistry (
RegRoot,
S_MARQUEE_SETTINGS,
S_MARQUEE,
g_MarqueeValues
);

//
// We need to divide the speed by two to be compatible
//

if (b) {
HKEY MarqueeKey;
LPCSTR Value;
CHAR NewValue[32];

// Read the setting we just wrote in the registry
MarqueeKey = pCreateControlPanelKey (RegRoot, S_MARQUEE_SETTINGS, FALSE);

if (MarqueeKey) {
Value = GetRegValueString (MarqueeKey, S_SPEED);
if (Value) {
// Write speed divided by two
wsprintf (NewValue, "%i", atoi (Value) / 2);
SetRegValueString (MarqueeKey, S_SPEED, NewValue);
}

CloseRegKey (MarqueeKey);
}
}

return b;
}