UTILS.C

/*++ 

Copyright (c) 1997 Microsoft Corporation

Module Name:

utils.c

Abstract:

This source file implements utility functions used by scrnsave.c.

Author:

Jim Schmidt (jimschm) 11-Apr-1997

Revision History:


--*/

#include "pch.h"

#ifdef UNICODE
#error UNICODE cannot be defined
#endif

//
// Declare strings
//

#define DEFMAC(var,str) CHAR var[] = str;
DEFINE_STRINGS
#undef DEFMAC

//
// Temporary buffer
//

static CHAR g_Data[MAX_PATH];

//
// Buffer for string representation of registry keys (for error logging)
//

typedef struct _tagKEYTOSTR {
struct _tagKEYTOSTR *Prev, *Next;
HKEY Key;
CHAR RegKey[];
} KEYTOSTR, *PKEYTOSTR;

static PKEYTOSTR g_Head = NULL;

VOID
pAddKeyToStrMapping (
IN HKEY Key,
IN LPCSTR RootStr,
IN LPCSTR KeyStr
)
{
PKEYTOSTR Node;
DWORD Size;
CHAR FullKeyStr[MAX_PATH];

// We control RootStr and KeyStr, so we know it is less than MAX_PATH in length
wsprintf (FullKeyStr, "%s\\%s", RootStr, KeyStr);

Size = sizeof (KEYTOSTR) + CountStringBytes (FullKeyStr);

Node = (PKEYTOSTR) HeapAlloc (g_hHeap, 0, Size);
if (Node) {
Node->Prev = NULL;
Node->Next = g_Head;
Node->Key = Key;
_mbscpy (Node->RegKey, FullKeyStr);

if (g_Head) {
g_Head->Prev = Node;
}
g_Head = Node;
}
}

PKEYTOSTR
pFindKeyToStrMapping (
IN HKEY Key
)
{
PKEYTOSTR Node;

Node = g_Head;
while (Node) {
if (Node->Key == Key) {
return Node;
}
Node = Node->Next;
}

return NULL;
}

VOID
pRemoveKeyToStrMapping (
IN HKEY Key
)
{
PKEYTOSTR Node;

Node = pFindKeyToStrMapping (Key);
if (!Node) {
return;
}

if (Node->Prev) {
Node->Prev->Next = Node->Next;
} else {
g_Head = Node->Next;
}

if (Node->Next) {
Node->Next->Prev = Node->Prev;
}

HeapFree (g_hHeap, 0, Node);
}


VOID
LogRegistryError (
IN HKEY Key,
IN LPCSTR ValueName
)
{
DWORD rc = GetLastError();
CHAR Msg[512];
LPCSTR FullKeyStr;
PKEYTOSTR Node;

Node = pFindKeyToStrMapping (Key);
if (Node) {
FullKeyStr = Node->RegKey;
} else {
FullKeyStr = S_DEFAULT_KEYSTR;
}

wsprintf (Msg, S_REGISTRY_ERROR, g_User, rc, FullKeyStr, ValueName);
SetupLogError (Msg, LogSevError);
}


VOID
GenerateFilePaths (
VOID
)
{
INT Len;

// Safety (unexpected condition)
if (!g_WorkingDirectory) {
return;
}

Len = CountStringBytes (g_WorkingDirectory) + sizeof(S_SETTINGS_MASK);
g_SettingsFile = (LPSTR) HeapAlloc (g_hHeap, 0, Len);
if (!g_SettingsFile) {
return;
}
wsprintf (g_SettingsFile, S_SETTINGS_MASK, g_WorkingDirectory);

Len = CountStringBytes (g_WorkingDirectory) + sizeof(S_MIGINF_MASK);
g_MigrateDotInf = (LPSTR) HeapAlloc (g_hHeap, 0, Len);
if (!g_MigrateDotInf) {
return;
}
wsprintf (g_MigrateDotInf, S_MIGINF_MASK, g_WorkingDirectory);
}


HKEY
OpenRegKey (
IN HKEY RootKey,
IN LPCSTR KeyStr
)
{
HKEY Key;
LONG rc;

rc = RegOpenKeyEx (RootKey, KeyStr, 0, KEY_ALL_ACCESS, &Key);
if (rc != ERROR_SUCCESS) {
SetLastError (rc);
return NULL;
}

pAddKeyToStrMapping (Key, S_HKR, KeyStr);

return Key;
}


HKEY
CreateRegKey (
IN HKEY RootKey,
IN LPCSTR KeyStr
)
{
HKEY Key;
LONG rc;
DWORD DontCare;

pAddKeyToStrMapping (NULL, S_HKR, KeyStr);

rc = RegCreateKeyEx (RootKey, KeyStr, 0, S_EMPTY, 0,
KEY_ALL_ACCESS, NULL, &Key, &DontCare);
if (rc != ERROR_SUCCESS) {
SetLastError (rc);
LogRegistryError (NULL, S_EMPTY);
pRemoveKeyToStrMapping (NULL);
return NULL;
}

pRemoveKeyToStrMapping (NULL);
pAddKeyToStrMapping (Key, S_HKR, KeyStr);

return Key;
}

