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; 
}