You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
599 lines
18 KiB
599 lines
18 KiB
//=--------------------------------------------------------------------------=
|
|
// (C) Copyright 1997-1998 Microsoft Corporation. All Rights Reserved.
|
|
// TriEdit SDK team
|
|
// Author: Yury Polyakovsky
|
|
// contact: [email protected]
|
|
//=--------------------------------------------------------------------------=
|
|
// Refcount support for DLLs
|
|
// Call: refcount < Install | Uninstall | CopyToClient | SetClient | ClearClient | Copy >, <registry key> [, <file name>[, <client subdirectory> I <destination for Copy>] | <component full path>]
|
|
// Call refcount.exe from an application's setup:
|
|
// Install : Increment ref-count for the component if it was not installed before by the app
|
|
// Uninstall : Decrement ref-count for the component if it was installed before by the app, deletes it if ref-count goes to 0
|
|
// CopyToClient : Copies the component to the application's directory (from the registry)
|
|
// SetClient : Set the flag in the registry that the component was installed by the application
|
|
// CreateDir : Checks on the directory "C:\Program Files\Common Files" and create one if it's not there
|
|
// ClearClient : Clear the flag in the registry that the component was installed by the application
|
|
// Copy: Copy to specified destination.
|
|
#include <ctype.h>
|
|
#include <windef.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <winbase.h>
|
|
#include <winreg.h>
|
|
#include <winuser.h>
|
|
#include <crtdbg.h>
|
|
#include <shlwapi.h>
|
|
#include "RefCount.h"
|
|
|
|
#define STRINGOP(func, param1, param2) (func(param1, param2, sizeof(param1)/sizeof(param1[0])))
|
|
#define STRINGOPL(func, param1, param2) (func(param1, param2, strlen(param1)))
|
|
#define SKIPSPACES(psz) {for (++psz; *psz == ' ' && *psz != '\0'; ++psz); if (!*psz) psz=NULL;}
|
|
BOOL PASCAL ReplaceFileOnReboot (LPCTSTR pszExisting, LPCTSTR pszNew);
|
|
|
|
int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance
|
|
HINSTANCE hPrevInstance, // handle to previous instance
|
|
LPSTR lpCmdLine, // pointer to command line
|
|
int nCmdShow) // show state of window);int main(int argc, char** argv)
|
|
{
|
|
_ASSERT(*lpCmdLine);
|
|
if (!*lpCmdLine)
|
|
{
|
|
// No command line
|
|
return 1;
|
|
}
|
|
|
|
CRefCount RefCount;
|
|
char szRegKey[MAX_PATH] = "";
|
|
char szRegInstalling[MAX_PATH] = "";
|
|
char szRegInstalled[MAX_PATH] = "";
|
|
char sz_AppPath[MAX_PATH] = "";
|
|
char sz_Application[MAX_PATH] = "";
|
|
char sz_Dir[MAX_PATH] = "";
|
|
char *pszAppPath = sz_AppPath;
|
|
char *pszApplication = sz_Application;
|
|
BOOL bMultiInstall = FALSE;
|
|
BOOL *pbInstallMode = &bMultiInstall;
|
|
DWORD dwValueSize = sizeof(sz_AppPath);
|
|
|
|
//_ASSERT(FALSE);
|
|
|
|
if (!STRINGOPL(_strnicmp, "CreateDir", lpCmdLine/*argv[1]*/))
|
|
{
|
|
dwValueSize = sizeof(sz_Application);
|
|
RefCount.ValueGet("SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "CommonFilesDir", (LPBYTE *)&pszApplication, &dwValueSize);
|
|
_ASSERT(pszApplication);
|
|
if (pszApplication)
|
|
{
|
|
if (!CreateDirectory(pszApplication, NULL))
|
|
DWORD dwError = GetLastError();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
LPSTR pszRegName = strchr(lpCmdLine, ',');
|
|
_ASSERT(pszRegName);
|
|
if (!pszRegName)
|
|
// command line not complete
|
|
return 1;
|
|
|
|
SKIPSPACES(pszRegName);
|
|
_ASSERT(pszRegName);
|
|
if (!pszRegName)
|
|
// command line not complete
|
|
return 1;
|
|
|
|
LPSTR pszPathName = strchr(pszRegName, ',');
|
|
if (pszPathName)
|
|
{
|
|
SKIPSPACES(pszPathName);
|
|
}
|
|
STRINGOP(strncpy, szRegKey, pszRegName/*argv[2]*/);
|
|
if (LPSTR pszEndRegName = strchr(szRegKey, ','))
|
|
*pszEndRegName = '\0';
|
|
STRINGOP(strncpy, szRegInstalling, szRegKey/*argv[2]*/);
|
|
STRINGOP(strncat , szRegInstalling, "\\InstallingClient");
|
|
RefCount.ValueGet(szRegInstalling, "Path", (LPBYTE *)&pszAppPath, &dwValueSize);
|
|
dwValueSize = sizeof(sz_Application);
|
|
RefCount.ValueGet(szRegInstalling, "Application", (LPBYTE *)&pszApplication, &dwValueSize);
|
|
dwValueSize = sizeof(BOOL);
|
|
RefCount.ValueGet(szRegInstalling, "MultiInstall", (LPBYTE *)&pbInstallMode, &dwValueSize);
|
|
if (pszAppPath && ((pbInstallMode && bMultiInstall) || !STRINGOPL(_strnicmp, "CopyToClient", lpCmdLine/*argv[1]*/)))
|
|
{
|
|
STRINGOP(strncat, pszAppPath, "\\");
|
|
STRINGOP(strncpy, sz_Dir, pszAppPath);
|
|
STRINGOP(strncat, sz_AppPath, sz_Application);
|
|
}
|
|
else
|
|
STRINGOP(strncpy, sz_AppPath, sz_Application);
|
|
|
|
// FInd the path in InstalledClients
|
|
STRINGOP(strncpy, szRegInstalled, szRegKey/*argv[2]*/);
|
|
STRINGOP(strncat, szRegInstalled, "\\InstalledClients");
|
|
|
|
char szTmp[MAX_PATH];
|
|
strcpy(szTmp, pszPathName);
|
|
char* x = strchr(szTmp, ',');
|
|
char szGUID[MAX_PATH];
|
|
char* pszGUID = NULL;
|
|
|
|
if( x )
|
|
{
|
|
// IE passed component guid so we need to check...
|
|
strcpy(szGUID, x);
|
|
*x = '\0';
|
|
strcpy(pszPathName, szTmp);
|
|
|
|
// now szGuid = " , {aab-cc-dd-ee}", need to stript white space and ','
|
|
pszGUID = szGUID;
|
|
for( int i = 0; i < MAX_PATH; i++)
|
|
{
|
|
if( *pszGUID != ' ' && *pszGUID != ',')
|
|
break;
|
|
pszGUID++;
|
|
}
|
|
if( i == MAX_PATH || *pszGUID == '\0' )
|
|
{
|
|
pszGUID = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
if (!STRINGOPL(_strnicmp, "CopyToClient", lpCmdLine/*argv[1]*/))
|
|
{
|
|
_ASSERT(pszPathName);
|
|
if (!pszPathName)
|
|
return 2;
|
|
else
|
|
{
|
|
LPSTR pszDestSubDir = strchr(pszPathName, ',');
|
|
if (pszDestSubDir)
|
|
{
|
|
SKIPSPACES(pszDestSubDir);
|
|
STRINGOP(strncat, sz_Dir, pszDestSubDir);
|
|
STRINGOP(strncat, sz_Dir, "\\");
|
|
}
|
|
if (LPSTR pszPathNameEnd = strchr(pszPathName, ','))
|
|
*pszPathNameEnd = '\0';
|
|
// Copy files we need for Uninstall to the client location
|
|
STRINGOP(strncat, sz_Dir, pszPathName);
|
|
if (LPSTR pszDestDirEnd = strchr(sz_Dir, ','))
|
|
*pszDestDirEnd = '\0';
|
|
if (!CopyFile(pszPathName/*argv[3]*/, sz_Dir, FALSE))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
_ASSERTE(!dwError);
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
else if (!STRINGOPL(_strnicmp, "Copy", lpCmdLine/*argv[1]*/))
|
|
{
|
|
_ASSERT(pszPathName);
|
|
if (!pszPathName)
|
|
return 2;
|
|
else
|
|
{
|
|
LPSTR pszDestSubDir = strchr(pszPathName, ',');
|
|
if (pszDestSubDir)
|
|
{
|
|
SKIPSPACES(pszDestSubDir);
|
|
STRINGOP(strncpy, sz_Dir, pszDestSubDir);
|
|
}
|
|
if (LPSTR pszPathNameEnd = strchr(pszPathName, ','))
|
|
*pszPathNameEnd = '\0';
|
|
// Copy files we need for Uninstall to the client location
|
|
if (LPSTR pszDestDirEnd = strchr(sz_Dir, ','))
|
|
*pszDestDirEnd = '\0';
|
|
if (!CopyFile(pszPathName/*argv[3]*/, sz_Dir, FALSE))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
_ASSERTE(!dwError);
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
else if (!RefCount.ValueExist(szRegInstalled, sz_AppPath) && !STRINGOPL(_strnicmp, "Install", lpCmdLine/*argv[1]*/))
|
|
{
|
|
// Increment ref-count
|
|
if( pszGUID )
|
|
{
|
|
// some check needed...
|
|
// is the component installed?
|
|
HKEY hkInstalled = NULL;
|
|
char szKeyName[MAX_PATH];
|
|
strcpy(szKeyName, "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\");
|
|
strcat(szKeyName, pszGUID);
|
|
|
|
if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_ALL_ACCESS, &hkInstalled)
|
|
)
|
|
{
|
|
DWORD dwType = 0;
|
|
BYTE bValueData[16];
|
|
DWORD cValueData = sizeof(bValueData);;
|
|
if (ERROR_SUCCESS == RegQueryValueEx( hkInstalled, "IsInstalled", NULL, &dwType, bValueData, &cValueData))
|
|
{
|
|
if( *(LPDWORD)(bValueData) )
|
|
{
|
|
// this app has been installed, we need to do nothing... (do not perform refcount, just quit)
|
|
RegCloseKey(hkInstalled);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
RegCloseKey(hkInstalled);
|
|
}
|
|
}
|
|
|
|
// we are here because
|
|
// 1. no guid passed from cmd line
|
|
// 2. or component not installed (the RegQueryValue failed..)
|
|
// so we continue to do refcount...
|
|
|
|
RefCount.SetInstalFlag(TRUE);
|
|
}
|
|
else if (!RefCount.ValueExist(szRegInstalled, sz_AppPath) && !STRINGOPL(_strnicmp, "SetClient", lpCmdLine/*argv[1]*/))
|
|
{
|
|
// Set the app's installed flag
|
|
RefCount.ValueSet(szRegInstalled, sz_AppPath);
|
|
RegDeleteKey (HKEY_LOCAL_MACHINE, szRegInstalling); // we don't need it anymore
|
|
return 0;
|
|
}
|
|
else if (!STRINGOPL(_strnicmp, "Uninstall", lpCmdLine/*argv[1]*/))
|
|
{
|
|
// Decrement ref-count
|
|
RefCount.SetInstalFlag(FALSE);
|
|
}
|
|
else if (!STRINGOPL(_strnicmp, "ClearClient", lpCmdLine/*argv[1]*/))
|
|
{
|
|
// Remove the app's installed flag
|
|
RefCount.ValueClear(szRegInstalled, sz_AppPath);
|
|
RegDeleteKey(HKEY_LOCAL_MACHINE, szRegInstalling); // we don't need it anymore
|
|
return 0;
|
|
}
|
|
else if (!STRINGOPL(_strnicmp, "SetClient", lpCmdLine/*argv[1]*/))
|
|
{
|
|
// Subsequent Installation
|
|
RegDeleteKey(HKEY_LOCAL_MACHINE, szRegInstalling); // we don't need it anymore
|
|
return 0;
|
|
}
|
|
else
|
|
// Subsequent Installation
|
|
return 0;
|
|
|
|
HKEY hkRef; // address of handle to open key
|
|
DWORD dwDisposition; // address of disposition value buffer
|
|
LONG lRet;
|
|
|
|
lRet = RegCreateKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs",
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkRef, &dwDisposition);
|
|
_ASSERT(REG_OPENED_EXISTING_KEY == dwDisposition);
|
|
_ASSERT(ERROR_SUCCESS == lRet);
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
_ASSERT(pszPathName);
|
|
if (pszPathName)
|
|
{
|
|
RefCount.Change(pszPathName/*argv[3]*/, &hkRef);
|
|
if (RefCount.GetCount() <= 0)
|
|
{
|
|
_ASSERT(RefCount.GetCount() == 0);
|
|
//RegDeleteKey(HKEY_LOCAL_MACHINE, szRegInstalling); // we don't need it anymore
|
|
//RegDeleteKey(HKEY_LOCAL_MACHINE, szRegInstalled); // we don't need it anymore
|
|
//RegDeleteKey(HKEY_LOCAL_MACHINE, szRegKey); // we don't need it anymore
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkRef);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CRefCount::Change(char *szName, PHKEY phkRef)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
DWORD cValueName = 0;
|
|
DWORD dwType = 0;
|
|
BYTE bValueData[16];
|
|
DWORD cValueData = sizeof(bValueData);;
|
|
|
|
// Check if the conponent exits
|
|
if (ERROR_SUCCESS == RegQueryValueEx( *phkRef, szName, NULL, &dwType, bValueData, &cValueData))
|
|
{
|
|
// Found
|
|
_ASSERT(dwType == REG_DWORD);
|
|
m_dwRefCount = *(LPDWORD)(bValueData);
|
|
(m_fInstall) ? ++m_dwRefCount : --m_dwRefCount;
|
|
}
|
|
else if (!m_fInstall)
|
|
{
|
|
// Trying to Uninstall the component that was not ref-counted before
|
|
// Just delete it
|
|
// _ASSERT(m_fInstall);
|
|
if (!DeleteFile(szName))
|
|
{
|
|
if (!ReplaceFileOnReboot(szName, NULL))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
_ASSERTE(!dwError);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
// If not found, create new else just overwrite it.
|
|
*(LPDWORD)(bValueData) = m_dwRefCount;
|
|
if (m_dwRefCount == 0)
|
|
{
|
|
char szDllFullPath[MAX_PATH+1];
|
|
DWORD dwLen = 0;
|
|
dwLen = strlen(szName);
|
|
char* p = NULL;
|
|
if( dwLen <= MAX_PATH )
|
|
{
|
|
strcpy(szDllFullPath, szName);
|
|
for( int i = dwLen; i >= 0; i--)
|
|
{
|
|
if( szDllFullPath[i] == '\\' )
|
|
{
|
|
p = &(szDllFullPath[i+1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( p &&
|
|
!_stricmp(p, "msdapml.dll") &&
|
|
!_stricmp(p, "msonsext.dll") &&
|
|
!_stricmp(p, "ragent.tlb") &&
|
|
!_stricmp(p, "ragent.dll") &&
|
|
!_stricmp(p, "fp4autl.dll") &&
|
|
!_stricmp(p, "fp4anwi.dll")
|
|
) {
|
|
// Last rererence deleted
|
|
HINSTANCE hInst = LoadLibrary(szName);
|
|
FARPROC pDllUnregisterServer = NULL;
|
|
if (hInst && (pDllUnregisterServer = GetProcAddress(hInst, "DllUnregisterServer")))
|
|
{
|
|
pDllUnregisterServer();
|
|
}
|
|
else
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
}
|
|
|
|
FreeLibrary(hInst);
|
|
}
|
|
|
|
RegDeleteValue(*phkRef, szName);
|
|
|
|
if (!DeleteFile(szName))
|
|
{
|
|
if (!ReplaceFileOnReboot(szName, NULL))
|
|
{
|
|
DWORD dwError = GetLastError();
|
|
_ASSERTE(!dwError);
|
|
}
|
|
}
|
|
|
|
|
|
if( p && !_stricmp(p, "msonsext.dll") )
|
|
{
|
|
LONG lRet =0;
|
|
|
|
lRet = RegDeleteKey (HKEY_CLASSES_ROOT,"CLSID\\{BDEADF00-C265-11d0-BCED-00A0C90AB50F}");
|
|
lRet = RegDeleteKey (HKEY_CLASSES_ROOT,"CLSID\\{BDEADF04-C265-11d0-BCED-00A0C90AB50F}");
|
|
lRet = RegDeleteKey (HKEY_CLASSES_ROOT,"Publishing Folder");
|
|
lRet = RegDeleteKey (HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\NameSpace\\{BDEADF00-C265-11d0-BCED-00A0C90AB50F}");
|
|
|
|
HKEY hkRef = NULL;
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", 0, KEY_ALL_ACCESS, &hkRef);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
RegDeleteValue(hkRef, "{BDEADF00-C265-11d0-BCED-00A0C90AB50F}");
|
|
RegCloseKey(hkRef);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
RegSetValueEx(*phkRef, szName, 0, REG_DWORD, bValueData, sizeof(DWORD));
|
|
}
|
|
|
|
BOOL CRefCount::ValueExist(char *sz_RegSubkey, char *sz_RegValue)
|
|
{
|
|
HKEY hkRef = NULL; // address of handle to open key
|
|
LONG lRet =0;
|
|
BOOL fret = FALSE;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz_RegSubkey,
|
|
0, KEY_ALL_ACCESS, &hkRef);
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
lRet = RegQueryValueEx(hkRef, sz_RegValue, 0, NULL, NULL, NULL);
|
|
if (ERROR_SUCCESS != lRet)
|
|
fret = FALSE;
|
|
else
|
|
fret = TRUE;
|
|
}
|
|
RegCloseKey(hkRef);
|
|
return fret;
|
|
}
|
|
|
|
void CRefCount::ValueSet(char *sz_RegSubkey, char *sz_RegValue)
|
|
{
|
|
HKEY hkRef = NULL; // address of handle to open key
|
|
LONG lRet =0;
|
|
DWORD dwValiue = 1;
|
|
DWORD dwDisposition; // address of disposition value buffer
|
|
|
|
lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, sz_RegSubkey,
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkRef, &dwDisposition);
|
|
|
|
_ASSERT(ERROR_SUCCESS == lRet);
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
RegSetValueEx(hkRef, sz_RegValue, 0, REG_DWORD, (BYTE *)&dwValiue, sizeof(dwValiue));
|
|
}
|
|
}
|
|
|
|
void CRefCount::ValueGet(char *sz_RegSubkey, char *sz_ValueName, LPBYTE *p_Value, DWORD *pdwValueSize)
|
|
{
|
|
HKEY hkRef = NULL; // address of handle to open key
|
|
LONG lRet =0;
|
|
DWORD dwValiue = 1;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz_RegSubkey,
|
|
0, KEY_ALL_ACCESS, &hkRef);
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
*p_Value = NULL;
|
|
}
|
|
else
|
|
{
|
|
lRet = RegQueryValueEx(hkRef, sz_ValueName, 0, NULL, *p_Value, pdwValueSize);
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
*p_Value = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CRefCount::ValueClear(char *sz_RegSubkey, char *sz_RegValue)
|
|
{
|
|
HKEY hkRef = NULL; // address of handle to open key
|
|
LONG lRet =0;
|
|
DWORD dwValiue = 1;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz_RegSubkey,
|
|
0, KEY_ALL_ACCESS, &hkRef);
|
|
|
|
if (ERROR_SUCCESS != lRet)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
RegDeleteValue(hkRef, sz_RegValue);
|
|
}
|
|
}
|
|
|
|
BOOL PASCAL ReplaceFileOnReboot (LPCTSTR pszExisting, LPCTSTR pszNew)
|
|
{
|
|
// _ASSERT(FALSE);
|
|
// First, attempt to use the MoveFileEx function.
|
|
BOOL fOk = MoveFileEx(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT);
|
|
if (fOk) return(fOk);
|
|
|
|
// If MoveFileEx failed, we are running on Windows 95 and need to add
|
|
// entries to the WININIT.INI file (an ANSI file).
|
|
// Start a new scope for local variables.
|
|
{
|
|
char szRenameLine[1024];
|
|
TCHAR szExistingShort[_MAX_PATH];
|
|
|
|
GetShortPathName(pszExisting, szExistingShort, sizeof(szExistingShort) / sizeof(szExistingShort[0]));
|
|
int cchRenameLine = wsprintfA(szRenameLine,
|
|
#ifdef UNICODE
|
|
"%ls=%ls\r\n",
|
|
#else
|
|
"%hs=%hs\r\n",
|
|
#endif
|
|
(pszNew == NULL) ? __TEXT("NUL") : pszNew, szExistingShort);
|
|
char szRenameSec[] = "[Rename]\r\n";
|
|
int cchRenameSec = sizeof(szRenameSec) - 1;
|
|
HANDLE hfile, hfilemap;
|
|
DWORD dwFileSize, dwRenameLinePos;
|
|
TCHAR szPathnameWinInit[_MAX_PATH];
|
|
|
|
// Construct the full pathname of the WININIT.INI file.
|
|
GetWindowsDirectory(szPathnameWinInit, _MAX_PATH);
|
|
lstrcat(szPathnameWinInit, __TEXT("\\WinInit.Ini"));
|
|
|
|
// Open/Create the WININIT.INI file.
|
|
hfile = CreateFile(szPathnameWinInit,
|
|
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
|
|
if (hfile == INVALID_HANDLE_VALUE)
|
|
return(fOk); // It is still FALSE
|
|
|
|
// Create a file mapping object that is the current size of
|
|
// the WININIT.INI file plus the length of the additional string
|
|
// that we're about to insert into it plus the length of the section
|
|
// header (which we might have to add).
|
|
dwFileSize = GetFileSize(hfile, NULL);
|
|
hfilemap = CreateFileMapping(hfile, NULL, PAGE_READWRITE, 0,
|
|
dwFileSize + cchRenameLine + cchRenameSec, NULL);
|
|
|
|
if (hfilemap != NULL) {
|
|
|
|
// Map the WININIT.INI file into memory. Note: The contents
|
|
// of WININIT.INI are always ANSI; never Unicode.
|
|
LPSTR pszWinInit = (LPSTR) MapViewOfFile(hfilemap,
|
|
FILE_MAP_WRITE, 0, 0, 0);
|
|
pszWinInit[dwFileSize] = 0; // Make sure it is null terminated. Yury
|
|
|
|
if (pszWinInit != NULL) {
|
|
|
|
// Search for the [Rename] section in the file.
|
|
LPSTR pszRenameSecInFile = strstr(pszWinInit, szRenameSec);
|
|
|
|
if (pszRenameSecInFile == NULL) {
|
|
|
|
// There is no [Rename] section in the WININIT.INI file.
|
|
// We must add the section too.
|
|
dwFileSize += wsprintfA(&pszWinInit[dwFileSize], "%s",
|
|
szRenameSec);
|
|
dwRenameLinePos = dwFileSize;
|
|
|
|
} else {
|
|
|
|
// We found the [Rename] section, shift all the lines down
|
|
PSTR pszFirstRenameLine = strchr(pszRenameSecInFile, '\n');
|
|
// Shift the contents of the file down to make room for
|
|
// the newly added line. The new line is always added
|
|
// to the top of the list.
|
|
pszFirstRenameLine++; // 1st char on the next line
|
|
memmove(pszFirstRenameLine + cchRenameLine, pszFirstRenameLine,
|
|
pszWinInit + dwFileSize - pszFirstRenameLine);
|
|
dwRenameLinePos = pszFirstRenameLine - pszWinInit;
|
|
}
|
|
|
|
// Insert the new line
|
|
memcpy(&pszWinInit[dwRenameLinePos], szRenameLine, cchRenameLine);
|
|
|
|
UnmapViewOfFile(pszWinInit);
|
|
|
|
// Calculate the true, new size of the file.
|
|
dwFileSize += cchRenameLine;
|
|
|
|
// Everything was successful.
|
|
fOk = TRUE;
|
|
}
|
|
CloseHandle(hfilemap);
|
|
}
|
|
|
|
// Force the end of the file to be the calculated, new size.
|
|
SetFilePointer(hfile, dwFileSize, NULL, FILE_BEGIN);
|
|
SetEndOfFile(hfile);
|
|
|
|
CloseHandle(hfile);
|
|
}
|
|
|
|
return(fOk);
|
|
}
|
|
|