VOID
CloseRegKey (
IN HKEY Key
)
{
pRemoveKeyToStrMapping (Key);
RegCloseKey (Key);
}


LPCSTR
GetRegValueString (
IN HKEY Key,
IN LPCSTR ValueName
)
{
static CHAR DataBuf[MAX_PATH];
DWORD Size;
LONG rc;
DWORD Type;
DWORD d;

Size = MAX_PATH;
rc = RegQueryValueEx (Key, ValueName, NULL, &Type, DataBuf, &Size);
SetLastError (rc);

if (rc != ERROR_SUCCESS) {
return NULL;
}

if (Type == REG_DWORD) {
d = *((PDWORD) DataBuf);
wsprintf (DataBuf, "%u", d);
}
else if (Type != REG_SZ) {
return NULL;
}

return DataBuf;
}

BOOL
SetRegValueString (
HKEY Key,
LPCSTR ValueName,
LPCSTR ValueStr
)
{
LONG rc;
LPCSTR p;

p = _mbschr (ValueStr, 0);
p++;

rc = RegSetValueEx (Key, ValueName, 0, REG_SZ, ValueStr, p - ValueStr);
SetLastError (rc);

if (rc != ERROR_SUCCESS) {
LogRegistryError (Key, ValueName);
}

return rc == ERROR_SUCCESS;
}


LPCSTR
GetScrnSaveExe (
VOID
)
{
CHAR IniFileSetting[MAX_PATH];

GetPrivateProfileString (
S_BOOT,
S_SCRNSAVE_EXE,
S_EMPTY,
IniFileSetting,
MAX_PATH,
S_SYSTEM_INI
);

if (!IniFileSetting[0]) {
return NULL;
}

if (!OurGetLongPathName (IniFileSetting, g_Data)) {
// File does not exist
return NULL;
}

return g_Data[0] ? g_Data : NULL;
}

INT
_mbsbytes (
IN LPCSTR str
)
{
LPCSTR p;

// Find the nul terminator and return the number of bytes
// occupied by the characters in the string, but don't
// include the nul.

p = _mbschr (str, 0);
return (p - str);
}


DWORD
CountStringBytes (
IN LPCSTR str
)
{
// Return bytes in string, plus 1 for the nul
return _mbsbytes (str) + 1;
}

DWORD
CountMultiStringBytes (
IN LPCSTR str
)
{
LPCSTR p;
INT Total = 0;
INT Bytes;

p = str;

do {
Bytes = CountStringBytes (p);
p += Bytes;
Total += Bytes;
} while (Bytes > 1);

return Total;
}


LPSTR
CopyStringAtoB (
OUT LPSTR mbstrDest,
IN LPCSTR mbstrStart,
IN LPCSTR mbstrEnd // first char NOT to copy
)
{
LPSTR mbstrOrg;

mbstrOrg = mbstrDest;

// Assume mbstrEnd is on a lead byte

while (mbstrStart < mbstrEnd) {
if (isleadbyte (*mbstrStart)) {
*mbstrDest = *mbstrStart;
mbstrDest++;
mbstrStart++;
}

*mbstrDest = *mbstrStart;
mbstrDest++;
mbstrStart++;
}

*mbstrDest = 0;

return mbstrOrg;
}

LPSTR
AppendStr (
OUT LPSTR mbstrDest,
IN LPCSTR mbstrSrc
)

{
// Advance mbstrDest to end of string
mbstrDest = _mbschr (mbstrDest, 0);

// Copy string
while (*mbstrSrc) {
*mbstrDest = *mbstrSrc++;
if (isleadbyte (*mbstrDest)) {
mbstrDest++;
*mbstrDest = *mbstrSrc++;
}
mbstrDest++;
}

*mbstrDest = 0;

return mbstrDest;
}


BOOL
pFindShortName (
IN LPCTSTR WhatToFind,
OUT LPTSTR Buffer
)
{
WIN32_FIND_DATA fd;
HANDLE hFind;

hFind = FindFirstFile (WhatToFind, &fd);
if (!hFind) {
return FALSE;
}

FindClose (hFind);
_mbscpy (Buffer, fd.cFileName);

return TRUE;
}


