/*++ 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(); LPCSTR FullKeyStr; PKEYTOSTR Node; Node = pFindKeyToStrMapping (Key); if (Node) { FullKeyStr = Node->RegKey; } else { FullKeyStr = S_DEFAULT_KEYSTR; } LOG ((LOG_ERROR, MSG_REGISTRY_ERROR, g_User, rc, FullKeyStr, ValueName)); } 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 == INVALID_HANDLE_VALUE) { 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)); } PCSTR ParseMessage ( UINT MessageId, ... ) { va_list list; PSTR RetStr = NULL; UINT RetStrSize; va_start (list, MessageId); RetStrSize = FormatMessageA ( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE, (PSTR) g_hInst, MessageId, 0, (PSTR) (&RetStr), 1, &list ); if (!RetStrSize && RetStr) { *RetStr = 0; } va_end (list); return RetStr; } VOID FreeMessage ( PCSTR Message ) { if (Message) { LocalFree ((PSTR) Message); } }