BOOL
OurGetLongPathName (
IN LPCSTR ShortPath,
OUT LPSTR Buffer
)
{
CHAR FullPath[MAX_PATH];
LPSTR FilePart;
LPSTR BufferEnd;
LPSTR p, p2;
CHAR c;

//
// Convert ShortPath into complete path name
//

if (!_mbschr (ShortPath, TEXT('\\'))) {
if (!SearchPath (NULL, ShortPath, NULL, MAX_PATH, FullPath, &FilePart)) {
return FALSE;
}
} else {
GetFullPathName (ShortPath, MAX_PATH, FullPath, &FilePart);
}

//
// Convert short path to long path
//

p = FullPath;

// Don't process non-local paths
if (!(*p) || _mbsnextc (_mbsinc (p)) != TEXT(':')) {
_mbscpy (Buffer, FullPath);
return TRUE;
}

p = _mbsinc (p);
p = _mbsinc (p);
if (_mbsnextc (p) != TEXT('\\')) {
_mbscpy (Buffer, FullPath);
return TRUE;
}

// Copy drive letter to buffer
p = _mbsinc (p);
CopyStringAtoB (Buffer, FullPath, p);
BufferEnd = _mbschr (Buffer, 0);

// Convert each portion of the path
do {
// Locate end of this file or dir
p2 = _mbschr (p, TEXT('\\'));
if (!p2) {
p = _mbschr (p, 0);
} else {
p = p2;
}

// Look up file
c = *p;
*p = 0;
if (!pFindShortName (FullPath, BufferEnd)) {
return FALSE;
}
*p = c;

// Move on to next part of path
BufferEnd = _mbschr (BufferEnd, 0);
if (*p) {
p = _mbsinc (p);
BufferEnd = AppendStr (BufferEnd, TEXT("\\"));
}
} while (*p);

return TRUE;
}


BOOL
CreateScreenSaverParamKey (
IN LPCSTR ScreenSaverName,
IN LPCSTR ValueName,
OUT LPSTR Buffer
)
{
//
// Make sure we cannot create a string bigger than MAX_PATH
//

if (_mbslen (ScreenSaverName) + 4 + _mbslen (ValueName) > MAX_PATH) {
return FALSE;
}

//
// Format the string with length of screen saver name, screen saver name,
// and value name.
//

wsprintf (Buffer, "%03u/%s/%s", _mbslen (ScreenSaverName), ScreenSaverName, ValueName);

return TRUE;
}

BOOL
DecodeScreenSaverParamKey (
IN LPCSTR EncodedString,
OUT LPSTR ScreenSaverName,
OUT LPSTR ValueName
)
{
INT Len;

//
// Validate encoded string. It is in the form of ###/screen saver name/value name.
//

Len = atoi (EncodedString);
if (Len < 0 || Len >= MAX_PATH || (Len - 5) > (INT) _mbslen (EncodedString)) {
return FALSE;
}

if (EncodedString[3] != '/' || EncodedString[4 + Len] != '/') {
return FALSE;
}

if (_mbslen (EncodedString + 5 + Len) >= MAX_PATH) {
return FALSE;
}

//
// Extract screen saver name and value name
//

_mbsncpy (ScreenSaverName, EncodedString + 4, Len);
ScreenSaverName[Len] = 0;

_mbscpy (ValueName, EncodedString + 5 + Len);
return TRUE;
}

LPSTR
_mbsistr (
IN LPCSTR mbstrStr,
IN LPCSTR mbstrSubStr
)
{
LPCSTR mbstrStart, mbstrStrPos, mbstrSubStrPos;
LPCSTR mbstrEnd;

mbstrEnd = (LPSTR) ((LPBYTE) mbstrStr + _mbsbytes (mbstrStr) - _mbsbytes (mbstrSubStr));

for (mbstrStart = mbstrStr ; mbstrStart <= mbstrEnd ; mbstrStart = _mbsinc (mbstrStart)) {
mbstrStrPos = mbstrStart;
mbstrSubStrPos = mbstrSubStr;

while (*mbstrSubStrPos &&
_mbctolower ((INT) _mbsnextc (mbstrSubStrPos)) == _mbctolower ((INT) _mbsnextc (mbstrStrPos)))
{
mbstrStrPos = _mbsinc (mbstrStrPos);
mbstrSubStrPos = _mbsinc (mbstrSubStrPos);
}

if (!(*mbstrSubStrPos))
return (LPSTR) mbstrStart;
}

return NULL;
}

VOID
DeletePartOfString (
IN LPSTR Buffer,
IN DWORD CharsToDelete
)
{
LPSTR p;
DWORD d;

p = Buffer;
for (d = 0 ; *p && d < CharsToDelete ; d++) {
p = _mbsinc (p);
}

if (!(*p)) {
*Buffer = 0;
} else {
MoveMemory (Buffer, p, CountStringBytes(p));
}
}

VOID
InsertStringInString (
IN LPSTR Buffer,
IN LPCSTR StringToInsert
)
{
DWORD BytesToMove;
DWORD BytesOfInsertedString;

BytesToMove = CountStringBytes (Buffer);
BytesOfInsertedString = _mbsbytes(StringToInsert);
MoveMemory (Buffer + BytesOfInsertedString,
Buffer,
BytesToMove
);
_mbsncpy (Buffer, StringToInsert, _mbslen (StringToInsert));
}


VOID
ConvertSystemToSystem32 (
IN OUT LPSTR FileName
)
{
LPSTR p;

// look for \system\ in the path somewhere
p = _mbsistr (FileName, S_SYSTEM_DIR);
if (p) {
// Remove "\system\" and replace with "\system32\"
DeletePartOfString (p, _mbslen (S_SYSTEM_DIR));
InsertStringInString (p, S_SYSTEM32_DIR);
}
}